diff --git a/pull/astral/00018/public.yaml b/pull/astral/00018/public.yaml
new file mode 100644
index 0000000..b66401b
--- /dev/null
+++ b/pull/astral/00018/public.yaml
@@ -0,0 +1,1249 @@
+openapi: 3.1.0
+info:
+ version: 1.2.2-oas3.1
+ title: Ankorstore Stock Tracking and Logistics API
+ summary: API specification for the Ankorstore Stock Tracking and Logistics system
+ description: Ankorstore Stock Tracking and Logistics (ASTRAL) API specification
+ contact:
+ name: Ankorstore
+ url: https://www.ankorstore.com
+ email: api@ankorstore.com
+ license:
+ url: https://creativecommons.org/publicdomain/zero/1.0/
+ name: CC0 1.0 Universal
+servers:
+ - url: http://www.ankorlocal.com:8000
+ description: Local Development Server
+ - url: https://www.preprod.ankorstore.com
+ description: Staging Environment
+ - url: https://www.ankorstore.com
+ description: Prod Environment
+paths:
+ /api/astral/v1/stock/state:
+ get:
+ tags:
+ - State
+ summary: Stock quantities by location and status
+ description: |
+ Return the current quantity for a given product variant across locations, statuses and potentially lots.
+ One stock state entity is returned per product variant, so the identifier of each entity will correspond with
+ the product variant identifier for which quantities are returned.
+ operationId: list-state
+ parameters:
+ - $ref: '#/components/parameters/acceptInHeader'
+ - $ref: '#/components/parameters/xAksBrandUuidHeader'
+ - $ref: '#/components/parameters/xAksRetailerUuidHeader'
+ - $ref: '#/components/parameters/productVariantIdFilter'
+ - $ref: '#/components/parameters/statusFilter'
+ - $ref: '#/components/parameters/locationTypeFilter'
+ - $ref: '#/components/parameters/locationIdFilter'
+ - $ref: '#/components/parameters/pageLimit'
+ - $ref: '#/components/parameters/pageBefore'
+ - $ref: '#/components/parameters/pageAfter'
+ - $ref: '#/components/parameters/stateAt'
+ responses:
+ default: {$ref: "#/components/responses/ErrorResponse"}
+ "200": {$ref: "#/components/responses/StockStateCollectionResponse"}
+ /api/astral/v1/stock/postings:
+ get:
+ tags:
+ - Movements
+ summary: List postings
+ description: |
+ Returns movement history for a set of product variants and locations, based on the provided filters.
+ To receive information on which specific lots were involved in the movement, include the `lot` resource. You
+ may also include the transaction resource to get more information on what caused the posting.
+ operationId: list-postings
+ parameters:
+ - $ref: '#/components/parameters/acceptInHeader'
+ - $ref: '#/components/parameters/xAksBrandUuidHeader'
+ - $ref: '#/components/parameters/xAksRetailerUuidHeader'
+ - $ref: '#/components/parameters/productVariantIdFilter'
+ - $ref: '#/components/parameters/locationTypeFilter'
+ - $ref: '#/components/parameters/locationIdFilter'
+ - $ref: '#/components/parameters/locationStatusFilter'
+ - $ref: '#/components/parameters/pageLimit'
+ - $ref: '#/components/parameters/pageBeforeUuidTimestamp'
+ - $ref: '#/components/parameters/pageAfterUuidTimestamp'
+ - name: sort
+ in: query
+ description: Specify what to sort by
+ required: false
+ allowEmptyValue: false
+ schema:
+ type: string
+ enum:
+ - transaction.createdAt
+ - '-transaction.createdAt'
+ - name: filter[movementType][in][]
+ in: query
+ description: Include only specific movement types
+ required: false
+ schema:
+ type: array
+ items: {$ref: '#/components/schemas/MovementType'}
+ - name: filter[movementType][notIn][]
+ in: query
+ description: Exclude specific movement types
+ required: false
+ schema:
+ type: array
+ items: {$ref: '#/components/schemas/MovementType'}
+ - name: include
+ in: query
+ description: >-
+ A comma-separated list of resources to include. Options are transaction, lot
+ schema:
+ type: string
+ responses:
+ default: {$ref: "#/components/responses/ErrorResponse"}
+ "200": {$ref: "#/components/responses/PostingCollectionResponse"}
+ /api/astral/v1/stock/transactions:
+ get:
+ tags:
+ - Movements
+ summary: List transactions
+ description: |
+ Returns transaction history for a set of product variants and locations, based on the provided filters.
+ Filters include relatedId, which is typically filled with the masterOrderUuid, fulfillmentOrderUuid or in case
+ of reservations, a user-specified identifier. You may also include the posting resource to get the individual
+ postings contained within the transaction(s).
+ operationId: list-transactions
+ parameters:
+ - $ref: '#/components/parameters/acceptInHeader'
+ - $ref: '#/components/parameters/xAksBrandUuidHeader'
+ - $ref: '#/components/parameters/xAksRetailerUuidHeader'
+ - $ref: '#/components/parameters/productVariantIdFilter'
+ - $ref: '#/components/parameters/locationTypeFilter'
+ - $ref: '#/components/parameters/locationIdFilter'
+ - $ref: '#/components/parameters/locationStatusFilter'
+ - $ref: '#/components/parameters/pageLimit'
+ - $ref: '#/components/parameters/pageBeforeUuidTimestamp'
+ - $ref: '#/components/parameters/pageAfterUuidTimestamp'
+ - name: filter[relatedIds][]
+ in: query
+ description: A set of related identifiers to fetch transactions for
+ required: false
+ schema:
+ type: array
+ minItems: 1
+ items:
+ type: string
+ - name: sort
+ in: query
+ description: Specify what to sort by
+ required: false
+ allowEmptyValue: false
+ schema:
+ type: string
+ enum:
+ - createdAt
+ - '-createdAt'
+ - name: include
+ in: query
+ description: 'A comma-separated list of resources to include. Options are: posting'
+ schema:
+ type: string
+ responses:
+ default: {$ref: "#/components/responses/ErrorResponse"}
+ "200": {$ref: "#/components/responses/TransactionCollectionResponse"}
+ /api/astral/v1/stock/locations:
+ get:
+ tags:
+ - Locations
+ summary: List locations
+ description: Return the list of available locations
+ operationId: list-locations
+ parameters:
+ - $ref: '#/components/parameters/acceptInHeader'
+ - $ref: '#/components/parameters/xAksBrandUuidHeader'
+ - $ref: '#/components/parameters/xAksRetailerUuidHeader'
+ - $ref: '#/components/parameters/locationTypeFilter'
+ - $ref: '#/components/parameters/externalIdFilter'
+ - $ref: '#/components/parameters/pageLimit'
+ - $ref: '#/components/parameters/pageBefore'
+ - $ref: '#/components/parameters/pageAfter'
+ responses:
+ default: {$ref: "#/components/responses/ErrorResponse"}
+ "200": {$ref: "#/components/responses/LocationCollectionResponse"}
+tags:
+ - name: How to work with the Ankorstore Stock Tracking and Logistics API
+ description: "ℹ️ This section provides an overview of the general concepts and conventions used throughout the API.\n\n### API Specification\nThis API follows the [Ankorstore API Specification](https://api-spec.ankorstore.com) which is based on the [JSON:API](https://jsonapi.org/) specification.\n\n### Headers\nWhen making any request, the header `Accept: application/vnd.api+json` is required.\nWhen sending JSON within the body of a request the header `Content-Type: application/vnd.api+json` is also required.\n\n\U0001F517 [Learn more about JSON:API media types](https://jsonapi.org/format/#jsonapi-media-type)\n\n### Resource Data\nIn every response, the actual resource data can be found in the root level object `data`, this will either be an array\nor an object, depending on if its list based or not.\n\n\U0001F517 [Learn more about JSON:API document structure](https://jsonapi.org/format/#document-structure)\n\n### Includes\nResources may have the ability to include data from other relations in the same request.\nFor example, when fetching a single posting you may include the related transaction and lots\n\n`?include=transaction,lots`\n\n
\n\n### Pagination\nAnkorstore uses cursor based pagination. In the root level object for pagination supported endpoints\nyou will find a `meta` object containing pagination information:\n\n```yaml json_schema\n type: object\n description: Meta\n properties:\n meta:\n type: object\n description: Meta with Pagination Details\n properties:\n page:\n description: Cursor pagination details\n type: object\n properties:\n from:\n type: string\n to:\n type: string\n hasMore:\n type: boolean\n perPage:\n type: integer\n```\n\nAs an example:\n\n```json\n{\n \"meta\": {\n \"page\": {\n \"from\": \"63e9bacd-0288-4cf1-81ab-b34270c7f68a\",\n \"to\": \"747a1dcd-decc-4f8d-a9a9-61ff4d33d92e\",\n \"hasMore\": true,\n \"perPage\": 15\n }\n }\n}\n```\n\nYou may manually construct the pagination query parameters yourself using `page[limit]` with `page[before]`\nor `page[after]` depending on which direction you wish to iterate over.\n\n
\n\n#### Effective pagination\n\nWe recommend using the provided helper pagination links below instead of manually constructing the URLs yourself.\n\n
\n\nThe response will also provide pagination links, so you do not need to construct these yourself:\n\n```yaml json_schema\n type: object\n description: Links\n properties:\n links:\n description: Pagination navigation links. If a link does not exist then you cannot paginate any further in that direction.\n type: object\n properties:\n first:\n type: string\n format: url\n next:\n type: string\n format: url\n prev:\n type: string\n format: url\n```\n\nAs an example:\n\n```json\n{\n \"links\": {\n \"first\": \"https://www.ankorstore.com/api/astral/v1/postings?page%5Blimit%5D=15\",\n \"next\": \"https://www.ankorstore.com/api/astral/v1/postings?page%5Bafter%5D=1189606a-139e-4b4e-917c-b0c992498bad&page%5Blimit%5D=15\",\n \"prev\": \"https://www.ankorstore.com/api/astral/v1/postings?page%5Bbefore%5D=e04e17bb-9e70-4ecd-a8f5-4417d45b872c&page%5Blimit%5D=15\"\n }\n}\n```\n\n\U0001F517 [Learn more about JSON:API pagination](https://jsonapi.org/format/#fetching-pagination)\n\n### Filters\n\nAn endpoint that supports filters requires each listed filter to be wrapped in a filter object.\nE.g. you may wish to only retrieve stock quantities for a given status:\n\n`?filter[status][]=available`\n\nYou may chain filters as well:\n\n`?filter[status][]=available&filter[locationIds][]=1189606a-572e-4b4e-88da-b0c992498bad`\n\n
\n\n#### What filters can be used?\n\nThe supported filters will be listed on each endpoint in the API documentation.\n\n
\n\n\U0001F517 [Learn more about JSON:API filters](https://jsonapi.org/format/#fetching-filtering)"
+ - name: Authentication
+ description: |+
+ ℹ️ The Ankorstore API uses OAuth2 authentication, in order to get a `client_id` and a `client_secret` please,
+ login at https://www.ankorstore.com/ and generate a new application
+ in the [integrations](https://ankorstore.com/account/integrations) area of your account.
+
+ To generate a token pass in your `client_id` and `client_secret`:
+
+ ```json http
+ {
+ "method": "post",
+ "headers": {
+ "accept": "application/json",
+ "Content-Type": "application/x-www-form-urlencoded"
+ },
+ "baseUrl": "https://www.ankorstore.com",
+ "url": "/oauth/token",
+ "body": "grant_type=client_credentials&client_id={{client_id}}&client_secret={{client_secret}}&scope=*"
+ }
+ ```
+
+ You will receive an `access_token`:
+
+ ```json
+ {
+ "token_type": "Bearer",
+ "expires_in": 3600,
+ "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9<...>"
+ }
+ ```
+
+ This access token has an expiry, in which you will receive an `401 Unauthenticated` response. To generate a new one
+ you can re-call the `/oauth/token` endpoint described above.
+
+ To authenticate with every other endpoint pass in the header `Authorization: Bearer {token}`.
+ You can test if your token is working with this endpoint (this is a not a JSON:API based endpoint):
+
+ ```json http
+ {
+ "method": "get",
+ "headers": {
+ "accept": "application/json",
+ "Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9<...>"
+ },
+ "baseUrl": "https://www.ankorstore.com",
+ "url": "/api/v1/me"
+ }
+ ```
+
+ If successful you will receive a 200 response:
+
+ ```json
+ {
+ "data": {
+ "type": "user",
+ "id": 1234,
+ "email": "api@ankorstore.com",
+ "first_name": "Test",
+ "last_name": "Account",
+ "created_at": "2020-01-28T11:26:35+00:00",
+ "updated_at": "2022-03-15T15:23:09+00:00"
+ }
+ }
+ ```
+
+ - name: Stock Concepts
+ description: |-
+ ℹ️ This section defines the various concepts and entities used in the API.
+
+ ### Product variants
+ Product variants are entities that can be sold via the Ankorstore Marketplace and/or fulfilled via Ankorstore logistics.
+ They are the primary entity that other systems can use to interact with the stock API
+
+ ### Batches & Units
+ Batches represent a physically pickable entity, used as the indivisible quantity for all matters stock tracking.
+ Unless specified otherwise, any quantity in the ASTRAL API will be the number of batches.
+
+ Units describe how many individual units are contained within a batch. It may be used for informational purposes
+ by the marketplace, but all stock movement tracking is primarily done with batches.
+
+ ### Bundles
+ A product variant may be composed of several other product variants. These are called bundles. Within a bundle, each
+ product variant contained will have a multiplier to indicate how many batches are contained within the bundle.
+
+ When stock for a bundle is reserved, the stock of each individual product variant contained within the bundle is
+ decremented accordingly.
+
+ ### Lots
+ A lots refers to a specific quantity of items that are produced, stored, or shipped together and identified with
+ a lot number. An item may have many lots, and each lot is uniquely identified by a lot number + an optional expiry date.
+
+ When reserving stock, you may specify a lot number and expiry date to obtain stock from that specific lot.
+ If you do not specify a lot number, and the item has lots attached, the system will automatically select the lot
+ with the earliest expiry date.
+
+ ## Movements
+ Ankorstore maintains a double-entry ledger for stock tracking, meaning that for each stock change on a target there
+ must be an equal and opposite entry on the source.
+
+ Movements may be between physical locations, such as a warehouse and retailer, or between virtual stock statuses,
+ such as available and reserved.
+
+ ### Postings
+ Each single stock quantity change on a specific location and status is represented as a Posting, with a movementType
+ to describe the reason of the change. Postings are considered immutable, forming an accounting-equivalent record of
+ the full stock history.
+
+ ### Transactions
+ Transactions represent a single trigger or event that initiated a set of stock changes, and group together a set of
+ postings with a timestamp, external identifiers and potentially metadata. Examples include a order reservation,
+ order shipment, or location snapshot
+
+ ## Stock state
+ A stock state represents the current "balance", the quantity for a given product variant across locations, statuses
+ and potentially lots. It may show for example, how many batches are currently `available` at a given `warehouse`
+ for each lot of a `product variant` X.
+
+ Stock state is always grouped per product variant, so the identifier for stock-state entities corresponds with the
+ product variant ID for which quantities are shown.
+
+ ### Location & Stock statuses
+ Ankorstore maintains 2 concepts of status; location status represents a physical or virtual ledger of stock, while
+ stock status represents a status for which a balance can be maintained.
+
+ A stock status may be a super-set of location status, such as onHand, which is the super-set of available, reserved
+ blocked, damaged and qualityControl. Conversely, some location statuses may be tracked without being exposed
+ as stock status
+
+ | State | Description | Location status | Stock status | |
+ |----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------|--------------|---|
+ | available | Inventory that is considered available for orders or fulfillment | yes | yes | |
+ | onHand | Inventory that is present at a location. This is a sum of available, reserved, damaged, qualityControl and blocked | no | yes | |
+ | reserved | Inventory that are set aside, and currently not available for orders or fulfillment | yes | yes | |
+ | damaged | Inventory that is damaged, and thus no longer available for orders or fulfillment | yes | yes | |
+ | qualityControl | Inventory that is set aside for inspection, and thus no longer available for orders or fulfillment | yes | yes | |
+ | blocked | Inventory that is blocked for any reason other than damage or inspection, and thus no longer available for orders or fulfillment. For example: expired | yes | yes | |
+ | incoming | Inventory that is expected but not yet physically present at the location | yes | yes | |
+ | void | Wildcard location to source (temporarily) unexplained movements to and from | yes | no | |
+
+ ## Reservations
+ Reservations are a specific type of transaction that represent a temporary allocation of stock. A reservation may only
+ be created when the stock balances in status `available` is higher than the requested quantities, and will move the
+ requested quantities of stock from the `available` status to the `reserved` status within the same location.
+
+
+
+ ### Postings
+ Postings are always linked to items, and each item must be linked to at least one "single" product variant. So the
+ Postings endpoint will return movements for "single" product variants only. If a bundle is specified, movements
+ should be returned for all single product variants contained within the bundle.
+
+ ### Stock state
+ Stock states can represent either a single product variant or a bundle. If a bundle is specified, the quantities
+ in the stock state should be computed as the largest possible common denominator of the contained single product
+ variants.
+
+ Example: consider a bundle BX containing `10 x PY` + `5 x PZ`, with the stock state for A being `30` and B being `10`.
+ Then the stock state for BX will be `2`, as PZ `10 / 5 = 2` defines the available number of complete bundles.
+ - name: State
+ - name: Reservations
+ - name: Locations
+ - name: Movements
+components:
+ requestBodies:
+ StockReservationRequest:
+ content:
+ application/vnd.api+json:
+ schema:
+ type: object
+ properties:
+ data: {$ref: '#/components/schemas/StockReservation'}
+ required:
+ - data
+ examples:
+ example-create-order-reservation:
+ value:
+ data:
+ type: reservation
+ id: 1ed86ab7-c16e-6002-b4d0-0242ac15000c
+ attributes:
+ items:
+ - productVariantId: 0f358c35-9698-46f4-8856-d0441e0533e5
+ quantity: 10
+ locationId: 0fba0067-87cb-4e36-9885-2529eb0475cc
+ - productVariantId: 0f358c35-9698-46f4-8856-d0441e0533e5
+ quantity: 5
+ locationId: 0fba0067-87cb-4e36-9885-2529eb0475cc
+ lotNumber: lot-abc
+ relatedId: 7326952d-383a-496b-ad8c-63a2517c0dbd
+ metadata:
+ masterOrderId: 7326952d-383a-496b-ad8c-63a2517c0dbd
+ LocationRequest:
+ content:
+ application/vnd.api+json:
+ schema:
+ type: object
+ properties:
+ data: {$ref: '#/components/schemas/LocationResource'}
+ required:
+ - data
+ examples:
+ example-create-location:
+ value:
+ data:
+ type: location
+ id: 38cbe75a-9e3c-4adc-a465-351625a88c3f
+ attributes:
+ externalId: 1841c9e9-33cc-4fd5-8045-32654adcc78a
+ type: warehouse
+ securitySchemes:
+ CookieKey:
+ type: apiKey
+ name: ankorstore_session
+ in: cookie
+ responses:
+ NoContent: # 201
+ description: No content
+ ErrorResponse:
+ description: Example response
+ content:
+ application/vnd.api+json:
+ schema:
+ type: object
+ properties:
+ errors:
+ type: array
+ items: {$ref: '#/components/schemas/Error'}
+ jsonapi: {$ref: '#/components/schemas/jsonapi'}
+ required:
+ - errors
+ StockStateCollectionResponse:
+ description: Set of stock state records
+ content:
+ application/vnd.api+json:
+ schema:
+ type: object
+ properties:
+ data:
+ type: array
+ items: {$ref: '#/components/schemas/ProductVariantStockStateResource'}
+ jsonapi: {$ref: '#/components/schemas/jsonapi'}
+ meta: {$ref: '#/components/schemas/paginationMeta'}
+ links: {$ref: '#/components/schemas/paginationLinks'}
+ required:
+ - data
+ - jsonapi
+ examples:
+ example-get-stock-quantities:
+ value:
+ data:
+ - type: 'stock-state'
+ id: 1ed86ab7-c16e-6002-b4d0-0242ac15000c
+ attributes:
+ quantities:
+ - quantity: 10
+ locationId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
+ status: 'available'
+ lot:
+ lotNumber: 'lot-20240915-a'
+ expiryDate: "2024-09-15"
+ - quantity: 7
+ locationId: 0f358c35-9698-46f4-8856-d0441e0533e5
+ status: 'reserved'
+ lot:
+ lotNumber: 'lot-20240915-a'
+ expiryDate: "2024-09-15"
+ - quantity: 3
+ locationId: 0f358c35-9698-46f4-8856-d0441e0533e5
+ status: 'reserved'
+ - quantity: 2
+ locationId: 0f358c35-9698-46f4-8856-d0441e0533e5
+ status: 'blocked'
+ lot:
+ lotNumber: 'lot-20231215-x'
+ expiryDate: "2023-12-15"
+ - type: 'stock-state'
+ id: 018fc37c-d9bc-7a25-96e0-9c80c843b6ea
+ attributes:
+ quantities:
+ - quantity: 5
+ locationId: 018fc37e-4460-7b27-8151-ee7422b71f2e
+ status: 'incoming'
+ lot:
+ lotNumber: 'lot-without-expiry'
+ - quantity: 7
+ locationId: 0f358c35-9698-46f4-8856-d0441e0533e5
+ status: 'available'
+ lot:
+ lotNumber: 'lot-without-expiry'
+ jsonapi:
+ version: string
+ meta: {}
+ LocationCollectionResponse:
+ description: Set of locations
+ content:
+ application/vnd.api+json:
+ schema:
+ type: object
+ properties:
+ data:
+ type: array
+ items: {$ref: '#/components/schemas/LocationResource'}
+ jsonapi: {$ref: '#/components/schemas/jsonapi'}
+ meta: {$ref: '#/components/schemas/paginationMeta'}
+ links: {$ref: '#/components/schemas/paginationLinks'}
+ required:
+ - data
+ - jsonapi
+ LocationResponse:
+ description: A single location
+ content:
+ application/vnd.api+json:
+ schema:
+ type: object
+ properties:
+ data: {$ref: '#/components/schemas/LocationResource'}
+ jsonapi: {$ref: '#/components/schemas/jsonapi'}
+ required:
+ - data
+ - jsonapi
+ PostingCollectionResponse:
+ description: Set of postings
+ content:
+ application/vnd.api+json:
+ schema: {$ref: '#/components/schemas/PostingCollection'}
+ examples:
+ example-get-postings-simple:
+ value:
+ data:
+ - type: 'posting'
+ id: 018fc37f-5c0a-7913-a672-9569d7b48756
+ attributes:
+ locationId: 20e62581-67a5-4166-8b1f-344e9b06b58b
+ productVariantId: 018fc380-1c43-75f9-a101-49447fbadeb7
+ locationStatus: available
+ movementType: 'order_reserved'
+ quantity: -10
+ unitMultiplier: 1
+ - type: 'posting'
+ id: 018fc385-5d99-7305-9cf5-a18b40005fbc
+ attributes:
+ locationId: 20e62581-67a5-4166-8b1f-344e9b06b58b
+ productVariantId: 018fc380-1c43-75f9-a101-49447fbadeb7
+ locationStatus: reserved
+ movementType: 'order_reserved'
+ quantity: 10
+ unitMultiplier: 1
+ example-get-postings-with-relations:
+ value:
+ data:
+ - type: 'posting'
+ id: 018fc386-3078-75b3-8e75-6bed4e01c144
+ attributes:
+ locationId: 20e62581-67a5-4166-8b1f-344e9b06b58b
+ productVariantId: 018fc380-1c43-75f9-a101-49447fbadeb7
+ locationStatus: incoming
+ movementType: 'replenishment'
+ quantity: -227
+ unitMultiplier: 2
+ relationships:
+ transaction:
+ data:
+ type: 'transaction'
+ id: 018fc399-3240-78b2-abfa-e8c5df1c304f
+ - type: 'posting'
+ id: 018fc386-4c76-76cf-9319-533c7dd9b66c
+ attributes:
+ locationId: 20e62581-67a5-4166-8b1f-344e9b06b58b
+ productVariantId: 018fc380-1c43-75f9-a101-49447fbadeb7
+ locationStatus: available
+ movementType: 'replenishment'
+ quantity: 200
+ unitMultiplier: 2
+ relationships:
+ transaction:
+ data:
+ type: 'transaction'
+ id: 018fc399-3240-78b2-abfa-e8c5df1c304f
+ lot:
+ data:
+ type: 'lot'
+ id: 018fc3b2-5e37-7b07-986b-7bbcee3c9243
+ - type: 'posting'
+ id: 018fc3d3-cd9b-7c96-9b29-fd90bf0eff7b
+ attributes:
+ locationId: 20e62581-67a5-4166-8b1f-344e9b06b58b
+ productVariantId: 018fc380-1c43-75f9-a101-49447fbadeb7
+ locationStatus: available
+ movementType: 'replenishment'
+ quantity: 24
+ unitMultiplier: 2
+ relationships:
+ transaction:
+ data:
+ type: 'transaction'
+ id: 018fc399-3240-78b2-abfa-e8c5df1c304f
+ lot:
+ data:
+ type: 'lot'
+ id: 018fc3b1-43af-7103-bfb9-2947ba73c264
+ - type: 'posting'
+ id: 018fc388-467e-7e9f-9745-0d2feb2b7b51
+ attributes:
+ locationId: 20e62581-67a5-4166-8b1f-344e9b06b58b
+ productVariantId: 018fc380-1c43-75f9-a101-49447fbadeb7
+ locationStatus: blocked
+ movementType: 'replenishment_mismatch'
+ quantity: 3
+ unitMultiplier: 2
+ relationships:
+ transaction:
+ data:
+ type: 'transaction'
+ id: 018fc399-3240-78b2-abfa-e8c5df1c304f
+ lot:
+ data:
+ type: 'lot'
+ id: 018fc3b1-43af-7103-bfb9-2947ba73c264
+ included:
+ - type: 'transaction'
+ id: 018fc399-3240-78b2-abfa-e8c5df1c304f
+ attributes:
+ relatedId: R_8P1P1LAX_681
+ createdAt: '2024-05-29T09:07:26.339Z'
+ metadata:
+ webhookId: 018fc39b-6248-7aa6-a8ed-3b1b86a2628e
+ - type: 'lot'
+ id: 018fc3b1-43af-7103-bfb9-2947ba73c264
+ attributes:
+ number: lot-X
+ expiryDate: '2025-01-01'
+ - type: 'lot'
+ id: 018fc3b2-5e37-7b07-986b-7bbcee3c9243
+ attributes:
+ number: lot-Y
+ expiryDate: '2025-02-02'
+ TransactionCollectionResponse:
+ description: Set of transactions
+ content:
+ application/vnd.api+json:
+ schema: {$ref: '#/components/schemas/TransactionCollection'}
+ examples:
+ example-get-transactions-simple:
+ value:
+ data:
+ - type: 'transaction'
+ id: 018fc3cd-80d9-7c27-ba48-d5e4e0cba379
+ attributes:
+ relatedId: 0408720a-5a88-434c-82c2-36a0e015bba6
+ createdAt: '2024-05-28T09:07:26.339Z'
+ metadata:
+ transition: submitted
+ masterOrderUuid: 0408720a-5a88-434c-82c2-36a0e015bba6
+ - type: 'transaction'
+ id: 018fc3cf-2b19-7392-ba9a-37114eaaba6c
+ attributes:
+ relatedId: 0408720a-5a88-434c-82c2-36a0e015bba6
+ createdAt: '2024-05-29T13:07:26.339Z'
+ metadata:
+ transition: shipped
+ masterOrderUuid: 0408720a-5a88-434c-82c2-36a0e015bba6
+ example-get-transactions-with-relations:
+ value:
+ data:
+ - type: 'transaction'
+ id: 018fc399-3240-78b2-abfa-e8c5df1c304f
+ attributes:
+ relatedId: R_8P1P1LAX_681
+ createdAt: '2024-05-29T09:07:26.339Z'
+ metadata:
+ webhookId: 018fc39b-6248-7aa6-a8ed-3b1b86a2628e
+ relationships:
+ postings:
+ data:
+ - type: 'posting'
+ id: 018fc386-3078-75b3-8e75-6bed4e01c144
+ - type: 'posting'
+ id: 018fc386-4c76-76cf-9319-533c7dd9b66c
+ - type: 'posting'
+ id: 018fc3d3-cd9b-7c96-9b29-fd90bf0eff7b
+ - type: 'posting'
+ id: 018fc388-467e-7e9f-9745-0d2feb2b7b51
+ included:
+ - type: 'posting'
+ id: 018fc386-3078-75b3-8e75-6bed4e01c144
+ attributes:
+ locationId: 20e62581-67a5-4166-8b1f-344e9b06b58b
+ productVariantId: 018fc380-1c43-75f9-a101-49447fbadeb7
+ locationStatus: incoming
+ movementType: 'replenishment'
+ quantity: -227
+ unitMultiplier: 2
+ - type: 'posting'
+ id: 018fc386-4c76-76cf-9319-533c7dd9b66c
+ attributes:
+ locationId: 20e62581-67a5-4166-8b1f-344e9b06b58b
+ productVariantId: 018fc380-1c43-75f9-a101-49447fbadeb7
+ locationStatus: available
+ movementType: 'replenishment'
+ quantity: 200
+ unitMultiplier: 2
+ - type: 'posting'
+ id: 018fc3d3-cd9b-7c96-9b29-fd90bf0eff7b
+ attributes:
+ locationId: 20e62581-67a5-4166-8b1f-344e9b06b58b
+ productVariantId: 018fc380-1c43-75f9-a101-49447fbadeb7
+ locationStatus: available
+ movementType: 'replenishment'
+ quantity: 24
+ unitMultiplier: 2
+ - type: 'posting'
+ id: 018fc388-467e-7e9f-9745-0d2feb2b7b51
+ attributes:
+ locationId: 20e62581-67a5-4166-8b1f-344e9b06b58b
+ productVariantId: 018fc380-1c43-75f9-a101-49447fbadeb7
+ locationStatus: blocked
+ movementType: 'replenishment_mismatch'
+ quantity: 3
+ unitMultiplier: 2
+ schemas:
+ Error:
+ type: object
+ required:
+ - status
+ - title
+ properties:
+ status:
+ type: integer
+ source:
+ type: object
+ properties:
+ pointer:
+ type: string
+ title:
+ type: string
+ detail:
+ type: string
+ meta: {$ref: '#/components/schemas/ErrorMeta'}
+ ErrorMeta:
+ type: object
+ properties:
+ stack:
+ type: array
+ items: {type: string}
+ LocationType:
+ type: string
+ enum:
+ - warehouse
+ - brand
+ - retailer
+ LocationStatus:
+ type: string
+ enum:
+ - available
+ - damaged
+ - reserved
+ - qualityControl
+ - blocked
+ - incoming
+ - void
+ StockStatus:
+ type: string
+ enum:
+ - onHand
+ - available
+ - damaged
+ - reserved
+ - qualityControl
+ - blocked
+ - incoming
+ MovementType:
+ type: string
+ enum:
+ - order_created
+ - order_cancelled
+ - order_reserved
+ - order_shipped
+ - order_received
+ - replenishment
+ - snapshot
+ - manual
+ - broken
+ - lost
+ - found
+ - destroyed
+ - replenishment_mismatch
+ - delivery_refused
+ - returned_to_brand
+ - adjustment_reversed
+ - quality_control
+ - expired
+ - brand_request
+ - blocked_by_provider
+ - unblocked
+ - batched
+ - unbatched
+ - returned
+ - batch_modified
+ - expiry_date_modified
+ type:
+ type: string
+ description: >-
+ [resource object type](https://jsonapi.org/format/#document-resource-object-identification)
+ id:
+ type: string
+ format: uuid
+ description: >-
+ [resource object identifier](https://jsonapi.org/format/#document-resource-object-identification)
+ Reservation:
+ type: object
+ title: Reservation
+ properties:
+ items:
+ type: array
+ items: {$ref: '#/components/schemas/ItemReservation'}
+ relatedId:
+ type: string
+ description: >-
+ Here you may specify an ID to which the reservation will be related. Recommended to use an UUID
+ metadata: {$ref: '#/components/schemas/metadata'}
+ required:
+ - items
+ - relatedId
+ ItemReservation:
+ type: object
+ title: ItemReservation
+ properties:
+ productVariantId:
+ type: string
+ format: uuid
+ quantity:
+ type: integer
+ locationId:
+ type: string
+ format: uuid
+ lotNumber:
+ type: string
+ nullable: true
+ expiryDate:
+ type: string
+ nullable: true
+ format: date
+ x-go-type: civil.Date
+ x-go-type-import:
+ path: github.com/ankorstore/astral/pkg/civil
+ name: civil
+ required:
+ - productVariantId
+ - quantity
+ - locationId
+ metadata:
+ type: object
+ additionalProperties:
+ type: string
+ jsonapi:
+ type: object
+ description: An object describing the server's implementation
+ additionalProperties: false
+ properties:
+ version:
+ type: string
+ meta: {$ref: '#/components/schemas/meta'}
+ meta:
+ type: object
+ description: >-
+ Non-standard meta-information that can not be represented as an attribute or relationship.
+ relationshipToOne:
+ description: References to other resource objects in a to-one (`relationship`). Relationships can be specified by including a member in a resource's links object.
+ $ref: '#/components/schemas/linkage'
+ relationshipToMany:
+ description: An array of objects each containing `type` and `id` members for to-many relationships.
+ type: array
+ items:
+ $ref: '#/components/schemas/linkage'
+ uniqueItems: true
+ linkage:
+ description: Resource identification present in Resource Objects and Resource Identifier Objects.
+ type: object
+ required:
+ - id
+ - type
+ properties:
+ id:
+ $ref: '#/components/schemas/id'
+ type:
+ $ref: '#/components/schemas/type'
+ meta:
+ $ref: '#/components/schemas/meta'
+ additionalProperties: false
+ paginationPage:
+ description: Cursor pagination details
+ type: object
+ properties:
+ from:
+ type: string
+ pattern: '^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}(,\d{10})?$'
+ nullable: true
+ to:
+ type: string
+ pattern: '^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}(,\d{10})?$'
+ nullable: true
+ hasMore:
+ type: boolean
+ perPage:
+ type: integer
+ required:
+ - from
+ - to
+ - hasMore
+ - perPage
+ paginationLinks:
+ description: Pagination links
+ type: object
+ properties:
+ first:
+ type: string
+ example: "https://www.ankorstore.com/api/v1/orders?page[limit]=15"
+ nullable: true
+ prev:
+ type: string
+ example: "https://www.ankorstore.com/api/v1/orders?page[before]=1189606a-139e-4b4e-917c-b0c992498bad2&page[limit]=15"
+ nullable: true
+ next:
+ type: string
+ example: "https://www.ankorstore.com/api/v1/orders?page[after]=1189606a-139e-4b4e-917c-b0c992498bad&page[limit]=15"
+ nullable: true
+ required:
+ - first
+ - next
+ - prev
+ paginationMeta:
+ type: object
+ description: Meta with Pagination Details
+ additionalProperties: true
+ properties:
+ page:
+ $ref: '#/components/schemas/paginationPage'
+ required:
+ - page
+ ProductVariantStockStateResource:
+ type: object
+ properties:
+ type: {$ref: '#/components/schemas/type'}
+ id: {$ref: '#/components/schemas/id'}
+ attributes: {$ref: '#/components/schemas/ProductVariantStockState'}
+ required:
+ - type
+ - id
+ - attributes
+ ProductVariantStockState:
+ type: object
+ title: ProductVariantStockState
+ properties:
+ quantities:
+ type: array
+ items: {$ref: '#/components/schemas/ProductVariantStockQuantity'}
+ required:
+ - quantities
+ ProductVariantStockQuantity:
+ type: object
+ title: ProductVariantStockQuantity
+ properties:
+ quantity:
+ type: integer
+ locationId:
+ type: string
+ format: uuid
+ status: {$ref: '#/components/schemas/StockStatus'}
+ lot: {$ref: '#/components/schemas/Lot'}
+ unitMultiplier:
+ type: integer
+ minimum: 1
+ description: The number of units each product variant (batch) consists of
+ required:
+ - quantity
+ - locationId
+ - status
+ - unitMultiplier
+ LocationResource:
+ type: object
+ properties:
+ type: {$ref: '#/components/schemas/type'}
+ id: {$ref: '#/components/schemas/id'}
+ attributes: {$ref: '#/components/schemas/Location'}
+ required:
+ - type
+ - id
+ - attributes
+ Location:
+ type: object
+ properties:
+ type: {$ref: '#/components/schemas/LocationType'}
+ externalId:
+ description: Identifier of the external entity that this location refers to (brandUuid, warehouseUuid, etc)
+ type: string
+ format: uuid
+ required:
+ - type
+ - externalId
+ PostingResource:
+ type: object
+ properties:
+ type: {$ref: '#/components/schemas/type'}
+ id: {$ref: '#/components/schemas/id'}
+ attributes: {$ref: '#/components/schemas/Posting'}
+ relationships: {$ref: '#/components/schemas/PostingsRelationships'}
+ required:
+ - type
+ - id
+ - attributes
+ PostingsRelationships:
+ type: object
+ properties:
+ transaction: {$ref: '#/components/schemas/PostingRelationshipsTransactions'}
+ PostingRelationshipsTransactions:
+ type: object
+ properties:
+ data:
+ $ref: '#/components/schemas/relationshipToOne'
+ Posting:
+ type: object
+ title: Posting
+ properties:
+ locationId:
+ type: string
+ format: uuid
+ productVariantId:
+ type: string
+ format: uuid
+ locationStatus: {$ref: '#/components/schemas/LocationStatus'}
+ quantity:
+ type: integer
+ description: Signed quantity delta
+ movementType: {$ref: '#/components/schemas/MovementType'}
+ unitMultiplier:
+ type: integer
+ minimum: 1
+ description: The number of units each item consists of at the time of this posting
+ expiryDate:
+ type: string
+ format: date
+ x-go-type: civil.Date
+ x-go-type-import:
+ path: github.com/ankorstore/astral/pkg/civil
+ name: civil
+ lotNumber:
+ type: string
+ required:
+ - locationId
+ - productVariantId
+ - locationStatus
+ - quantity
+ - movementType
+ - unitMultiplier
+ TransactionResource:
+ type: object
+ properties:
+ type: {$ref: '#/components/schemas/type'}
+ id: {$ref: '#/components/schemas/id'}
+ attributes: {$ref: '#/components/schemas/Transaction'}
+ relationships: {$ref: '#/components/schemas/TransactionRelationships'}
+ required:
+ - type
+ - id
+ - attributes
+ TransactionRelationships:
+ type: object
+ properties:
+ postings: {$ref: '#/components/schemas/TransactionRelationshipsPostings'}
+ TransactionRelationshipsPostings:
+ type: object
+ properties:
+ data:
+ $ref: '#/components/schemas/relationshipToMany'
+ Transaction:
+ type: object
+ title: Transaction
+ properties:
+ relatedId:
+ type: string
+ createdAt:
+ type: string
+ format: date-time
+ metadata: {$ref: '#/components/schemas/metadata'}
+ required:
+ - relatedId
+ - createdAt
+ - metadata
+ Lot:
+ type: object
+ properties:
+ number:
+ type: string
+ expiryDate:
+ type: string
+ nullable: true
+ format: date
+ x-go-type: civil.Date
+ x-go-type-import:
+ path: github.com/ankorstore/astral/pkg/civil
+ name: civil
+ required:
+ - number
+ PostingCollection:
+ type: object
+ properties:
+ data:
+ type: array
+ items: {$ref: '#/components/schemas/PostingResource'}
+ jsonapi: {$ref: '#/components/schemas/jsonapi'}
+ meta: {$ref: '#/components/schemas/paginationMeta'}
+ links: {$ref: '#/components/schemas/paginationLinks'}
+ included:
+ type: array
+ items:
+ anyOf:
+ - $ref: '#/components/schemas/TransactionResource'
+ required:
+ - data
+ - jsonapi
+ TransactionCollection:
+ type: object
+ properties:
+ data:
+ type: array
+ items: {$ref: '#/components/schemas/TransactionResource'}
+ jsonapi: {$ref: '#/components/schemas/jsonapi'}
+ meta: {$ref: '#/components/schemas/paginationMeta'}
+ links: {$ref: '#/components/schemas/paginationLinks'}
+ included:
+ type: array
+ items:
+ anyOf:
+ - $ref: '#/components/schemas/PostingResource'
+ required:
+ - data
+ - jsonapi
+ StockReservation:
+ type: object
+ properties:
+ type: {$ref: '#/components/schemas/type'}
+ id: {$ref: '#/components/schemas/id'}
+ attributes: {$ref: '#/components/schemas/Reservation'}
+ required:
+ - type
+ - id
+ - attributes
+ parameters:
+ acceptInHeader:
+ name: Accept
+ in: header
+ description: application/vnd.api+json
+ schema:
+ type: string
+ default: application/vnd.api+json
+ xAksBrandUuidHeader:
+ name: X-Aks-Brand-Uuid
+ in: header
+ description: Brand entity when none provided via auth token
+ schema:
+ type: string
+ format: uuid
+ nullable: true
+ xAksRetailerUuidHeader:
+ name: X-Aks-Retailer-Uuid
+ in: header
+ description: Retailer entity when none provided via auth token
+ schema:
+ type: string
+ format: uuid
+ nullable: true
+ pageLimit:
+ name: 'page[limit]'
+ in: query
+ description: limit the amount of results returned
+ required: false
+ schema:
+ type: integer
+ format: int
+ default: 10
+ pageBefore:
+ name: 'page[before]'
+ in: query
+ description: show items before the provided ID (uuid format)
+ required: false
+ schema:
+ type: string
+ format: uuid
+ pageBeforeUuidTimestamp:
+ name: 'page[before]'
+ in: query
+ description: show items before the provided cursors (uuid<,timestamp> format)
+ required: false
+ schema:
+ type: string
+ pattern: '^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}(,\d{10})?$'
+ pageAfter:
+ name: 'page[after]'
+ in: query
+ description: show items after the provided ID (uuid format)
+ required: false
+ schema:
+ type: string
+ format: uuid
+ pageAfterUuidTimestamp:
+ name: 'page[after]'
+ in: query
+ description: show items after the provided cursors (uuid<,timestamp> format)
+ required: false
+ schema:
+ type: string
+ pattern: '^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}(,\d{10})?$'
+ stateAt:
+ name: 'stateAt'
+ in: query
+ description: obtain state up to and including transactions for the given timestamp
+ required: false
+ schema:
+ type: integer
+ productVariantIdFilter:
+ name: filter[productVariantIds][]
+ in: query
+ description: >-
+ A set of identifiers representing the items to check quantities for
+ required: false
+ schema:
+ type: array
+ minItems: 1
+ items:
+ type: string
+ format: uuid
+ statusFilter:
+ name: filter[status][]
+ in: query
+ description: A set of statuses to check quantities for
+ required: false
+ schema:
+ type: array
+ minItems: 1
+ items: {$ref: '#/components/schemas/StockStatus'}
+ locationStatusFilter:
+ name: filter[locationStatus][]
+ in: query
+ description: A set of (location) statuses to check quantities for
+ required: false
+ schema:
+ type: array
+ minItems: 1
+ items: {$ref: '#/components/schemas/LocationStatus'}
+ locationTypeFilter:
+ name: filter[locationTypes][]
+ in: query
+ description: A set of location types to check quantities at
+ required: false
+ schema:
+ type: array
+ minItems: 1
+ items: {$ref: '#/components/schemas/LocationType'}
+ locationIdFilter:
+ name: filter[locationIds][]
+ in: query
+ description: >-
+ A set of identifiers representing the locations to check quantities at
+ required: false
+ schema:
+ type: array
+ minItems: 1
+ items:
+ type: string
+ format: uuid
+ externalIdFilter:
+ name: filter[externalId]
+ in: query
+ description: An external identifier to match on
+ required: false
+ schema:
+ type: string
+ format: uuid