{"openapi":"3.1.0","info":{"title":"Karatry API","version":"1.0.0","description":"Read a Karatry workspace from your own software: styles and their parts lists, stock and single pieces, customers, vendors, quotes, sales orders, invoices, payments, memos, purchase orders and metal prices. With a key that can make changes, add and change customers, vendors and styles, and make draft quotes, sales orders and purchase orders. It can also ask for a sales order to be confirmed, shipped or invoiced, for a payment to be recorded, for a purchase order to be received, for a memo line to be settled, or for a stock item's quantity to be adjusted.\n\n**Keys.** An admin makes a key in Karatry under Settings, Developers. It is shown once. Send it on every request as `Authorization: Bearer <key>`. A key belongs to one workspace and can only ever reach that workspace. A key reads; it makes changes only if the admin ticked \"Can make changes\" when making it.\n\n**What a key can see.** Three kinds of figure are off unless the admin switched them on for the key: cost (what things cost), margin (markup, shown only to a key that also sees cost) and vendors (who supplies a part and at what price, vendors and purchase orders). A field of a kind the key cannot see is left out of the record; a whole resource of that kind answers 403.\n\n**Money and dates.** Every amount is a string with two decimals, such as \"1250.00\", in the workspace's currency (see `/workspace`). Every date is ISO 8601 in UTC.\n\n**Lists.** A list returns `data` and `next_cursor`. Records come oldest first, 50 to a page (up to 100 with `limit`). Pass `next_cursor` back as `cursor` for the next page; it is null on the last. Ids never change, so a record you stored can always be read again by its id.\n\n**Changes.** `POST` makes a record and `PATCH` changes only the fields you send. The body is one JSON object of the fields listed for that call; a field that is not listed is refused. A change runs the same rules as Karatry's own screens, and a refusal comes back in the same words with status 422. A document made here is a draft: nothing is sent, reserved, shipped or owed until someone confirms it in Karatry. A key can only set what it can see: a cost, margin or vendor field is refused for a key without that kind. An amount has at most 2 decimal places; a finer one is refused, never rounded. A line that names both a style and a stock item must name that style's own stock item. The answer is the record, exactly as reading it returns it. When the record saved and something about it needs a look (a style whose metal could not be priced), the answer also carries a `Karatry-Notice` header with one sentence. Two changes to the same record at once never undo each other; in the rare case a record keeps changing under a request it answers 409 `conflict`, and sending it again is safe.\n\n**Requests an admin approves.** A key never moves money or goods itself. Confirming, shipping or invoicing a sales order (`POST /sales-orders/{id}/confirm`, `/ship`, `/invoice`), recording a payment on its invoice (`POST /sales-orders/{id}/payments`), receiving a purchase order (`POST /purchase-orders/{id}/receive`), settling a memo line as sold or returned (`POST /memos/{id}/settle`) and adjusting a stock item's on-hand quantity (`POST /stock-items/{id}/adjust`) each file a request and answer 202 with it; nothing has changed yet. An admin sees the request in Karatry, under Proposals, with everything it would do, and approves or dismisses it within 7 days. Approving runs the same step, with the same checks, as the button on the record's own screen. Read `/proposals/{id}` (the `Location` of the 202) to see where the request stands: waiting, approved, unconfirmed (an admin approved it, but Karatry could not confirm that it ran: read the record), dismissed, withdrawn or expired. A ship or receive request with no `lines` asks for everything still open on the order, fixed at the quantities open when you sent it. A receive is booked at the purchase order's own prices. A payment is recorded against the order's invoice, for no more than is still owed on it. A memo settle is for one line at a time; a line that went out as numbered pieces is settled all at once. A stock adjustment changes on hand by the amount sent, it does not set it. If the record changes after you file (`changed_since_filed` is true), the request can no longer be approved: withdraw it and send a new one. A key sees and withdraws only its own requests, and `/proposals` lists them in a fixed order, not by date. At most 100 requests from API keys can be waiting in one workspace, and at most 50 from one key; past that the API answers 429 `inbox_full`.\n\n**Safe retries.** Every change needs an `Idempotency-Key` header: any text unique to that one change, such as a UUID. If a request times out, send it again with the same key and you get the first result back (with `Idempotent-Replay: true`) instead of a second record. The same key with a different request is refused (422). If the first request never finished on our side the key answers 409 `idempotency_unresolved`: read the record to check, then use a new key. Keys are remembered for 24 hours.\n\n**A workspace that is not taking changes.** When a trial has ended without a subscription the workspace is read-only: reads keep working and changes answer 403 `read_only`. For a few minutes while a restore point is being rolled back, changes answer 423 `locked`.\n\n**Webhooks.** An admin adds a webhook in Settings, Developers: an https address and the events to send it. When one of those happens, Karatry sends a POST with a short JSON body: `id`, `type`, `created_at`, `api_version` and `data` (ids, numbers and status; never a cost, margin or vendor figure. Read the record with a key for more). The events and what each carries are listed under `webhooks` in this document. Each message carries `Karatry-Signature: t=<unix seconds>,v1=<hex>`, where the hex is the HMAC-SHA256 of `<t>.<raw body>` with the webhook's signing secret. Check it against the raw body before parsing, and turn away a message whose `t` is more than 300 seconds old. Answer with any 2xx within 8 seconds; anything else is tried again, nine tries in all, waiting at least 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours, 12 hours, a day and a day between them. A try that has come due goes out within a few minutes. A redirect is not followed. A message can arrive more than once and out of order: the event `id` is the same on every delivery of an event, so ignore one you have already handled. A webhook that fails every try for three days is switched off, and events from while it was off are not sent.\n\n**Limits.** Each key has its own requests-a-minute limit, reported in the `X-RateLimit-*` headers. Over it, the API answers 429 with `Retry-After`.\n\n**Errors.** Every error is `{ \"error\": { \"code\", \"message\" } }` with a matching HTTP status."},"servers":[{"url":"https://app.karatry.com/api/v1"}],"security":[{"apiKey":[]}],"tags":[{"name":"Workspace"},{"name":"Styles"},{"name":"Stock"},{"name":"Customers"},{"name":"Vendors"},{"name":"Sales"},{"name":"Purchasing"},{"name":"Metal"},{"name":"Requests for approval"},{"name":"Webhooks"}],"paths":{"/workspace":{"get":{"operationId":"get_workspace","tags":["Workspace"],"summary":"The workspace this key belongs to, and what the key may do. A good first call to check a key.","responses":{"200":{"description":"The workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Workspace"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/styles":{"get":{"operationId":"list_styles","tags":["Styles"],"summary":"Styles: the designs a workspace makes or buys, with their variants and stored prices.","description":"Lists records, oldest first, 50 to a page unless `limit` says otherwise. Follow `next_cursor` until it is null to read them all.","parameters":[{"name":"limit","in":"query","required":false,"description":"How many records to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the page before.","schema":{"type":"string"}},{"name":"style","in":"query","required":false,"description":"The exact style number.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Only styles in this status.","schema":{"type":"string","enum":["ACTIVE","DRAFT","DISCONTINUED"]}},{"name":"category","in":"query","required":false,"description":"Only styles in this category, such as RING.","schema":{"type":"string"}},{"name":"updated_since","in":"query","required":false,"description":"Only records changed at or after this time (ISO 8601). Use it to pick up what changed since your last sync.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"One page of records.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Style"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"400":{"description":"A parameter is wrong. The message says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"create_style","tags":["Styles"],"summary":"Makes a style, with its stock item. Its parts list is added in Karatry. Needs a key that can make changes.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StyleCreate"}}}},"responses":{"201":{"description":"The new record, as reading it returns it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Style"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, can't see a kind of field it tried to set, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The change was refused, in the words Karatry's own screen would use; or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/styles/{id}":{"get":{"operationId":"get_styles","tags":["Styles"],"summary":"Reads a style by id.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Style"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"update_style","tags":["Styles"],"summary":"Changes a style's header and re-costs it. Only the fields sent are changed. Needs a key that can make changes.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StyleUpdate"}}}},"responses":{"200":{"description":"The record after the change, as reading it returns it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Style"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, can't see a kind of field it tried to set, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished; or the record kept changing while this change was being saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The change was refused, in the words Karatry's own screen would use; or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/styles/{id}/bom":{"get":{"operationId":"get_styles_bom","tags":["Styles"],"summary":"The style's parts list (bill of materials), one record per line.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Every record, in one page.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StyleBom"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/styles/{id}/costing":{"get":{"operationId":"get_styles_costing","tags":["Styles"],"summary":"The style's live cost breakdown, computed now from current metal prices, labour rates and the parts list. It is the same breakdown the style's page shows. Needs a key that can see cost; other keys get 403.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StyleCosting"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't see this kind of record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stock-items":{"get":{"operationId":"list_stock_items","tags":["Stock"],"summary":"Stock items: what the workspace holds and how much. A style's finished stock is one item (category FINISHED_GOOD, with style_id set); stones, metal and findings are items too.","description":"Lists records, oldest first, 50 to a page unless `limit` says otherwise. Follow `next_cursor` until it is null to read them all.","parameters":[{"name":"limit","in":"query","required":false,"description":"How many records to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the page before.","schema":{"type":"string"}},{"name":"sku","in":"query","required":false,"description":"The exact SKU.","schema":{"type":"string"}},{"name":"category","in":"query","required":false,"description":"Only items in this category.","schema":{"type":"string","enum":["DIAMOND","GEMSTONE","METAL","FINDING","CASTING","FINISHED_GOOD","SCRAP","SERVICE"]}},{"name":"style_id","in":"query","required":false,"description":"Only the stock of this style.","schema":{"type":"string"}},{"name":"updated_since","in":"query","required":false,"description":"Only records changed at or after this time (ISO 8601). Use it to pick up what changed since your last sync.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"One page of records.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StockItem"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"400":{"description":"A parameter is wrong. The message says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stock-items/{id}":{"get":{"operationId":"get_stock_items","tags":["Stock"],"summary":"Reads a stock item by id.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockItem"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stock-items/{id}/adjust":{"post":{"operationId":"adjust_stock_item","tags":["Stock"],"summary":"Ask for a stock item's on-hand quantity to be adjusted up or down. An admin approves it in Karatry before stock changes. Needs a key that can make changes.","description":"Changes nothing by itself. It files a request and answers 202 with it; an admin approves or dismisses it in Karatry within 7 days. Read the request at the `Location` given to see where it stands.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockItemAdjust"}}}},"responses":{"202":{"description":"The request was filed and is waiting for an admin. Nothing has changed yet.","headers":{"Location":{"description":"Where to read the request: /api/v1/proposals/{id}.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Proposal"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request could never be approved as sent (the message says why), or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit (`rate_limited`; Retry-After says how long to wait), or 100 requests from API keys (50 from this key) are already waiting for an admin (`inbox_full`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pieces":{"get":{"operationId":"list_pieces","tags":["Stock"],"summary":"Pieces: single finished pieces, each with its own number and barcode.","description":"Lists records, oldest first, 50 to a page unless `limit` says otherwise. Follow `next_cursor` until it is null to read them all.","parameters":[{"name":"limit","in":"query","required":false,"description":"How many records to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the page before.","schema":{"type":"string"}},{"name":"number","in":"query","required":false,"description":"The exact piece number.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Only pieces in this status.","schema":{"type":"string","enum":["IN_STOCK","RESERVED","SOLD","RETURNED","CONSUMED","ON_MEMO","IN_REPAIR"]}},{"name":"stock_item_id","in":"query","required":false,"description":"Only pieces of this stock item.","schema":{"type":"string"}},{"name":"location_id","in":"query","required":false,"description":"Only pieces at this location.","schema":{"type":"string"}}],"responses":{"200":{"description":"One page of records.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Piece"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"400":{"description":"A parameter is wrong. The message says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pieces/{id}":{"get":{"operationId":"get_pieces","tags":["Stock"],"summary":"Reads a piece by id.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Piece"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/locations":{"get":{"operationId":"list_locations","tags":["Stock"],"summary":"Locations: the places stock is kept. Empty in a workspace that does not track locations.","description":"Lists records, oldest first, 50 to a page unless `limit` says otherwise. Follow `next_cursor` until it is null to read them all.","parameters":[{"name":"limit","in":"query","required":false,"description":"How many records to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the page before.","schema":{"type":"string"}},{"name":"updated_since","in":"query","required":false,"description":"Only records changed at or after this time (ISO 8601). Use it to pick up what changed since your last sync.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"One page of records.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Location"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"400":{"description":"A parameter is wrong. The message says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/locations/{id}":{"get":{"operationId":"get_locations","tags":["Stock"],"summary":"Reads a location by id.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Location"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/customers":{"get":{"operationId":"list_customers","tags":["Customers"],"summary":"Customers: who the workspace sells to, with their terms and what they owe.","description":"Lists records, oldest first, 50 to a page unless `limit` says otherwise. Follow `next_cursor` until it is null to read them all.","parameters":[{"name":"limit","in":"query","required":false,"description":"How many records to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the page before.","schema":{"type":"string"}},{"name":"code","in":"query","required":false,"description":"The exact customer code.","schema":{"type":"string"}},{"name":"email","in":"query","required":false,"description":"The exact email address.","schema":{"type":"string"}},{"name":"updated_since","in":"query","required":false,"description":"Only records changed at or after this time (ISO 8601). Use it to pick up what changed since your last sync.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"One page of records.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Customer"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"400":{"description":"A parameter is wrong. The message says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"create_customer","tags":["Customers"],"summary":"Makes a customer. Needs a key that can make changes.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerCreate"}}}},"responses":{"201":{"description":"The new record, as reading it returns it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Customer"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, can't see a kind of field it tried to set, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The change was refused, in the words Karatry's own screen would use; or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/customers/{id}":{"get":{"operationId":"get_customers","tags":["Customers"],"summary":"Reads a customer by id.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Customer"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"update_customer","tags":["Customers"],"summary":"Changes a customer. Only the fields sent are changed. Needs a key that can make changes.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerUpdate"}}}},"responses":{"200":{"description":"The record after the change, as reading it returns it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Customer"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, can't see a kind of field it tried to set, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished; or the record kept changing while this change was being saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The change was refused, in the words Karatry's own screen would use; or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/vendors":{"get":{"operationId":"list_vendors","tags":["Vendors"],"summary":"Vendors: who the workspace buys from.","description":"Lists records, oldest first, 50 to a page unless `limit` says otherwise. Follow `next_cursor` until it is null to read them all. Needs a key that can see vendors; other keys get 403.","parameters":[{"name":"limit","in":"query","required":false,"description":"How many records to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the page before.","schema":{"type":"string"}},{"name":"code","in":"query","required":false,"description":"The exact vendor code.","schema":{"type":"string"}},{"name":"updated_since","in":"query","required":false,"description":"Only records changed at or after this time (ISO 8601). Use it to pick up what changed since your last sync.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"One page of records.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Vendor"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"400":{"description":"A parameter is wrong. The message says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't see this kind of record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"create_vendor","tags":["Vendors"],"summary":"Makes a vendor. Needs a key that can make changes and can see vendors.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VendorCreate"}}}},"responses":{"201":{"description":"The new record, as reading it returns it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Vendor"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, can't see a kind of field it tried to set, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The change was refused, in the words Karatry's own screen would use; or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/vendors/{id}":{"get":{"operationId":"get_vendors","tags":["Vendors"],"summary":"Reads a vendor by id. Needs a key that can see vendors; other keys get 403.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Vendor"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't see this kind of record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"update_vendor","tags":["Vendors"],"summary":"Changes a vendor. Only the fields sent are changed. Needs a key that can make changes and can see vendors.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VendorUpdate"}}}},"responses":{"200":{"description":"The record after the change, as reading it returns it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Vendor"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, can't see a kind of field it tried to set, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished; or the record kept changing while this change was being saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The change was refused, in the words Karatry's own screen would use; or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/quotes":{"get":{"operationId":"list_quotes","tags":["Sales"],"summary":"Quotes: prices offered to a customer, with their lines.","description":"Lists records, oldest first, 50 to a page unless `limit` says otherwise. Follow `next_cursor` until it is null to read them all.","parameters":[{"name":"limit","in":"query","required":false,"description":"How many records to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the page before.","schema":{"type":"string"}},{"name":"number","in":"query","required":false,"description":"The exact quote number.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Only quotes in this status.","schema":{"type":"string","enum":["DRAFT","SENT","ACCEPTED","DECLINED","EXPIRED"]}},{"name":"customer_id","in":"query","required":false,"description":"Only this customer's quotes.","schema":{"type":"string"}},{"name":"updated_since","in":"query","required":false,"description":"Only records changed at or after this time (ISO 8601). Use it to pick up what changed since your last sync.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"One page of records.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Quote"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"400":{"description":"A parameter is wrong. The message says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"create_quote","tags":["Sales"],"summary":"Makes a draft quote. Tax is worked out from the customer; nothing is sent. Needs a key that can make changes.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteCreate"}}}},"responses":{"201":{"description":"The new record, as reading it returns it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, can't see a kind of field it tried to set, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The change was refused, in the words Karatry's own screen would use; or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/quotes/{id}":{"get":{"operationId":"get_quotes","tags":["Sales"],"summary":"Reads a quote by id.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sales-orders":{"get":{"operationId":"list_sales_orders","tags":["Sales"],"summary":"Sales orders, with their lines.","description":"Lists records, oldest first, 50 to a page unless `limit` says otherwise. Follow `next_cursor` until it is null to read them all.","parameters":[{"name":"limit","in":"query","required":false,"description":"How many records to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the page before.","schema":{"type":"string"}},{"name":"number","in":"query","required":false,"description":"The exact order number.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Only orders in this status.","schema":{"type":"string","enum":["DRAFT","CONFIRMED","IN_PRODUCTION","PARTIAL_SHIPPED","SHIPPED","INVOICED","PAID","CANCELLED"]}},{"name":"customer_id","in":"query","required":false,"description":"Only this customer's orders.","schema":{"type":"string"}},{"name":"updated_since","in":"query","required":false,"description":"Only records changed at or after this time (ISO 8601). Use it to pick up what changed since your last sync.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"One page of records.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SalesOrder"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"400":{"description":"A parameter is wrong. The message says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"create_sales_order","tags":["Sales"],"summary":"Makes a draft sales order. Tax is worked out from the customer; no stock is reserved until the order is confirmed in Karatry. Needs a key that can make changes.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderCreate"}}}},"responses":{"201":{"description":"The new record, as reading it returns it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrder"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, can't see a kind of field it tried to set, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The change was refused, in the words Karatry's own screen would use; or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sales-orders/{id}":{"get":{"operationId":"get_sales_orders","tags":["Sales"],"summary":"Reads a sales order by id.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrder"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sales-orders/{id}/confirm":{"post":{"operationId":"confirm_sales_order","tags":["Sales"],"summary":"Ask for a draft sales order to be confirmed. An admin approves it in Karatry before anything changes. Needs a key that can make changes.","description":"Changes nothing by itself. It files a request and answers 202 with it; an admin approves or dismisses it in Karatry within 7 days. Read the request at the `Location` given to see where it stands.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":false,"description":"May be left out, or sent as an empty object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderConfirm"}}}},"responses":{"202":{"description":"The request was filed and is waiting for an admin. Nothing has changed yet.","headers":{"Location":{"description":"Where to read the request: /api/v1/proposals/{id}.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Proposal"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request could never be approved as sent (the message says why), or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit (`rate_limited`; Retry-After says how long to wait), or 100 requests from API keys (50 from this key) are already waiting for an admin (`inbox_full`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sales-orders/{id}/ship":{"post":{"operationId":"ship_sales_order","tags":["Sales"],"summary":"Ask for goods on a sales order to be shipped. An admin approves it in Karatry before anything leaves stock. Needs a key that can make changes.","description":"Changes nothing by itself. It files a request and answers 202 with it; an admin approves or dismisses it in Karatry within 7 days. Read the request at the `Location` given to see where it stands.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":false,"description":"May be left out, or sent as an empty object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderShip"}}}},"responses":{"202":{"description":"The request was filed and is waiting for an admin. Nothing has changed yet.","headers":{"Location":{"description":"Where to read the request: /api/v1/proposals/{id}.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Proposal"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request could never be approved as sent (the message says why), or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit (`rate_limited`; Retry-After says how long to wait), or 100 requests from API keys (50 from this key) are already waiting for an admin (`inbox_full`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sales-orders/{id}/invoice":{"post":{"operationId":"invoice_sales_order","tags":["Sales"],"summary":"Ask for a shipped sales order to be invoiced. An admin approves it in Karatry before any invoice exists. Needs a key that can make changes.","description":"Changes nothing by itself. It files a request and answers 202 with it; an admin approves or dismisses it in Karatry within 7 days. Read the request at the `Location` given to see where it stands.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":false,"description":"May be left out, or sent as an empty object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderInvoice"}}}},"responses":{"202":{"description":"The request was filed and is waiting for an admin. Nothing has changed yet.","headers":{"Location":{"description":"Where to read the request: /api/v1/proposals/{id}.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Proposal"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request could never be approved as sent (the message says why), or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit (`rate_limited`; Retry-After says how long to wait), or 100 requests from API keys (50 from this key) are already waiting for an admin (`inbox_full`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sales-orders/{id}/payments":{"post":{"operationId":"payments_sales_order","tags":["Sales"],"summary":"Ask for a payment to be recorded against a sales order's invoice. An admin approves it in Karatry before any money is booked. Needs a key that can make changes.","description":"Changes nothing by itself. It files a request and answers 202 with it; an admin approves or dismisses it in Karatry within 7 days. Read the request at the `Location` given to see where it stands.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderPayments"}}}},"responses":{"202":{"description":"The request was filed and is waiting for an admin. Nothing has changed yet.","headers":{"Location":{"description":"Where to read the request: /api/v1/proposals/{id}.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Proposal"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request could never be approved as sent (the message says why), or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit (`rate_limited`; Retry-After says how long to wait), or 100 requests from API keys (50 from this key) are already waiting for an admin (`inbox_full`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/invoices":{"get":{"operationId":"list_invoices","tags":["Sales"],"summary":"Invoices, with what has been paid and what is still owed.","description":"Lists records, oldest first, 50 to a page unless `limit` says otherwise. Follow `next_cursor` until it is null to read them all.","parameters":[{"name":"limit","in":"query","required":false,"description":"How many records to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the page before.","schema":{"type":"string"}},{"name":"number","in":"query","required":false,"description":"The exact invoice number.","schema":{"type":"string"}},{"name":"customer_id","in":"query","required":false,"description":"Only this customer's invoices.","schema":{"type":"string"}},{"name":"order_id","in":"query","required":false,"description":"Only the invoice for this sales order.","schema":{"type":"string"}}],"responses":{"200":{"description":"One page of records.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Invoice"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"400":{"description":"A parameter is wrong. The message says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/invoices/{id}":{"get":{"operationId":"get_invoices","tags":["Sales"],"summary":"Reads an invoice by id.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invoice"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/payments":{"get":{"operationId":"list_payments","tags":["Sales"],"summary":"Payments received from customers.","description":"Lists records, oldest first, 50 to a page unless `limit` says otherwise. Follow `next_cursor` until it is null to read them all.","parameters":[{"name":"limit","in":"query","required":false,"description":"How many records to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the page before.","schema":{"type":"string"}},{"name":"invoice_id","in":"query","required":false,"description":"Only payments against this invoice.","schema":{"type":"string"}},{"name":"order_id","in":"query","required":false,"description":"Only deposits on this sales order.","schema":{"type":"string"}},{"name":"received_since","in":"query","required":false,"description":"Only payments received at or after this time (ISO 8601).","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"One page of records.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Payment"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"400":{"description":"A parameter is wrong. The message says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/payments/{id}":{"get":{"operationId":"get_payments","tags":["Sales"],"summary":"Reads a payment by id.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/memos":{"get":{"operationId":"list_memos","tags":["Sales"],"summary":"Memos: goods out with a customer on consignment, with their lines and pieces.","description":"Lists records, oldest first, 50 to a page unless `limit` says otherwise. Follow `next_cursor` until it is null to read them all.","parameters":[{"name":"limit","in":"query","required":false,"description":"How many records to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the page before.","schema":{"type":"string"}},{"name":"number","in":"query","required":false,"description":"The exact memo number.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Only memos in this status.","schema":{"type":"string","enum":["OUT","PARTIAL_RETURN","RETURNED","SOLD","OVERDUE","DISPOSED","SETTLED"]}},{"name":"customer_id","in":"query","required":false,"description":"Only this customer's memos.","schema":{"type":"string"}},{"name":"updated_since","in":"query","required":false,"description":"Only records changed at or after this time (ISO 8601). Use it to pick up what changed since your last sync.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"One page of records.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Memo"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"400":{"description":"A parameter is wrong. The message says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/memos/{id}":{"get":{"operationId":"get_memos","tags":["Sales"],"summary":"Reads a memo by id.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Memo"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/memos/{id}/settle":{"post":{"operationId":"settle_memo","tags":["Sales"],"summary":"Ask for one line of a memo to be settled: sold to the customer holding it, or returned to stock. An admin approves it in Karatry before anything changes. Needs a key that can make changes.","description":"Changes nothing by itself. It files a request and answers 202 with it; an admin approves or dismisses it in Karatry within 7 days. Read the request at the `Location` given to see where it stands.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoSettle"}}}},"responses":{"202":{"description":"The request was filed and is waiting for an admin. Nothing has changed yet.","headers":{"Location":{"description":"Where to read the request: /api/v1/proposals/{id}.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Proposal"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request could never be approved as sent (the message says why), or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit (`rate_limited`; Retry-After says how long to wait), or 100 requests from API keys (50 from this key) are already waiting for an admin (`inbox_full`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/purchase-orders":{"get":{"operationId":"list_purchase_orders","tags":["Purchasing"],"summary":"Purchase orders, with their lines.","description":"Lists records, oldest first, 50 to a page unless `limit` says otherwise. Follow `next_cursor` until it is null to read them all. Needs a key that can see vendors; other keys get 403.","parameters":[{"name":"limit","in":"query","required":false,"description":"How many records to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the page before.","schema":{"type":"string"}},{"name":"number","in":"query","required":false,"description":"The exact purchase order number.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Only orders in this status.","schema":{"type":"string","enum":["DRAFT","SENT","PARTIAL","RECEIVED","CANCELLED"]}},{"name":"vendor_id","in":"query","required":false,"description":"Only orders with this vendor.","schema":{"type":"string"}},{"name":"updated_since","in":"query","required":false,"description":"Only records changed at or after this time (ISO 8601). Use it to pick up what changed since your last sync.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"One page of records.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseOrder"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"400":{"description":"A parameter is wrong. The message says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't see this kind of record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"create_purchase_order","tags":["Purchasing"],"summary":"Makes a draft purchase order. Needs a key that can make changes and can see vendors.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderCreate"}}}},"responses":{"201":{"description":"The new record, as reading it returns it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrder"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, can't see a kind of field it tried to set, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The change was refused, in the words Karatry's own screen would use; or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/purchase-orders/{id}":{"get":{"operationId":"get_purchase_orders","tags":["Purchasing"],"summary":"Reads a purchase order by id. Needs a key that can see vendors; other keys get 403.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrder"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't see this kind of record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/purchase-orders/{id}/receive":{"post":{"operationId":"receive_purchase_order","tags":["Purchasing"],"summary":"Ask for goods on a purchase order to be received. An admin approves it in Karatry before anything goes into stock. Needs a key that can make changes and can see vendors.","description":"Changes nothing by itself. It files a request and answers 202 with it; an admin approves or dismisses it in Karatry within 7 days. Read the request at the `Location` given to see where it stands.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":false,"description":"May be left out, or sent as an empty object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderReceive"}}}},"responses":{"202":{"description":"The request was filed and is waiting for an admin. Nothing has changed yet.","headers":{"Location":{"description":"Where to read the request: /api/v1/proposals/{id}.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Proposal"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes or can't see this kind of record, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with this Idempotency-Key is still running, or never finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request could never be approved as sent (the message says why), or the Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit (`rate_limited`; Retry-After says how long to wait), or 100 requests from API keys (50 from this key) are already waiting for an admin (`inbox_full`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/metal-prices":{"get":{"operationId":"list_metal_prices","tags":["Metal"],"summary":"Metal prices: the spot prices the workspace's costing uses.","description":"Lists records, oldest first, 50 to a page unless `limit` says otherwise. Follow `next_cursor` until it is null to read them all.","parameters":[{"name":"limit","in":"query","required":false,"description":"How many records to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the page before.","schema":{"type":"string"}},{"name":"metal","in":"query","required":false,"description":"The exact metal, such as GOLD.","schema":{"type":"string"}},{"name":"updated_since","in":"query","required":false,"description":"Only records changed at or after this time (ISO 8601). Use it to pick up what changed since your last sync.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"One page of records.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MetalPrice"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"400":{"description":"A parameter is wrong. The message says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/metal-prices/{id}":{"get":{"operationId":"get_metal_prices","tags":["Metal"],"summary":"Reads a metal price by id.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetalPrice"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/proposals":{"get":{"operationId":"list_proposals","tags":["Requests for approval"],"summary":"The requests this key has filed for an admin to approve (confirming, shipping or invoicing a sales order, recording a payment, receiving a purchase order, settling a memo line, adjusting stock), and where each one stands. A key sees only its own.","description":"Lists records, in a fixed order (not by date), 50 to a page unless `limit` says otherwise. Follow `next_cursor` until it is null to read them all.","parameters":[{"name":"limit","in":"query","required":false,"description":"How many records to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the page before.","schema":{"type":"string"}}],"responses":{"200":{"description":"One page of records.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Proposal"}},"next_cursor":{"type":["string","null"],"description":"Pass this as `cursor` to get the next page. Null on the last page."}}}}}},"400":{"description":"A parameter is wrong. The message says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/proposals/{id}":{"get":{"operationId":"get_proposals","tags":["Requests for approval"],"summary":"Reads a request this key filed by id.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Proposal"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/proposals/{id}/withdraw":{"post":{"operationId":"withdraw_proposal","tags":["Requests for approval"],"summary":"Takes back a request this key filed, while it is still waiting. The admin no longer sees it to approve. A request an admin already approved, dismissed, or that was already withdrawn answers 409. Needs a key that can make changes.","parameters":[{"name":"id","in":"path","required":true,"description":"The record's id.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"Any text that is unique to this one change, such as a UUID (1 to 200 characters, no spaces). Sending the same request again with the same key returns the first result instead of making the change twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":false,"description":"May be left out, or sent as an empty object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProposalWithdraw"}}}},"responses":{"200":{"description":"The record after the change, as reading it returns it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Proposal"}}}},"400":{"description":"The body or the Idempotency-Key header is wrong. The message says what.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key is missing, wrong or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key can't make changes, or the workspace is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No record with that id for this key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The change can no longer be made (the message says why); or a request with this Idempotency-Key is still running, or never finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The Idempotency-Key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"423":{"description":"The workspace is not taking changes for a few minutes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The key is over its requests-a-minute limit. Retry-After says how long to wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{"sales_order.confirmed":{"post":{"summary":"A sales order was confirmed, or the unshipped remainder of one was split off as a new order.","tags":["Webhooks"],"security":[],"parameters":[{"name":"Karatry-Signature","in":"header","required":true,"description":"`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `<t>.<raw body>` with the webhook's signing secret. Turn away a message more than 300 seconds old.","schema":{"type":"string"}},{"name":"Karatry-Event","in":"header","required":true,"description":"The event type, the same as `type` in the body.","schema":{"type":"string"}},{"name":"Karatry-Event-Id","in":"header","required":true,"description":"The event's id, the same as `id` in the body and the same on every delivery of this event.","schema":{"type":"string"}},{"name":"Karatry-Delivery-Id","in":"header","required":true,"description":"This delivery's id: a new one for each Send again.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookSalesOrderConfirmed"}}}},"responses":{"2XX":{"description":"Received. Anything else, or no answer within 8 seconds, is tried again."}}}},"invoice.issued":{"post":{"summary":"An invoice was issued for a sales order.","tags":["Webhooks"],"security":[],"parameters":[{"name":"Karatry-Signature","in":"header","required":true,"description":"`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `<t>.<raw body>` with the webhook's signing secret. Turn away a message more than 300 seconds old.","schema":{"type":"string"}},{"name":"Karatry-Event","in":"header","required":true,"description":"The event type, the same as `type` in the body.","schema":{"type":"string"}},{"name":"Karatry-Event-Id","in":"header","required":true,"description":"The event's id, the same as `id` in the body and the same on every delivery of this event.","schema":{"type":"string"}},{"name":"Karatry-Delivery-Id","in":"header","required":true,"description":"This delivery's id: a new one for each Send again.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookInvoiceIssued"}}}},"responses":{"2XX":{"description":"Received. Anything else, or no answer within 8 seconds, is tried again."}}}},"payment.received":{"post":{"summary":"A customer's payment was recorded against an invoice, or a deposit was taken on an order.","tags":["Webhooks"],"security":[],"parameters":[{"name":"Karatry-Signature","in":"header","required":true,"description":"`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `<t>.<raw body>` with the webhook's signing secret. Turn away a message more than 300 seconds old.","schema":{"type":"string"}},{"name":"Karatry-Event","in":"header","required":true,"description":"The event type, the same as `type` in the body.","schema":{"type":"string"}},{"name":"Karatry-Event-Id","in":"header","required":true,"description":"The event's id, the same as `id` in the body and the same on every delivery of this event.","schema":{"type":"string"}},{"name":"Karatry-Delivery-Id","in":"header","required":true,"description":"This delivery's id: a new one for each Send again.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookPaymentReceived"}}}},"responses":{"2XX":{"description":"Received. Anything else, or no answer within 8 seconds, is tried again."}}}},"memo.settled":{"post":{"summary":"Goods out on memo were sold, returned, or written off as lost or damaged.","tags":["Webhooks"],"security":[],"parameters":[{"name":"Karatry-Signature","in":"header","required":true,"description":"`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `<t>.<raw body>` with the webhook's signing secret. Turn away a message more than 300 seconds old.","schema":{"type":"string"}},{"name":"Karatry-Event","in":"header","required":true,"description":"The event type, the same as `type` in the body.","schema":{"type":"string"}},{"name":"Karatry-Event-Id","in":"header","required":true,"description":"The event's id, the same as `id` in the body and the same on every delivery of this event.","schema":{"type":"string"}},{"name":"Karatry-Delivery-Id","in":"header","required":true,"description":"This delivery's id: a new one for each Send again.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookMemoSettled"}}}},"responses":{"2XX":{"description":"Received. Anything else, or no answer within 8 seconds, is tried again."}}}},"piece.created":{"post":{"summary":"A numbered piece was added to stock.","tags":["Webhooks"],"security":[],"parameters":[{"name":"Karatry-Signature","in":"header","required":true,"description":"`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `<t>.<raw body>` with the webhook's signing secret. Turn away a message more than 300 seconds old.","schema":{"type":"string"}},{"name":"Karatry-Event","in":"header","required":true,"description":"The event type, the same as `type` in the body.","schema":{"type":"string"}},{"name":"Karatry-Event-Id","in":"header","required":true,"description":"The event's id, the same as `id` in the body and the same on every delivery of this event.","schema":{"type":"string"}},{"name":"Karatry-Delivery-Id","in":"header","required":true,"description":"This delivery's id: a new one for each Send again.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookPieceCreated"}}}},"responses":{"2XX":{"description":"Received. Anything else, or no answer within 8 seconds, is tried again."}}}},"piece.sold":{"post":{"summary":"A numbered piece left stock on a shipped sales order.","tags":["Webhooks"],"security":[],"parameters":[{"name":"Karatry-Signature","in":"header","required":true,"description":"`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `<t>.<raw body>` with the webhook's signing secret. Turn away a message more than 300 seconds old.","schema":{"type":"string"}},{"name":"Karatry-Event","in":"header","required":true,"description":"The event type, the same as `type` in the body.","schema":{"type":"string"}},{"name":"Karatry-Event-Id","in":"header","required":true,"description":"The event's id, the same as `id` in the body and the same on every delivery of this event.","schema":{"type":"string"}},{"name":"Karatry-Delivery-Id","in":"header","required":true,"description":"This delivery's id: a new one for each Send again.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookPieceSold"}}}},"responses":{"2XX":{"description":"Received. Anything else, or no answer within 8 seconds, is tried again."}}}},"stock.changed":{"post":{"summary":"A stock item's on-hand or reserved quantity changed. Sent once per item for each saved change, with the quantities after it.","tags":["Webhooks"],"security":[],"parameters":[{"name":"Karatry-Signature","in":"header","required":true,"description":"`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `<t>.<raw body>` with the webhook's signing secret. Turn away a message more than 300 seconds old.","schema":{"type":"string"}},{"name":"Karatry-Event","in":"header","required":true,"description":"The event type, the same as `type` in the body.","schema":{"type":"string"}},{"name":"Karatry-Event-Id","in":"header","required":true,"description":"The event's id, the same as `id` in the body and the same on every delivery of this event.","schema":{"type":"string"}},{"name":"Karatry-Delivery-Id","in":"header","required":true,"description":"This delivery's id: a new one for each Send again.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookStockChanged"}}}},"responses":{"2XX":{"description":"Received. Anything else, or no answer within 8 seconds, is tried again."}}}},"webhook.test":{"post":{"summary":"Sent once when an admin presses Send a test event. Never retried.","tags":["Webhooks"],"security":[],"parameters":[{"name":"Karatry-Signature","in":"header","required":true,"description":"`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `<t>.<raw body>` with the webhook's signing secret. Turn away a message more than 300 seconds old.","schema":{"type":"string"}},{"name":"Karatry-Event","in":"header","required":true,"description":"The event type, the same as `type` in the body.","schema":{"type":"string"}},{"name":"Karatry-Event-Id","in":"header","required":true,"description":"The event's id, the same as `id` in the body and the same on every delivery of this event.","schema":{"type":"string"}},{"name":"Karatry-Delivery-Id","in":"header","required":true,"description":"This delivery's id: a new one for each Send again.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The event's id. The same on every delivery and every retry of this event, so a receiver can ignore one it has already handled."},"type":{"type":"string","const":"webhook.test"},"created_at":{"type":"string","format":"date-time","description":"When the change was saved."},"api_version":{"type":"string","description":"Always v1."},"data":{"type":"object","properties":{"message":{"type":"string"},"webhook_id":{"type":"string","description":"The webhook the test was sent to."}},"required":["message","webhook_id"]}},"required":["id","type","created_at","api_version","data"]}}}},"responses":{"2XX":{"description":"Received. Anything else, or no answer within 8 seconds, is tried again."}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key made in Settings, Developers."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["not_found","unauthorized","forbidden","rate_limited","invalid_request","method_not_allowed","unavailable","internal","payload_too_large","unprocessable","read_only","locked","conflict","idempotency_key_required","idempotency_mismatch","idempotency_in_progress","idempotency_unresolved","inbox_full"]},"message":{"type":"string","description":"What went wrong, in a sentence."}}}}},"Workspace":{"type":"object","required":["name","currency","tracks_locations","read_only","key"],"properties":{"name":{"type":"string","description":"The workspace's name."},"currency":{"type":"string","description":"The currency every amount is in, as an ISO 4217 code."},"tracks_locations":{"type":"boolean","description":"True when the workspace tracks stock by location."},"read_only":{"type":"boolean","description":"True when the workspace's trial has ended without a subscription. Reading keeps working."},"key":{"type":"object","required":["name","scopes","rate_limit_per_minute"],"properties":{"name":{"type":"string","description":"What the key was called when it was made."},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","cost","margin","vendors"]},"description":"What the key may do (read, and write when it can make changes) and which figures it may see (cost, margin, vendors)."},"rate_limit_per_minute":{"type":"integer","description":"The key's limit, in requests a minute."}}}}},"Style":{"type":"object","properties":{"id":{"type":"string","description":"The style's id. Stable for the life of the record."},"style":{"type":"string","description":"The style number, unique in the workspace."},"name":{"type":"string","description":"The style's name."},"category":{"type":"string","description":"What kind of piece it is, such as RING."},"collection":{"type":["string","null"],"description":"The collection it belongs to."},"metal_type":{"type":"string","description":"The metal, such as GOLD."},"karat":{"type":"string","description":"The purity, such as 14K."},"description":{"type":["string","null"],"description":"The style's description."},"image_url":{"type":["string","null"],"description":"The style's main image."},"metal_weight_grams":{"type":"number","description":"The style's nominal metal weight in grams."},"status":{"type":"string","description":"Where the style stands.","enum":["ACTIVE","DRAFT","DISCONTINUED"]},"archived_at":{"type":["string","null"],"format":"date-time","description":"When the style was archived."},"wholesale_price":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The stored wholesale price."},"msrp":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The stored retail price."},"labor_cost":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The stored labour cost. Only returned to a key that may see cost."},"material_cost":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The stored material cost. Only returned to a key that may see cost."},"total_cost":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The stored theoretical cost of one piece. Only returned to a key that may see cost."},"markup":{"type":"number","description":"The markup multiplier the prices were set with. Only returned to a key that may see cost and margin."},"vendor_id":{"type":["string","null"],"description":"The vendor the style is bought from, when it is bought finished. Only returned to a key that may see vendors."},"vendor_sku":{"type":["string","null"],"description":"The vendor's own number for the style. Only returned to a key that may see vendors."},"variants":{"type":"array","description":"The style's variants. Every style has at least its default one.","items":{"type":"object","properties":{"id":{"type":"string","description":"The variant's id."},"label":{"type":"string","description":"What the variant is called, such as a ring size. Empty on a style's single default variant."},"attribute_key":{"type":"string","description":"What varies, such as RING_SIZE. DEFAULT on the default variant."},"attribute_value":{"type":"string","description":"The value of that attribute, such as 6.5."},"sku_suffix":{"type":"string","description":"What is added to the style number to make this variant's SKU."},"metal_weight_grams":{"type":"number","description":"The variant's own metal weight in grams. 0 means the style's weight applies."},"is_default":{"type":"boolean","description":"True on the one variant every style has."},"status":{"type":"string","description":"ACTIVE or INACTIVE.","enum":["ACTIVE","INACTIVE"]}},"required":["id","label","attribute_key","attribute_value","sku_suffix","metal_weight_grams","is_default","status"]}},"created_at":{"type":"string","format":"date-time","description":"When the style was created."},"updated_at":{"type":"string","format":"date-time","description":"When the style last changed."}},"required":["id","style","name","category","collection","metal_type","karat","description","image_url","metal_weight_grams","status","archived_at","wholesale_price","msrp","variants","created_at","updated_at"]},"StyleCreate":{"type":"object","properties":{"style":{"type":"string","description":"The style number. Left out, the next number in the workspace's own sequence is used."},"name":{"type":"string","description":"The style's name."},"category":{"type":"string","description":"The category. RING unless said.","enum":["RING","NECKLACE","EARRING","BRACELET","PENDANT"]},"collection":{"type":"string","description":"The collection the style belongs to."},"metal_type":{"type":"string","description":"The metal, such as GOLD, PLATINUM or SILVER. GOLD unless said. Needs a key that can see cost."},"karat":{"type":"string","description":"The purity, such as 14K or 950. Left out when the style is made, the metal's usual purity is used. Needs a key that can see cost."},"metal_weight_grams":{"type":"number","description":"The metal weight of one piece, in grams. Needs a key that can see cost."},"labor_cost":{"type":["string","number"],"examples":["1250.00"],"description":"The labor cost of one piece. Needs a key that can see cost."},"markup":{"type":"number","description":"What the cost is multiplied by to reach the retail price. Needs a key that can see cost and margin."},"description":{"type":"string","description":"The description."},"status":{"type":"string","description":"The status. ACTIVE unless said.","enum":["ACTIVE","DRAFT","DISCONTINUED"]},"vendor_id":{"type":"string","description":"The vendor the style is bought from. Needs a key that can see vendors."},"vendor_sku":{"type":"string","description":"That vendor's own number for the style. Needs a key that can see vendors."}},"required":["name"],"additionalProperties":false},"StyleUpdate":{"type":"object","properties":{"name":{"type":"string","description":"The style's name."},"category":{"type":"string","description":"The category. RING unless said.","enum":["RING","NECKLACE","EARRING","BRACELET","PENDANT"]},"collection":{"type":"string","description":"The collection the style belongs to."},"metal_type":{"type":"string","description":"The metal, such as GOLD, PLATINUM or SILVER. GOLD unless said. Needs a key that can see cost."},"karat":{"type":"string","description":"The purity, such as 14K or 950. Left out when the style is made, the metal's usual purity is used. Needs a key that can see cost."},"metal_weight_grams":{"type":"number","description":"The metal weight of one piece, in grams. Needs a key that can see cost."},"labor_cost":{"type":["string","number"],"examples":["1250.00"],"description":"The labor cost of one piece. Needs a key that can see cost."},"markup":{"type":"number","description":"What the cost is multiplied by to reach the retail price. Needs a key that can see cost and margin."},"description":{"type":"string","description":"The description."},"status":{"type":"string","description":"The status. ACTIVE unless said.","enum":["ACTIVE","DRAFT","DISCONTINUED"]},"vendor_id":{"type":["string","null"],"description":"The vendor the style is bought from. Needs a key that can see vendors. Send null to clear it."},"vendor_sku":{"type":["string","null"],"description":"That vendor's own number for the style. Needs a key that can see vendors. Send null to clear it."}},"required":[],"additionalProperties":false,"minProperties":1},"StyleBom":{"type":"object","properties":{"id":{"type":"string","description":"The line's id."},"stock_item_id":{"type":["string","null"],"description":"The stock item the line draws from, when it is linked to one."},"component":{"type":"string","description":"What the part is."},"type":{"type":"string","description":"The kind of line, such as METAL, STONE, FINDING, LABOR or SERVICE."},"quantity":{"type":"number","description":"How many, in the line's unit."},"unit":{"type":"string","description":"The unit the quantity is in, such as EACH, GRAM or CARAT."},"price_basis":{"type":"string","description":"How the line is priced, such as PER_PIECE or PER_CARAT."},"unit_cost":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The cost of one unit. Only returned to a key that may see cost."},"line_cost":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The cost of the whole line. Only returned to a key that may see cost."},"note":{"type":["string","null"],"description":"A note on the line."},"metal_type":{"type":["string","null"],"description":"The metal, on a metal line."},"metal_color":{"type":["string","null"],"description":"The metal's colour."},"karat":{"type":["string","null"],"description":"The purity, on a metal line."},"weight_grams":{"type":["number","null"],"description":"The weight in grams, on a metal line."},"stone_type":{"type":["string","null"],"description":"The stone, on a stone line."},"shape":{"type":["string","null"],"description":"The stone's shape."},"color":{"type":["string","null"],"description":"The stone's colour grade."},"clarity":{"type":["string","null"],"description":"The stone's clarity grade."},"cut":{"type":["string","null"],"description":"The stone's cut grade."},"carat_weight":{"type":["number","null"],"description":"The stone's weight in carats."},"dimensions":{"type":["string","null"],"description":"The stone's measurements."},"stone_origin":{"type":["string","null"],"description":"Where the stone comes from: natural, lab grown and so on."},"cert_lab":{"type":["string","null"],"description":"The grading lab."},"cert_number":{"type":["string","null"],"description":"The grading report number."},"finding_type":{"type":["string","null"],"description":"The kind of finding."},"labor_op":{"type":["string","null"],"description":"The labour operation."}},"required":["id","stock_item_id","component","type","quantity","unit","price_basis","note","metal_type","metal_color","karat","weight_grams","stone_type","shape","color","clarity","cut","carat_weight","dimensions","stone_origin","cert_lab","cert_number","finding_type","labor_op"]},"StyleCosting":{"type":"object","properties":{"style_id":{"type":"string","description":"The style the breakdown is for."},"as_of":{"type":"string","format":"date-time","description":"When the breakdown was computed."},"currency":{"type":"string","description":"The workspace's currency, as an ISO 4217 code."},"metal":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"Metal cost."},"stones":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"Stone cost."},"findings":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"Findings and other materials."},"labor":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"Labour: the style's own labour plus labour and service lines on the parts list."},"duties":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"Duties."},"total":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The live total: metal + stones + findings + labor + duties."},"stored_total_cost":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The cost stored on the style."},"stored_matches_live":{"type":"boolean","description":"True when the stored cost and the live total agree to the half-cent."},"metal_unresolved":{"type":"boolean","description":"True when some metal on the style could not be priced, so the total understates it."},"contract_status":{"type":"string","description":"none: costed from the parts list. ok: metal and labour come from a supplier contract. blocked: a contract exists but did not resolve, so this is an estimate.","enum":["none","ok","blocked"]}},"required":["style_id","as_of","currency","metal","stones","findings","labor","duties","total","stored_total_cost","stored_matches_live","metal_unresolved","contract_status"]},"StockItem":{"type":"object","properties":{"id":{"type":"string","description":"The stock item's id. Stable for the life of the record."},"sku":{"type":"string","description":"The SKU, unique in the workspace."},"name":{"type":"string","description":"The item's name."},"category":{"type":"string","description":"FINISHED_GOOD for a style's stock, otherwise the kind of component.","enum":["DIAMOND","GEMSTONE","METAL","FINDING","CASTING","FINISHED_GOOD","SCRAP","SERVICE"]},"description":{"type":["string","null"],"description":"The item's description."},"unit":{"type":"string","description":"The unit quantities are in, such as EACH, GRAM or CARAT."},"on_hand":{"type":"number","description":"How much is on hand."},"reserved":{"type":"number","description":"How much of that is held for confirmed orders."},"reorder_point":{"type":"number","description":"The level at or below which the item counts as low."},"by_location":{"type":"array","description":"Where the stock is, one record per location that holds some. Empty when the workspace does not track locations.","items":{"type":"object","properties":{"location_id":{"type":["string","null"],"description":"The location's id. Null for the main location while it has no record of its own."},"name":{"type":"string","description":"The location's name."},"code":{"type":"string","description":"The location's short code."},"quantity":{"type":"number","description":"How much of the item is there."},"pieces":{"type":"integer","description":"How many numbered pieces of the item are there."},"in_transit":{"type":"boolean","description":"True for stock a transfer is carrying between two locations."}},"required":["location_id","name","code","quantity","pieces","in_transit"]}},"retail_price":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The item's retail price."},"unit_cost":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The cost of one unit. 0 on a vendor's stock (goods held on memo from a vendor, not owned): their buy price is on each of their pieces. Only returned to a key that may see cost."},"style_id":{"type":["string","null"],"description":"The style this item is the stock of, on a finished good."},"variant_id":{"type":["string","null"],"description":"The variant this item is the stock of, on a finished good."},"vendor_id":{"type":["string","null"],"description":"The vendor the item is bought from. Only returned to a key that may see vendors."},"vendor_sku":{"type":["string","null"],"description":"The vendor's own number for the item. Only returned to a key that may see vendors."},"metal_type":{"type":["string","null"],"description":"The metal."},"karat":{"type":["string","null"],"description":"The purity."},"weight_grams":{"type":["number","null"],"description":"The weight in grams."},"stone_type":{"type":["string","null"],"description":"The stone."},"shape":{"type":["string","null"],"description":"The stone's shape."},"carat_weight":{"type":["number","null"],"description":"The stone's weight in carats."},"color":{"type":["string","null"],"description":"The stone's colour grade."},"clarity":{"type":["string","null"],"description":"The stone's clarity grade."},"cut":{"type":["string","null"],"description":"The stone's cut grade."},"cert_lab":{"type":["string","null"],"description":"The grading lab."},"cert_number":{"type":["string","null"],"description":"The grading report number."},"stone_origin":{"type":["string","null"],"description":"Where the stone comes from: natural, lab grown and so on."},"image_url":{"type":["string","null"],"description":"The item's image."},"created_at":{"type":"string","format":"date-time","description":"When the item was created."},"updated_at":{"type":"string","format":"date-time","description":"When the item last changed."}},"required":["id","sku","name","category","description","unit","on_hand","reserved","reorder_point","by_location","retail_price","style_id","variant_id","metal_type","karat","weight_grams","stone_type","shape","carat_weight","color","clarity","cut","cert_lab","cert_number","stone_origin","image_url","created_at","updated_at"]},"StockItemAdjust":{"type":"object","properties":{"delta":{"type":"number","description":"How much on hand goes up (a positive number) or down (a negative one). Never 0, and at most 3 decimal places. On hand is not set to this figure: it changes by it."},"type":{"type":"string","description":"What kind of change it is. ADJUST unless said.","enum":["RECEIPT","ISSUE","ADJUST","RETURN","SCRAP"]},"reference":{"type":"string","description":"A reference for the change, up to 100 characters."},"note":{"type":"string","description":"Why stock changed, up to 500 characters."}},"required":["delta"],"additionalProperties":false},"Piece":{"type":"object","properties":{"id":{"type":"string","description":"The piece's id. Stable for the life of the record."},"number":{"type":"string","description":"The piece's own number, which is also its barcode."},"stock_item_id":{"type":"string","description":"The stock item the piece belongs to."},"sku":{"type":"string","description":"That stock item's SKU."},"style_id":{"type":["string","null"],"description":"The style the piece is one of."},"variant_id":{"type":["string","null"],"description":"The variant the piece is."},"status":{"type":"string","description":"Where the piece stands.","enum":["IN_STOCK","RESERVED","SOLD","RETURNED","CONSUMED","ON_MEMO","IN_REPAIR"]},"location_id":{"type":["string","null"],"description":"Where the piece is. Null in a workspace that does not track locations, or for a piece at the main location."},"weight_grams":{"type":["number","null"],"description":"The piece's own metal weight in grams."},"unit_cost":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"What the piece cost. For a vendor's piece, held on memo from a vendor and not yet bought, it is the buy price: what the shop pays the vendor if it sells or keeps it. It is not stock value; the shop's inventory value never counts a vendor's piece. Only returned to a key that may see cost."},"cert_lab":{"type":["string","null"],"description":"The grading lab."},"cert_number":{"type":["string","null"],"description":"The grading report number."},"stone_origin":{"type":["string","null"],"description":"Where the stone comes from: natural, lab grown and so on."},"notes":{"type":["string","null"],"description":"Notes on the piece."},"received_at":{"type":"string","format":"date-time","description":"When the piece came into stock."},"created_at":{"type":"string","format":"date-time","description":"When the record was created."}},"required":["id","number","stock_item_id","sku","style_id","variant_id","status","location_id","weight_grams","cert_lab","cert_number","stone_origin","notes","received_at","created_at"]},"Location":{"type":"object","properties":{"id":{"type":"string","description":"The location's id."},"name":{"type":"string","description":"The location's name."},"code":{"type":"string","description":"The location's short code, unique in the workspace."},"kind":{"type":"string","description":"What kind of place it is, such as VAULT, SHOWROOM or BENCH."},"parent_id":{"type":["string","null"],"description":"The location this one sits inside."},"selling":{"type":"boolean","description":"True when stock here can be sold."},"active":{"type":"boolean","description":"False once the location is retired."},"in_transit":{"type":"boolean","description":"True for the one location that holds stock a transfer is carrying."},"created_at":{"type":"string","format":"date-time","description":"When the location was created."},"updated_at":{"type":"string","format":"date-time","description":"When the location last changed."}},"required":["id","name","code","kind","parent_id","selling","active","in_transit","created_at","updated_at"]},"Customer":{"type":"object","properties":{"id":{"type":"string","description":"The customer's id. Stable for the life of the record."},"code":{"type":"string","description":"The customer's code, unique in the workspace."},"name":{"type":"string","description":"The customer's name."},"company":{"type":["string","null"],"description":"The company name."},"email":{"type":["string","null"],"description":"The customer's email."},"phone":{"type":["string","null"],"description":"The customer's phone."},"type":{"type":"string","description":"What kind of customer.","enum":["WHOLESALE","RETAILER","DESIGNER","DEALER"]},"tier":{"type":"string","description":"The customer's tier.","enum":["STANDARD","PREFERRED","VIP"]},"terms":{"type":"string","description":"Payment terms, such as NET_30."},"credit_limit":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The credit limit. 0.00 means none is set."},"balance":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"What the customer owes now."},"credit_hold":{"type":"boolean","description":"True when the customer is on credit hold."},"tax_exempt":{"type":"boolean","description":"True when sales to the customer are not taxed."},"address_line":{"type":["string","null"],"description":"Street address."},"city":{"type":["string","null"],"description":"City."},"state":{"type":["string","null"],"description":"State or region."},"postal_code":{"type":["string","null"],"description":"Postal code."},"country":{"type":["string","null"],"description":"Country."},"notes":{"type":["string","null"],"description":"Notes on the customer."},"created_at":{"type":"string","format":"date-time","description":"When the customer was created."},"updated_at":{"type":"string","format":"date-time","description":"When the customer last changed."}},"required":["id","code","name","company","email","phone","type","tier","terms","credit_limit","balance","credit_hold","tax_exempt","address_line","city","state","postal_code","country","notes","created_at","updated_at"]},"CustomerCreate":{"type":"object","properties":{"code":{"type":"string","description":"The customer's code. Left out, the next code in the workspace's own sequence is used."},"name":{"type":"string","description":"The customer's name."},"company":{"type":"string","description":"The company name."},"email":{"type":"string","description":"The customer's email."},"phone":{"type":"string","description":"The customer's phone."},"type":{"type":"string","description":"What kind of customer. WHOLESALE unless said.","enum":["WHOLESALE","RETAILER","DESIGNER","DEALER"]},"tier":{"type":"string","description":"The customer's tier. STANDARD unless said.","enum":["STANDARD","PREFERRED","VIP"]},"terms":{"type":"string","description":"Payment terms, such as NET_30."},"credit_limit":{"type":["string","number"],"examples":["1250.00"],"description":"The credit limit. 0 means no limit."},"tax_exempt":{"type":"boolean","description":"True when sales to the customer are not taxed."},"city":{"type":"string","description":"City."},"state":{"type":"string","description":"State or region."},"country":{"type":"string","description":"Country. USA unless said."},"notes":{"type":"string","description":"Notes on the customer."}},"required":["name"],"additionalProperties":false},"CustomerUpdate":{"type":"object","properties":{"name":{"type":"string","description":"The customer's name."},"company":{"type":"string","description":"The company name."},"email":{"type":"string","description":"The customer's email."},"phone":{"type":"string","description":"The customer's phone."},"type":{"type":"string","description":"What kind of customer. WHOLESALE unless said.","enum":["WHOLESALE","RETAILER","DESIGNER","DEALER"]},"tier":{"type":"string","description":"The customer's tier. STANDARD unless said.","enum":["STANDARD","PREFERRED","VIP"]},"terms":{"type":"string","description":"Payment terms, such as NET_30."},"credit_limit":{"type":["string","number"],"examples":["1250.00"],"description":"The credit limit. 0 means no limit."},"tax_exempt":{"type":"boolean","description":"True when sales to the customer are not taxed."},"city":{"type":"string","description":"City."},"state":{"type":"string","description":"State or region."},"notes":{"type":"string","description":"Notes on the customer."}},"required":[],"additionalProperties":false,"minProperties":1},"Vendor":{"type":"object","properties":{"id":{"type":"string","description":"The vendor's id. Stable for the life of the record."},"code":{"type":"string","description":"The vendor's code, unique in the workspace."},"name":{"type":"string","description":"The vendor's name."},"category":{"type":"string","description":"What the vendor supplies, such as METAL or STONES."},"email":{"type":["string","null"],"description":"The vendor's email."},"phone":{"type":["string","null"],"description":"The vendor's phone."},"terms":{"type":"string","description":"Payment terms, such as NET_30."},"balance":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"What the workspace owes the vendor now."},"lead_time_days":{"type":"integer","description":"The usual days from order to delivery."},"country":{"type":["string","null"],"description":"The vendor's country."},"default_currency":{"type":["string","null"],"description":"The currency the vendor is usually paid in."},"notes":{"type":["string","null"],"description":"Notes on the vendor."},"created_at":{"type":"string","format":"date-time","description":"When the vendor was created."},"updated_at":{"type":"string","format":"date-time","description":"When the vendor last changed."}},"required":["id","code","name","category","email","phone","terms","balance","lead_time_days","country","default_currency","notes","created_at","updated_at"]},"VendorCreate":{"type":"object","properties":{"code":{"type":"string","description":"The vendor's code. Left out, the next code in the workspace's own sequence is used."},"name":{"type":"string","description":"The vendor's name."},"category":{"type":"string","description":"What the vendor supplies, such as METAL or STONES. METAL unless said."},"email":{"type":"string","description":"The vendor's email."},"phone":{"type":"string","description":"The vendor's phone."},"terms":{"type":"string","description":"Payment terms, such as NET_30."},"lead_time_days":{"type":"integer","description":"The usual days from order to delivery."},"country":{"type":"string","description":"The vendor's country."},"default_currency":{"type":"string","description":"The currency the vendor is usually paid in, as a 3-letter code such as USD."},"notes":{"type":"string","description":"Notes on the vendor."}},"required":["name"],"additionalProperties":false},"VendorUpdate":{"type":"object","properties":{"name":{"type":"string","description":"The vendor's name."},"category":{"type":"string","description":"What the vendor supplies, such as METAL or STONES. METAL unless said."},"email":{"type":"string","description":"The vendor's email."},"phone":{"type":"string","description":"The vendor's phone."},"terms":{"type":"string","description":"Payment terms, such as NET_30."},"lead_time_days":{"type":"integer","description":"The usual days from order to delivery."},"country":{"type":["string","null"],"description":"The vendor's country. Send null to clear it."},"default_currency":{"type":["string","null"],"description":"The currency the vendor is usually paid in, as a 3-letter code such as USD. Send null to clear it."},"notes":{"type":"string","description":"Notes on the vendor."}},"required":[],"additionalProperties":false,"minProperties":1},"Quote":{"type":"object","properties":{"id":{"type":"string","description":"The quote's id. Stable for the life of the record."},"number":{"type":"string","description":"The quote number."},"customer_id":{"type":"string","description":"The customer the quote is for."},"status":{"type":"string","description":"Where the quote stands.","enum":["DRAFT","SENT","ACCEPTED","DECLINED","EXPIRED"]},"quote_date":{"type":"string","format":"date-time","description":"The quote's date."},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the quote stops being valid."},"subtotal":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The lines' total."},"discount_amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The discount off the whole quote."},"tax":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"Tax."},"shipping":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"Shipping."},"total":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The quote's total."},"notes":{"type":["string","null"],"description":"Notes on the quote."},"converted_order_id":{"type":["string","null"],"description":"The sales order the quote became, once accepted and converted."},"lines":{"type":"array","description":"The quote's lines.","items":{"type":"object","properties":{"id":{"type":"string","description":"The line's id."},"style_id":{"type":["string","null"],"description":"The style quoted, when the line is for one."},"stock_item_id":{"type":["string","null"],"description":"The stock item quoted, when the line is for one."},"description":{"type":"string","description":"What the line is for."},"quantity":{"type":"integer","description":"How many."},"unit_price":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The price of one."},"discount_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","description":"The line's discount, as a percentage."},"line_total":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The line's total after its discount."}},"required":["id","style_id","stock_item_id","description","quantity","unit_price","discount_pct","line_total"]}},"created_at":{"type":"string","format":"date-time","description":"When the quote was created."},"updated_at":{"type":"string","format":"date-time","description":"When the quote last changed."}},"required":["id","number","customer_id","status","quote_date","expires_at","subtotal","discount_amount","tax","shipping","total","notes","converted_order_id","lines","created_at","updated_at"]},"QuoteCreate":{"type":"object","properties":{"customer_id":{"type":"string","description":"The customer the quote is for."},"expires_at":{"type":"string","format":"date","description":"The last day the quote stands."},"shipping":{"type":["string","number"],"examples":["1250.00"],"description":"The shipping charge."},"discount_amount":{"type":["string","number"],"examples":["1250.00"],"description":"A discount on the whole quote, taken off before tax."},"notes":{"type":"string","description":"Notes on the quote."},"lines":{"type":"array","description":"The quote's lines.","maxItems":500,"items":{"type":"object","properties":{"description":{"type":"string","description":"What the line is for."},"quantity":{"type":"integer","description":"How many. 1 unless said."},"unit_price":{"type":["string","number"],"examples":["1250.00"],"description":"The price of one, before the line's discount. Send 0 for a line that really is free."},"discount_pct":{"type":"number","description":"A discount on this line, as a percent from 0 to 100."},"style_id":{"type":"string","description":"The style the line is for."},"stock_item_id":{"type":"string","description":"The stock item the line is for."}},"required":["description","unit_price"],"additionalProperties":false}}},"required":["customer_id"],"additionalProperties":false},"SalesOrder":{"type":"object","properties":{"id":{"type":"string","description":"The order's id. Stable for the life of the record."},"number":{"type":"string","description":"The order number."},"customer_id":{"type":"string","description":"The customer who ordered."},"status":{"type":"string","description":"Where the order stands.","enum":["DRAFT","CONFIRMED","IN_PRODUCTION","PARTIAL_SHIPPED","SHIPPED","INVOICED","PAID","CANCELLED"]},"order_date":{"type":"string","format":"date-time","description":"The order's date."},"ship_date":{"type":["string","null"],"format":"date-time","description":"When the order shipped, or is due to."},"customer_po_number":{"type":["string","null"],"description":"The customer's purchase order number."},"customer_po_date":{"type":["string","null"],"format":"date-time","description":"The date on the customer's purchase order."},"subtotal":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The lines' total."},"discount_amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The discount off the whole order."},"tax":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"Tax."},"shipping":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"Shipping."},"total":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The order's total."},"notes":{"type":["string","null"],"description":"Notes on the order."},"lines":{"type":"array","description":"The order's lines.","items":{"type":"object","properties":{"id":{"type":"string","description":"The line's id."},"style_id":{"type":["string","null"],"description":"The style ordered, when the line is for one."},"stock_item_id":{"type":["string","null"],"description":"The stock item the line draws from."},"description":{"type":"string","description":"What the line is for."},"customer_sku":{"type":["string","null"],"description":"The customer's own number for it."},"quantity":{"type":"integer","description":"How many were ordered."},"quantity_shipped":{"type":"integer","description":"How many have shipped."},"unit_price":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The price of one."},"line_total":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The line's total."},"unit_cost":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"What one cost. Only returned to a key that may see cost."},"cost_basis":{"type":"string","description":"Where that cost came from: the piece shipped, a snapshot, a derived figure, or unknown. Only returned to a key that may see cost."}},"required":["id","style_id","stock_item_id","description","customer_sku","quantity","quantity_shipped","unit_price","line_total"]}},"created_at":{"type":"string","format":"date-time","description":"When the order was created."},"updated_at":{"type":"string","format":"date-time","description":"When the order last changed."}},"required":["id","number","customer_id","status","order_date","ship_date","customer_po_number","customer_po_date","subtotal","discount_amount","tax","shipping","total","notes","lines","created_at","updated_at"]},"SalesOrderCreate":{"type":"object","properties":{"customer_id":{"type":"string","description":"The customer the order is for."},"customer_po_number":{"type":"string","description":"The customer's own purchase order number."},"customer_po_date":{"type":"string","format":"date","description":"The date on the customer's purchase order."},"ship_date":{"type":"string","format":"date","description":"The date the customer wants it shipped by."},"shipping":{"type":["string","number"],"examples":["1250.00"],"description":"The shipping charge."},"notes":{"type":"string","description":"Notes on the order."},"lines":{"type":"array","description":"The order's lines.","maxItems":500,"items":{"type":"object","properties":{"description":{"type":"string","description":"What the line is for."},"quantity":{"type":"integer","description":"How many. 1 unless said."},"unit_price":{"type":["string","number"],"examples":["1250.00"],"description":"The price of one. Send 0 for a line that really is free."},"style_id":{"type":"string","description":"The style the line is for. Its stock is what the order reserves once it is confirmed."},"stock_item_id":{"type":"string","description":"The stock item the line is for."},"customer_sku":{"type":"string","description":"The customer's own number for the line."}},"required":["description","unit_price"],"additionalProperties":false}}},"required":["customer_id"],"additionalProperties":false},"SalesOrderConfirm":{"type":"object","properties":{},"required":[],"additionalProperties":false},"SalesOrderShip":{"type":"object","properties":{"tracking":{"type":"string","description":"The carrier's tracking number, up to 100 characters."},"note":{"type":"string","description":"A note for the shipment, up to 500 characters."},"lines":{"type":"array","description":"The order lines to ship and how many of each. Leave it out to ship everything still open on the order: the quantities are fixed at what is open when you send this, and an admin approves exactly those.","maxItems":100,"items":{"type":"object","properties":{"line_id":{"type":"string","description":"The id of a line of this order."},"quantity":{"type":"integer","description":"How many to ship. No more than is still open on the line."}},"required":["line_id","quantity"],"additionalProperties":false}}},"required":[],"additionalProperties":false},"SalesOrderInvoice":{"type":"object","properties":{},"required":[],"additionalProperties":false},"SalesOrderPayments":{"type":"object","properties":{"amount":{"type":["string","number"],"examples":["1250.00"],"description":"How much was received. More than 0, and no more than is still owed on the invoice."},"method":{"type":"string","description":"How it was paid. WIRE unless said.","enum":["WIRE","CHECK","CARD","CASH","ACH"]},"reference":{"type":"string","description":"The check or wire number, up to 100 characters. An invoice takes each reference once."}},"required":["amount"],"additionalProperties":false},"Invoice":{"type":"object","properties":{"id":{"type":"string","description":"The invoice's id. Stable for the life of the record."},"number":{"type":"string","description":"The invoice number."},"customer_id":{"type":"string","description":"The customer invoiced."},"order_id":{"type":["string","null"],"description":"The sales order the invoice is for."},"status":{"type":"string","description":"Where the invoice stands today, worked out from what is still owed and the due date.","enum":["OPEN","PARTIAL","PAID","OVERDUE"]},"issue_date":{"type":"string","format":"date-time","description":"The invoice's date."},"due_date":{"type":["string","null"],"format":"date-time","description":"When payment is due."},"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The invoice's total."},"amount_paid":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"What has been paid against it."},"balance":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"What is still owed: amount less amount_paid."},"days_late":{"type":"integer","description":"Days past due while a balance is owed, otherwise 0."},"external_number":{"type":["string","null"],"description":"The invoice's number in a previous system, when it was moved in."},"created_at":{"type":"string","format":"date-time","description":"When the invoice was created."}},"required":["id","number","customer_id","order_id","status","issue_date","due_date","amount","amount_paid","balance","days_late","external_number","created_at"]},"Payment":{"type":"object","properties":{"id":{"type":"string","description":"The payment's id. Stable for the life of the record."},"kind":{"type":"string","description":"What the payment is: against an invoice, or a deposit on an order."},"invoice_id":{"type":["string","null"],"description":"The invoice paid."},"order_id":{"type":["string","null"],"description":"The sales order a deposit was taken on."},"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The amount received."},"method":{"type":"string","description":"How it was paid, such as WIRE, CHECK or CARD."},"reference":{"type":["string","null"],"description":"The payment's reference, such as a check number."},"received_at":{"type":"string","format":"date-time","description":"When it was received."},"refunded_at":{"type":["string","null"],"format":"date-time","description":"When it was refunded, if it was."},"refund_method":{"type":["string","null"],"description":"How the refund was sent."},"refund_reference":{"type":["string","null"],"description":"The refund's reference."}},"required":["id","kind","invoice_id","order_id","amount","method","reference","received_at","refunded_at","refund_method","refund_reference"]},"Memo":{"type":"object","properties":{"id":{"type":"string","description":"The memo's id. Stable for the life of the record."},"number":{"type":"string","description":"The memo number."},"customer_id":{"type":"string","description":"The customer holding the goods."},"status":{"type":"string","description":"Where the memo stands.","enum":["OUT","PARTIAL_RETURN","RETURNED","SOLD","OVERDUE","DISPOSED","SETTLED"]},"issue_date":{"type":"string","format":"date-time","description":"When the goods went out."},"due_date":{"type":["string","null"],"format":"date-time","description":"When they are due back or due to be paid for."},"total_value":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The value of what is out."},"stated_value":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The value stated for shipping and insurance."},"carrier":{"type":["string","null"],"description":"Who carried the goods."},"notes":{"type":["string","null"],"description":"Notes on the memo."},"external_number":{"type":["string","null"],"description":"The memo's number in a previous system, when it was moved in."},"lines":{"type":"array","description":"The memo's lines.","items":{"type":"object","properties":{"id":{"type":"string","description":"The line's id."},"stock_item_id":{"type":["string","null"],"description":"The stock item sent out."},"description":{"type":"string","description":"What the line is for."},"quantity":{"type":"integer","description":"How many are still on the line."},"value":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The value of the line."},"status":{"type":"string","description":"Where the line stands.","enum":["OUT","RETURNED","SOLD","LOST","DAMAGED"]},"pieces":{"type":"array","description":"The numbered pieces sent out on the line.","items":{"type":"object","properties":{"piece_id":{"type":"string","description":"The piece sent out."},"outcome":{"type":["string","null"],"description":"What became of it: RETURNED, SOLD, LOST or DAMAGED. Null while it is still out."},"resolved_at":{"type":["string","null"],"format":"date-time","description":"When that was recorded."}},"required":["piece_id","outcome","resolved_at"]}}},"required":["id","stock_item_id","description","quantity","value","status","pieces"]}},"created_at":{"type":"string","format":"date-time","description":"When the memo was created."},"updated_at":{"type":"string","format":"date-time","description":"When the memo last changed."}},"required":["id","number","customer_id","status","issue_date","due_date","total_value","stated_value","carrier","notes","external_number","lines","created_at","updated_at"]},"MemoSettle":{"type":"object","properties":{"line_id":{"type":"string","description":"The id of a line of this memo."},"outcome":{"type":"string","description":"sold: the customer is keeping the goods, and Karatry makes a draft sales order for them. returned: the goods are back, and go into stock.","enum":["sold","returned"]},"quantity":{"type":"integer","description":"How many to settle. No more than is still out on the line. A line that went out as numbered pieces is settled all at once: ask for every piece still out on it."}},"required":["line_id","outcome","quantity"],"additionalProperties":false},"PurchaseOrder":{"type":"object","properties":{"id":{"type":"string","description":"The purchase order's id. Stable for the life of the record."},"number":{"type":"string","description":"The purchase order number."},"vendor_id":{"type":"string","description":"The vendor ordered from. Only returned to a key that may see vendors."},"status":{"type":"string","description":"Where the order stands.","enum":["DRAFT","SENT","PARTIAL","RECEIVED","CANCELLED"]},"order_date":{"type":"string","format":"date-time","description":"The order's date."},"expected_date":{"type":["string","null"],"format":"date-time","description":"When the goods are expected."},"subtotal":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The lines' total. Only returned to a key that may see vendors."},"total":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The order's total. Only returned to a key that may see vendors."},"notes":{"type":["string","null"],"description":"Notes on the order."},"external_number":{"type":["string","null"],"description":"The order's number in a previous system, when it was moved in."},"lines":{"type":"array","description":"The order's lines.","items":{"type":"object","properties":{"id":{"type":"string","description":"The line's id."},"stock_item_id":{"type":["string","null"],"description":"The stock item ordered."},"description":{"type":"string","description":"What the line is for."},"quantity":{"type":"number","description":"How much was ordered."},"received":{"type":"number","description":"How much has been received."},"unit_cost":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The vendor's price for one unit. Only returned to a key that may see vendors."},"line_total":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The line's total. Only returned to a key that may see vendors."},"received_value":{"type":["string","null"],"pattern":"^-?\\d+\\.\\d{2}$","examples":["1250.00"],"description":"The value of what has been received. Only returned to a key that may see vendors."}},"required":["id","stock_item_id","description","quantity","received"]}},"created_at":{"type":"string","format":"date-time","description":"When the order was created."},"updated_at":{"type":"string","format":"date-time","description":"When the order last changed."}},"required":["id","number","status","order_date","expected_date","notes","external_number","lines","created_at","updated_at"]},"PurchaseOrderCreate":{"type":"object","properties":{"vendor_id":{"type":"string","description":"The vendor the order is placed with. Needs a key that can see vendors."},"expected_date":{"type":"string","format":"date","description":"When the goods are expected."},"notes":{"type":"string","description":"Notes on the order."},"lines":{"type":"array","description":"The order's lines. At least one.","minItems":1,"maxItems":500,"items":{"type":"object","properties":{"description":{"type":"string","description":"What is being bought."},"quantity":{"type":"number","description":"How much, to at most four decimals. 1 unless said."},"unit_cost":{"type":["string","number"],"examples":["1250.00"],"description":"The cost of one. Send 0 for a line that really is free. Needs a key that can see vendors."},"stock_item_id":{"type":"string","description":"The stock item the line buys."}},"required":["description","unit_cost"],"additionalProperties":false}}},"required":["vendor_id","lines"],"additionalProperties":false},"PurchaseOrderReceive":{"type":"object","properties":{"lines":{"type":"array","description":"The purchase order lines to receive and how much of each. Leave it out to receive everything still open on the order: the quantities are fixed at what is open when you send this, and an admin approves exactly those. Each line is received at the order's own price.","maxItems":100,"items":{"type":"object","properties":{"line_id":{"type":"string","description":"The id of a line of this purchase order."},"quantity":{"type":"number","description":"How much to receive. No more than is still open on the line."}},"required":["line_id","quantity"],"additionalProperties":false}}},"required":[],"additionalProperties":false},"MetalPrice":{"type":"object","properties":{"id":{"type":"string","description":"The price record's id."},"metal":{"type":"string","description":"The metal, such as GOLD, SILVER or PLATINUM."},"price_per_ozt":{"type":"number","description":"The price of one troy ounce of the pure metal, in the workspace's currency."},"change_pct":{"type":"number","description":"The change since the price before, as a percentage."},"updated_at":{"type":"string","format":"date-time","description":"When the price was last refreshed."}},"required":["id","metal","price_per_ozt","change_pct","updated_at"]},"Proposal":{"type":"object","properties":{"id":{"type":"string","description":"The request's id."},"status":{"type":"string","description":"Where the request stands. waiting: an admin has not decided yet, or an approval is being carried out right now. approved: an admin approved it and it ran. unconfirmed: an admin approved it, but Karatry could not confirm that it ran; read the record to see where it stands, and send a new request if it did not happen (this one is closed and will never run again). dismissed: an admin turned it down. withdrawn: the key took it back. expired: nobody decided within 7 days, so it can no longer be approved.","enum":["waiting","approved","unconfirmed","dismissed","withdrawn","expired"]},"move":{"type":"string","description":"What was asked for.","enum":["confirm","ship","invoice","payment","receive","settle","adjust"]},"record":{"type":"object","properties":{"type":{"type":"string","description":"The kind of record.","enum":["sales_order","purchase_order","memo","stock_item"]},"id":{"type":"string","description":"The record's id."},"number":{"type":"string","description":"The record's number when the request was filed. For a stock item, its SKU."}},"required":["type","id","number"],"description":"The record the request is about."},"filed_at":{"type":"string","format":"date-time","description":"When the request was filed."},"expires_at":{"type":"string","format":"date-time","description":"When a request that is still waiting stops being approvable: 7 days after it was filed."},"decided_at":{"type":["string","null"],"format":"date-time","description":"When it was approved, dismissed or withdrawn. Null while the request is waiting."},"changed_since_filed":{"type":["boolean","null"],"description":"While the request is waiting: true when the record has changed since it was filed, so it can no longer be approved as it stands. Withdraw it and send a new one. Null once an admin has decided or the request has expired."},"result":{"type":["object","null"],"properties":{"type":{"type":"string","description":"The kind of record."},"id":{"type":"string","description":"The record's id."}},"required":["type","id"],"description":"Once approved: the record the move changed or made. Null until then."}},"required":["id","status","move","record","filed_at","expires_at","decided_at","changed_since_filed","result"]},"ProposalWithdraw":{"type":"object","properties":{},"required":[],"additionalProperties":false},"WebhookSalesOrderConfirmed":{"type":"object","properties":{"id":{"type":"string","description":"The event's id. The same on every delivery and every retry of this event, so a receiver can ignore one it has already handled."},"type":{"type":"string","const":"sales_order.confirmed","description":"The event type."},"created_at":{"type":"string","format":"date-time","description":"When the change was saved."},"api_version":{"type":"string","description":"Always v1."},"data":{"type":"object","properties":{"id":{"type":"string","description":"The order's id. Read it at /api/v1/sales-orders/{id}."},"number":{"type":"string","description":"The order number."},"customer_id":{"type":"string","description":"The customer who ordered."},"status":{"type":"string","description":"Where the order stands when the change was saved."},"order_date":{"type":"string","format":"date-time","description":"The order's date."},"ship_date":{"type":["string","null"],"format":"date-time","description":"When the order is due to ship."},"customer_po_number":{"type":["string","null"],"description":"The customer's purchase order number."},"total":{"type":"string","examples":["1250.00"],"description":"The order's total."},"split_from_order_id":{"type":["string","null"],"description":"Set when this order was split off another: the goods still owed on an order that shipped in part moved here. That order's total is now lower by this one's, so read it again rather than adding the two events."}},"required":["id","number","customer_id","status","order_date","ship_date","customer_po_number","total","split_from_order_id"]}},"required":["id","type","created_at","api_version","data"]},"WebhookInvoiceIssued":{"type":"object","properties":{"id":{"type":"string","description":"The event's id. The same on every delivery and every retry of this event, so a receiver can ignore one it has already handled."},"type":{"type":"string","const":"invoice.issued","description":"The event type."},"created_at":{"type":"string","format":"date-time","description":"When the change was saved."},"api_version":{"type":"string","description":"Always v1."},"data":{"type":"object","properties":{"id":{"type":"string","description":"The invoice's id. Read it at /api/v1/invoices/{id}."},"number":{"type":"string","description":"The invoice number."},"customer_id":{"type":"string","description":"The customer invoiced."},"order_id":{"type":["string","null"],"description":"The sales order the invoice is for."},"status":{"type":"string","description":"OPEN; PARTIAL when a deposit covered part of it; PAID when nothing was left to pay."},"issue_date":{"type":"string","format":"date-time","description":"The invoice's date."},"due_date":{"type":["string","null"],"format":"date-time","description":"When payment is due."},"amount":{"type":"string","examples":["1250.00"],"description":"The invoice's total."},"amount_paid":{"type":"string","examples":["1250.00"],"description":"What has been paid against it."}},"required":["id","number","customer_id","order_id","status","issue_date","due_date","amount","amount_paid"]}},"required":["id","type","created_at","api_version","data"]},"WebhookPaymentReceived":{"type":"object","properties":{"id":{"type":"string","description":"The event's id. The same on every delivery and every retry of this event, so a receiver can ignore one it has already handled."},"type":{"type":"string","const":"payment.received","description":"The event type."},"created_at":{"type":"string","format":"date-time","description":"When the change was saved."},"api_version":{"type":"string","description":"Always v1."},"data":{"type":"object","properties":{"id":{"type":"string","description":"The payment's id. Read it at /api/v1/payments/{id}."},"kind":{"type":"string","description":"What the payment is: against an invoice, or a deposit on an order."},"invoice_id":{"type":["string","null"],"description":"The invoice paid."},"order_id":{"type":["string","null"],"description":"The sales order a deposit was taken on."},"customer_id":{"type":["string","null"],"description":"The customer who paid."},"amount":{"type":"string","examples":["1250.00"],"description":"The amount received."},"method":{"type":"string","description":"How it was paid."},"reference":{"type":["string","null"],"description":"The cheque number, wire reference and so on."},"received_at":{"type":"string","format":"date-time","description":"When it was received."}},"required":["id","kind","invoice_id","order_id","customer_id","amount","method","reference","received_at"]}},"required":["id","type","created_at","api_version","data"]},"WebhookMemoSettled":{"type":"object","properties":{"id":{"type":"string","description":"The event's id. The same on every delivery and every retry of this event, so a receiver can ignore one it has already handled."},"type":{"type":"string","const":"memo.settled","description":"The event type."},"created_at":{"type":"string","format":"date-time","description":"When the change was saved."},"api_version":{"type":"string","description":"Always v1."},"data":{"type":"object","properties":{"memo_id":{"type":"string","description":"The memo's id. Read it at /api/v1/memos/{id}."},"memo_number":{"type":"string","description":"The memo number."},"customer_id":{"type":"string","description":"The customer holding the goods."},"line_id":{"type":"string","description":"The memo line settled."},"stock_item_id":{"type":["string","null"],"description":"The stock item on the line."},"outcome":{"type":"string","description":"SOLD, RETURNED, LOST or DAMAGED."},"quantity":{"type":"integer","description":"How many were settled this time."},"line_status":{"type":"string","description":"Where the line stands now."}},"required":["memo_id","memo_number","customer_id","line_id","stock_item_id","outcome","quantity","line_status"]}},"required":["id","type","created_at","api_version","data"]},"WebhookPieceCreated":{"type":"object","properties":{"id":{"type":"string","description":"The event's id. The same on every delivery and every retry of this event, so a receiver can ignore one it has already handled."},"type":{"type":"string","const":"piece.created","description":"The event type."},"created_at":{"type":"string","format":"date-time","description":"When the change was saved."},"api_version":{"type":"string","description":"Always v1."},"data":{"type":"object","properties":{"id":{"type":"string","description":"The piece's id. Read it at /api/v1/pieces/{id}."},"number":{"type":"string","description":"The piece's own number, which is also its barcode."},"stock_item_id":{"type":"string","description":"The stock item the piece belongs to."},"sku":{"type":"string","description":"That stock item's SKU."},"status":{"type":"string","description":"Where the piece stands."},"location_id":{"type":["string","null"],"description":"Where the piece is, in a workspace that tracks locations."}},"required":["id","number","stock_item_id","sku","status","location_id"]}},"required":["id","type","created_at","api_version","data"]},"WebhookPieceSold":{"type":"object","properties":{"id":{"type":"string","description":"The event's id. The same on every delivery and every retry of this event, so a receiver can ignore one it has already handled."},"type":{"type":"string","const":"piece.sold","description":"The event type."},"created_at":{"type":"string","format":"date-time","description":"When the change was saved."},"api_version":{"type":"string","description":"Always v1."},"data":{"type":"object","properties":{"id":{"type":"string","description":"The piece's id. Read it at /api/v1/pieces/{id}."},"number":{"type":"string","description":"The piece's own number, which is also its barcode."},"stock_item_id":{"type":"string","description":"The stock item the piece belongs to."},"sku":{"type":"string","description":"That stock item's SKU."},"status":{"type":"string","description":"Where the piece stands."},"location_id":{"type":["string","null"],"description":"Where the piece is, in a workspace that tracks locations."},"order_id":{"type":"string","description":"The sales order it shipped on."}},"required":["id","number","stock_item_id","sku","status","location_id","order_id"]}},"required":["id","type","created_at","api_version","data"]},"WebhookStockChanged":{"type":"object","properties":{"id":{"type":"string","description":"The event's id. The same on every delivery and every retry of this event, so a receiver can ignore one it has already handled."},"type":{"type":"string","const":"stock.changed","description":"The event type."},"created_at":{"type":"string","format":"date-time","description":"When the change was saved."},"api_version":{"type":"string","description":"Always v1."},"data":{"type":"object","properties":{"id":{"type":"string","description":"The stock item's id. Read it at /api/v1/stock-items/{id}."},"sku":{"type":"string","description":"The SKU."},"unit":{"type":"string","description":"The unit quantities are in."},"on_hand":{"type":"number","description":"How much is on hand."},"reserved":{"type":"number","description":"How much of that is held for confirmed orders."}},"required":["id","sku","unit","on_hand","reserved"]}},"required":["id","type","created_at","api_version","data"]}}}}