List your order submissions
const url = 'https://api.partners.collaterate.com/v1/orders/submissions?status=queued&limit=50';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://api.partners.collaterate.com/v1/orders/submissions?status=queued&limit=50' \ --header 'Authorization: Bearer <token>'Keyset-paginated listing of every submission you have created, newest first. Use this
to discover submissions or reconcile the full set; once you have a specific
submissionId, poll it directly with GET /v1/orders/submissions/{submissionId}
(below) rather than paging through this list to find it again.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”Restrict the result to submissions with this exact status.
Opaque pagination token from a previous response’s nextCursor. Do not parse it,
construct it, or rely on its format staying the same. Pass it back as received.
Page size. Defaults to 50. Values above 100 are rejected, not capped.
Responses
Section titled “Responses”A page of submissions.
object
The resource both POST /v1/orders and GET /v1/orders/submissions/{submissionId}
return – the identical shape from both, described in full on the create operation.
object
Opaque id to poll with. Belongs to the partner that created it – see submission_not_found.
queued and processing are transient; poll again. completed and failed are
terminal and never revert – completed populates order, failed populates
errors.
Present only when status is completed.
object
One priced line of a completed submission’s order, in Submission.order.lines.
Every money field here is a whole-line amount and a JSON number. None is a per-unit
price, so never multiply by quantity. Treat this object as a receipt: for money you
intend to reconcile against, read GET /v1/orders/{orderNumber}/items, which publishes
decimal strings and the authoritative post-adjustment total.
object
Echoes the partnerLineId you submitted, so you can match this line back to your request.
The quantity being produced for this line. Published so the amounts below can be interpreted at all - they are line totals, not unit prices.
The whole line’s extended list amount, before discounts and adjustments. Priced by
Collaterate; you never send a price on submission. Called unitPrice before
2026-07-29, which was wrong - it has never been a per-unit figure. Same value as
OrderItem.lineListTotal, which publishes it as an exact decimal string.
The whole line’s total before adjustments, and deliberately not called lineTotal
because it is a different number from OrderItem.lineTotal, which is measured after
them. Collaterate reports the ORDER total after adjustments while reporting each LINE
before them, so on an adjusted line these will not sum to SubmittedOrder.totalPrice.
Reconcile against GET /v1/orders/{orderNumber}/items.
Present only when status is failed.
One reason a submission was rejected, in Submission.errors. code is our own
stable identifier, mapped from whatever Collaterate rejected the order for – not
a Problem.code: a SubmissionError describes why an accepted, well-formed request
could not be turned into an order, which is a different kind of failure from a
malformed request or an authentication problem.
object
Stable identifier for this rejection reason. order_rejected is the value in
practice today – one entry per problem Collaterate reported, per-line where the
rejection names a line.
Human-readable explanation. Do not parse this – it may be reworded without notice.
The request field this rejection concerns, if it names one.
The partnerLineId this rejection concerns, if it is about one line rather than the whole order.
Opaque cursor for the next page, or null when this is the last page.
Terminate your loop on null and on nothing else.
Examples
{ "submissions": [ { "submissionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "status": "completed", "order": { "orderNumber": 1000234, "status": "NEW", "totalPrice": 245.5, "projectId": 88213, "lines": [ { "partnerLineId": "acme-line-1", "quantity": 500, "lineListTotal": 245.5, "lineTotalBeforeAdjustments": 245.5 } ] } }, { "submissionId": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d", "status": "queued" } ], "nextCursor": null}A status value outside the published set, a limit that is not a positive
integer no greater than 100, or a cursor that could not be decoded.
RFC 9457 application/problem+json body. code is the published, stable,
machine-readable field to branch your integration logic on – detail is a
human-readable string that may be reworded over time and must not be parsed.
This table is the whole published set: every code this API can return appears below,
and nothing below is unreachable. test/docs/openapi-matches-reality.test.ts compares
the enum to the codes the handlers actually construct, so a code added to one side and
not the other fails the build rather than shipping.
Published code values:
code |
HTTP status | Meaning | Retry? |
|---|---|---|---|
invalid_cursor |
400 | The cursor query parameter could not be decoded. |
No – restart pagination with no cursor. Do not resend the same value. |
invalid_site_id |
400 | The siteId filter is not a positive integer, or it names a site outside your grant. detail says which. |
No – fix the parameter against GET /v1/me’s grantedSiteIds. |
invalid_order_number |
400 | The order number in the path is not a positive integer. | No – fix the path. |
invalid_product_id |
400 | The productId path segment on GET /v1/products/{productId} does not match the SLO_/SLS_-prefixed shape. |
No – fix the path. |
invalid_service_type |
400 | GET /v1/products’s serviceType filter is not one of the values this API can order (STOCK or POD). |
No – fix the parameter. |
updated_since_not_supported |
400 | An updatedSince parameter was sent. Rejected rather than ignored, on purpose – see “No updatedSince / no change polling” above. |
No – remove the parameter; there is no change-polling mechanism to switch to. |
invalid_request |
400 | POST /v1/orders’s request body failed validation – malformed JSON, a missing or malformed field, an unknown key, or a body-level rule such as partnerLineId uniqueness or a misplaced shipTo – or GET /v1/orders/submissions’s status/limit filter is malformed. detail names the exact violation. |
No – fix the request. |
invalid_submission_id |
400 | The submissionId path segment on GET /v1/orders/submissions/{submissionId} is not a well-formed UUID. |
No – fix the path. |
invalid_quantity |
400 | The quantity on POST /v1/products/{productId}/quote is missing or not a positive integer. |
No – fix the request body. |
invalid_token |
401 | The credential is missing, expired, or invalid. | No – mint a new token, retry once, then investigate the credential. |
insufficient_scope |
403 | The token lacks the scope required for this operation. | No – mint a token with the required scope. |
order_not_found |
404 | No such order, or one that exists outside your granted sites (see above). | No. |
product_not_found |
404 | No such product, or one that exists but belongs to a site outside your granted sites (same rule as order_not_found). |
No. |
quote_product_not_found |
404 | The product resolved in our own catalog but Collaterate could not price it. Rare. | No. |
submission_not_found |
404 | No submission exists with this id for your credential – whether it never existed or belongs to another partner, identically. | No. |
ordering_not_provisioned |
409 | POST /v1/orders’s siteId has no ordering user configured. This is set up per (partner, site) by staff at onboarding; a partner cannot provision it themselves. |
No – ask Partner Integrations to provision an ordering user for the site, then retry. |
partner_order_id_reused |
409 | POST /v1/orders’s partnerOrderId was already used, with a request body that does not match this one. Resending the identical body under the same partnerOrderId is safe and returns the original submission (see the operation description); reusing it for a materially different order is rejected instead of silently creating a second order. |
No – use a new partnerOrderId, or resend the exact original body to poll the existing submission. |
quote_invalid |
422 | Collaterate rejected the quote on business-validation grounds (e.g. quantity over the product’s configured maximum). detail carries Collaterate’s own validation message. |
No – fix the request body (e.g. reduce quantity). |
rate_limit_exceeded |
429 | Rate limit or daily quota exceeded. | Yes – honor Retry-After. |
internal_error |
500 | Unexpected server-side failure. Detail is always the fixed string below, never the underlying error. | No, or with caution – if persistent, contact Partner Integrations. |
service_unavailable |
503 | Transient failure – typically the database path, but also a Lambda that crashed, timed out, or hit its own concurrency limit before any handler ran. | Yes, with backoff. |
Three statuses are answered by the API gateway before your request reaches application
code: 401 (authorizer denial), 429 (usage-plan throttle), and 503 (the Lambda
integration itself failed). All three are configured to return this same document with
the codes above, so one parser and one branch on code covers every error this API
produces. The 403 on GET /v1/ping is the sole exception anywhere in the API – it
comes from the edge firewall, which is not ours to shape, and carries no problem
document.
object
Always the literal string about:blank today; reserved by RFC 9457 for future use.
Short, human-readable summary of the HTTP status (e.g. “Not Found”).
The HTTP status code, repeated in the body for convenience.
Stable, machine-readable error identifier. Safe to branch on. See the table above.
Human-readable explanation. Do not parse this – it may be reworded without notice.
Echoes the request’s id. Include this when contacting Partner Integrations about a specific failed call – it resolves directly to one log entry.
Examples
{ "type": "about:blank", "title": "Bad Request", "status": 400, "code": "invalid_request", "detail": "\"status\" must be one of queued, processing, completed, failed, got: bogus", "requestId": "8f3c1e2a-..."}{ "type": "about:blank", "title": "Bad Request", "status": 400, "code": "invalid_cursor", "detail": "The \"cursor\" query parameter is malformed.", "requestId": "8f3c1e2a-..."}Missing, expired, or otherwise invalid credential. Not retryable as-is.
Produced by the API gateway’s authorizer, before the request reaches any application
code, so every cause – no Authorization header, a malformed one, a token that is
expired, wrongly signed, from the wrong pool, or belongs to a credential that has been
disabled – yields this identical response. The gateway is configured to answer in the
same application/problem+json shape as everything else, so you do not need a second
parser for this status; what it cannot do is tell you which of those causes applied.
RFC 9457 application/problem+json body. code is the published, stable,
machine-readable field to branch your integration logic on – detail is a
human-readable string that may be reworded over time and must not be parsed.
This table is the whole published set: every code this API can return appears below,
and nothing below is unreachable. test/docs/openapi-matches-reality.test.ts compares
the enum to the codes the handlers actually construct, so a code added to one side and
not the other fails the build rather than shipping.
Published code values:
code |
HTTP status | Meaning | Retry? |
|---|---|---|---|
invalid_cursor |
400 | The cursor query parameter could not be decoded. |
No – restart pagination with no cursor. Do not resend the same value. |
invalid_site_id |
400 | The siteId filter is not a positive integer, or it names a site outside your grant. detail says which. |
No – fix the parameter against GET /v1/me’s grantedSiteIds. |
invalid_order_number |
400 | The order number in the path is not a positive integer. | No – fix the path. |
invalid_product_id |
400 | The productId path segment on GET /v1/products/{productId} does not match the SLO_/SLS_-prefixed shape. |
No – fix the path. |
invalid_service_type |
400 | GET /v1/products’s serviceType filter is not one of the values this API can order (STOCK or POD). |
No – fix the parameter. |
updated_since_not_supported |
400 | An updatedSince parameter was sent. Rejected rather than ignored, on purpose – see “No updatedSince / no change polling” above. |
No – remove the parameter; there is no change-polling mechanism to switch to. |
invalid_request |
400 | POST /v1/orders’s request body failed validation – malformed JSON, a missing or malformed field, an unknown key, or a body-level rule such as partnerLineId uniqueness or a misplaced shipTo – or GET /v1/orders/submissions’s status/limit filter is malformed. detail names the exact violation. |
No – fix the request. |
invalid_submission_id |
400 | The submissionId path segment on GET /v1/orders/submissions/{submissionId} is not a well-formed UUID. |
No – fix the path. |
invalid_quantity |
400 | The quantity on POST /v1/products/{productId}/quote is missing or not a positive integer. |
No – fix the request body. |
invalid_token |
401 | The credential is missing, expired, or invalid. | No – mint a new token, retry once, then investigate the credential. |
insufficient_scope |
403 | The token lacks the scope required for this operation. | No – mint a token with the required scope. |
order_not_found |
404 | No such order, or one that exists outside your granted sites (see above). | No. |
product_not_found |
404 | No such product, or one that exists but belongs to a site outside your granted sites (same rule as order_not_found). |
No. |
quote_product_not_found |
404 | The product resolved in our own catalog but Collaterate could not price it. Rare. | No. |
submission_not_found |
404 | No submission exists with this id for your credential – whether it never existed or belongs to another partner, identically. | No. |
ordering_not_provisioned |
409 | POST /v1/orders’s siteId has no ordering user configured. This is set up per (partner, site) by staff at onboarding; a partner cannot provision it themselves. |
No – ask Partner Integrations to provision an ordering user for the site, then retry. |
partner_order_id_reused |
409 | POST /v1/orders’s partnerOrderId was already used, with a request body that does not match this one. Resending the identical body under the same partnerOrderId is safe and returns the original submission (see the operation description); reusing it for a materially different order is rejected instead of silently creating a second order. |
No – use a new partnerOrderId, or resend the exact original body to poll the existing submission. |
quote_invalid |
422 | Collaterate rejected the quote on business-validation grounds (e.g. quantity over the product’s configured maximum). detail carries Collaterate’s own validation message. |
No – fix the request body (e.g. reduce quantity). |
rate_limit_exceeded |
429 | Rate limit or daily quota exceeded. | Yes – honor Retry-After. |
internal_error |
500 | Unexpected server-side failure. Detail is always the fixed string below, never the underlying error. | No, or with caution – if persistent, contact Partner Integrations. |
service_unavailable |
503 | Transient failure – typically the database path, but also a Lambda that crashed, timed out, or hit its own concurrency limit before any handler ran. | Yes, with backoff. |
Three statuses are answered by the API gateway before your request reaches application
code: 401 (authorizer denial), 429 (usage-plan throttle), and 503 (the Lambda
integration itself failed). All three are configured to return this same document with
the codes above, so one parser and one branch on code covers every error this API
produces. The 403 on GET /v1/ping is the sole exception anywhere in the API – it
comes from the edge firewall, which is not ours to shape, and carries no problem
document.
object
Always the literal string about:blank today; reserved by RFC 9457 for future use.
Short, human-readable summary of the HTTP status (e.g. “Not Found”).
The HTTP status code, repeated in the body for convenience.
Stable, machine-readable error identifier. Safe to branch on. See the table above.
Human-readable explanation. Do not parse this – it may be reworded without notice.
Echoes the request’s id. Include this when contacting Partner Integrations about a specific failed call – it resolves directly to one log entry.
Example
{ "type": "about:blank", "title": "Unauthorized", "status": 401, "code": "invalid_token", "detail": "The credential presented with this request is missing, expired, or invalid.", "requestId": "8f3c1e2a-..."}The credential is valid but lacks the scope required for this operation (for
example, a token minted without partner-api/orders:read). Not retryable as-is –
request a token with the required scope. Not to be confused with an out-of-scope
order, which is a 404 (see above), or with the edge firewall’s 403 on /ping,
which carries no problem document at all.
RFC 9457 application/problem+json body. code is the published, stable,
machine-readable field to branch your integration logic on – detail is a
human-readable string that may be reworded over time and must not be parsed.
This table is the whole published set: every code this API can return appears below,
and nothing below is unreachable. test/docs/openapi-matches-reality.test.ts compares
the enum to the codes the handlers actually construct, so a code added to one side and
not the other fails the build rather than shipping.
Published code values:
code |
HTTP status | Meaning | Retry? |
|---|---|---|---|
invalid_cursor |
400 | The cursor query parameter could not be decoded. |
No – restart pagination with no cursor. Do not resend the same value. |
invalid_site_id |
400 | The siteId filter is not a positive integer, or it names a site outside your grant. detail says which. |
No – fix the parameter against GET /v1/me’s grantedSiteIds. |
invalid_order_number |
400 | The order number in the path is not a positive integer. | No – fix the path. |
invalid_product_id |
400 | The productId path segment on GET /v1/products/{productId} does not match the SLO_/SLS_-prefixed shape. |
No – fix the path. |
invalid_service_type |
400 | GET /v1/products’s serviceType filter is not one of the values this API can order (STOCK or POD). |
No – fix the parameter. |
updated_since_not_supported |
400 | An updatedSince parameter was sent. Rejected rather than ignored, on purpose – see “No updatedSince / no change polling” above. |
No – remove the parameter; there is no change-polling mechanism to switch to. |
invalid_request |
400 | POST /v1/orders’s request body failed validation – malformed JSON, a missing or malformed field, an unknown key, or a body-level rule such as partnerLineId uniqueness or a misplaced shipTo – or GET /v1/orders/submissions’s status/limit filter is malformed. detail names the exact violation. |
No – fix the request. |
invalid_submission_id |
400 | The submissionId path segment on GET /v1/orders/submissions/{submissionId} is not a well-formed UUID. |
No – fix the path. |
invalid_quantity |
400 | The quantity on POST /v1/products/{productId}/quote is missing or not a positive integer. |
No – fix the request body. |
invalid_token |
401 | The credential is missing, expired, or invalid. | No – mint a new token, retry once, then investigate the credential. |
insufficient_scope |
403 | The token lacks the scope required for this operation. | No – mint a token with the required scope. |
order_not_found |
404 | No such order, or one that exists outside your granted sites (see above). | No. |
product_not_found |
404 | No such product, or one that exists but belongs to a site outside your granted sites (same rule as order_not_found). |
No. |
quote_product_not_found |
404 | The product resolved in our own catalog but Collaterate could not price it. Rare. | No. |
submission_not_found |
404 | No submission exists with this id for your credential – whether it never existed or belongs to another partner, identically. | No. |
ordering_not_provisioned |
409 | POST /v1/orders’s siteId has no ordering user configured. This is set up per (partner, site) by staff at onboarding; a partner cannot provision it themselves. |
No – ask Partner Integrations to provision an ordering user for the site, then retry. |
partner_order_id_reused |
409 | POST /v1/orders’s partnerOrderId was already used, with a request body that does not match this one. Resending the identical body under the same partnerOrderId is safe and returns the original submission (see the operation description); reusing it for a materially different order is rejected instead of silently creating a second order. |
No – use a new partnerOrderId, or resend the exact original body to poll the existing submission. |
quote_invalid |
422 | Collaterate rejected the quote on business-validation grounds (e.g. quantity over the product’s configured maximum). detail carries Collaterate’s own validation message. |
No – fix the request body (e.g. reduce quantity). |
rate_limit_exceeded |
429 | Rate limit or daily quota exceeded. | Yes – honor Retry-After. |
internal_error |
500 | Unexpected server-side failure. Detail is always the fixed string below, never the underlying error. | No, or with caution – if persistent, contact Partner Integrations. |
service_unavailable |
503 | Transient failure – typically the database path, but also a Lambda that crashed, timed out, or hit its own concurrency limit before any handler ran. | Yes, with backoff. |
Three statuses are answered by the API gateway before your request reaches application
code: 401 (authorizer denial), 429 (usage-plan throttle), and 503 (the Lambda
integration itself failed). All three are configured to return this same document with
the codes above, so one parser and one branch on code covers every error this API
produces. The 403 on GET /v1/ping is the sole exception anywhere in the API – it
comes from the edge firewall, which is not ours to shape, and carries no problem
document.
object
Always the literal string about:blank today; reserved by RFC 9457 for future use.
Short, human-readable summary of the HTTP status (e.g. “Not Found”).
The HTTP status code, repeated in the body for convenience.
Stable, machine-readable error identifier. Safe to branch on. See the table above.
Human-readable explanation. Do not parse this – it may be reworded without notice.
Echoes the request’s id. Include this when contacting Partner Integrations about a specific failed call – it resolves directly to one log entry.
Example
{ "type": "about:blank", "title": "Forbidden", "status": 403, "code": "insufficient_scope", "detail": "This request requires the \"partner-api/orders:read\" scope.", "requestId": "8f3c1e2a-..."}Your rate limit or daily quota was exceeded. Retryable – honor the Retry-After
header (seconds) before your next attempt.
Like the 401, this comes from the gateway’s usage plan rather than from application code, and is configured to carry the same problem document as every other error so a single parser covers the whole API.
RFC 9457 application/problem+json body. code is the published, stable,
machine-readable field to branch your integration logic on – detail is a
human-readable string that may be reworded over time and must not be parsed.
This table is the whole published set: every code this API can return appears below,
and nothing below is unreachable. test/docs/openapi-matches-reality.test.ts compares
the enum to the codes the handlers actually construct, so a code added to one side and
not the other fails the build rather than shipping.
Published code values:
code |
HTTP status | Meaning | Retry? |
|---|---|---|---|
invalid_cursor |
400 | The cursor query parameter could not be decoded. |
No – restart pagination with no cursor. Do not resend the same value. |
invalid_site_id |
400 | The siteId filter is not a positive integer, or it names a site outside your grant. detail says which. |
No – fix the parameter against GET /v1/me’s grantedSiteIds. |
invalid_order_number |
400 | The order number in the path is not a positive integer. | No – fix the path. |
invalid_product_id |
400 | The productId path segment on GET /v1/products/{productId} does not match the SLO_/SLS_-prefixed shape. |
No – fix the path. |
invalid_service_type |
400 | GET /v1/products’s serviceType filter is not one of the values this API can order (STOCK or POD). |
No – fix the parameter. |
updated_since_not_supported |
400 | An updatedSince parameter was sent. Rejected rather than ignored, on purpose – see “No updatedSince / no change polling” above. |
No – remove the parameter; there is no change-polling mechanism to switch to. |
invalid_request |
400 | POST /v1/orders’s request body failed validation – malformed JSON, a missing or malformed field, an unknown key, or a body-level rule such as partnerLineId uniqueness or a misplaced shipTo – or GET /v1/orders/submissions’s status/limit filter is malformed. detail names the exact violation. |
No – fix the request. |
invalid_submission_id |
400 | The submissionId path segment on GET /v1/orders/submissions/{submissionId} is not a well-formed UUID. |
No – fix the path. |
invalid_quantity |
400 | The quantity on POST /v1/products/{productId}/quote is missing or not a positive integer. |
No – fix the request body. |
invalid_token |
401 | The credential is missing, expired, or invalid. | No – mint a new token, retry once, then investigate the credential. |
insufficient_scope |
403 | The token lacks the scope required for this operation. | No – mint a token with the required scope. |
order_not_found |
404 | No such order, or one that exists outside your granted sites (see above). | No. |
product_not_found |
404 | No such product, or one that exists but belongs to a site outside your granted sites (same rule as order_not_found). |
No. |
quote_product_not_found |
404 | The product resolved in our own catalog but Collaterate could not price it. Rare. | No. |
submission_not_found |
404 | No submission exists with this id for your credential – whether it never existed or belongs to another partner, identically. | No. |
ordering_not_provisioned |
409 | POST /v1/orders’s siteId has no ordering user configured. This is set up per (partner, site) by staff at onboarding; a partner cannot provision it themselves. |
No – ask Partner Integrations to provision an ordering user for the site, then retry. |
partner_order_id_reused |
409 | POST /v1/orders’s partnerOrderId was already used, with a request body that does not match this one. Resending the identical body under the same partnerOrderId is safe and returns the original submission (see the operation description); reusing it for a materially different order is rejected instead of silently creating a second order. |
No – use a new partnerOrderId, or resend the exact original body to poll the existing submission. |
quote_invalid |
422 | Collaterate rejected the quote on business-validation grounds (e.g. quantity over the product’s configured maximum). detail carries Collaterate’s own validation message. |
No – fix the request body (e.g. reduce quantity). |
rate_limit_exceeded |
429 | Rate limit or daily quota exceeded. | Yes – honor Retry-After. |
internal_error |
500 | Unexpected server-side failure. Detail is always the fixed string below, never the underlying error. | No, or with caution – if persistent, contact Partner Integrations. |
service_unavailable |
503 | Transient failure – typically the database path, but also a Lambda that crashed, timed out, or hit its own concurrency limit before any handler ran. | Yes, with backoff. |
Three statuses are answered by the API gateway before your request reaches application
code: 401 (authorizer denial), 429 (usage-plan throttle), and 503 (the Lambda
integration itself failed). All three are configured to return this same document with
the codes above, so one parser and one branch on code covers every error this API
produces. The 403 on GET /v1/ping is the sole exception anywhere in the API – it
comes from the edge firewall, which is not ours to shape, and carries no problem
document.
object
Always the literal string about:blank today; reserved by RFC 9457 for future use.
Short, human-readable summary of the HTTP status (e.g. “Not Found”).
The HTTP status code, repeated in the body for convenience.
Stable, machine-readable error identifier. Safe to branch on. See the table above.
Human-readable explanation. Do not parse this – it may be reworded without notice.
Echoes the request’s id. Include this when contacting Partner Integrations about a specific failed call – it resolves directly to one log entry.
Example
{ "type": "about:blank", "title": "Too Many Requests", "status": 429, "code": "rate_limit_exceeded", "detail": "The request rate limit has been exceeded. Retry after the indicated delay.", "requestId": "8f3c1e2a-..."}Headers
Section titled “Headers”Seconds to wait before retrying.
An unexpected server-side failure. detail is always the fixed string below and never
the underlying error – a database message quoted back to a partner is a disclosure,
so nothing is interpolated into it. The requestId resolves to the log entry that does
carry the cause; send it to Partner Integrations rather than guessing.
RFC 9457 application/problem+json body. code is the published, stable,
machine-readable field to branch your integration logic on – detail is a
human-readable string that may be reworded over time and must not be parsed.
This table is the whole published set: every code this API can return appears below,
and nothing below is unreachable. test/docs/openapi-matches-reality.test.ts compares
the enum to the codes the handlers actually construct, so a code added to one side and
not the other fails the build rather than shipping.
Published code values:
code |
HTTP status | Meaning | Retry? |
|---|---|---|---|
invalid_cursor |
400 | The cursor query parameter could not be decoded. |
No – restart pagination with no cursor. Do not resend the same value. |
invalid_site_id |
400 | The siteId filter is not a positive integer, or it names a site outside your grant. detail says which. |
No – fix the parameter against GET /v1/me’s grantedSiteIds. |
invalid_order_number |
400 | The order number in the path is not a positive integer. | No – fix the path. |
invalid_product_id |
400 | The productId path segment on GET /v1/products/{productId} does not match the SLO_/SLS_-prefixed shape. |
No – fix the path. |
invalid_service_type |
400 | GET /v1/products’s serviceType filter is not one of the values this API can order (STOCK or POD). |
No – fix the parameter. |
updated_since_not_supported |
400 | An updatedSince parameter was sent. Rejected rather than ignored, on purpose – see “No updatedSince / no change polling” above. |
No – remove the parameter; there is no change-polling mechanism to switch to. |
invalid_request |
400 | POST /v1/orders’s request body failed validation – malformed JSON, a missing or malformed field, an unknown key, or a body-level rule such as partnerLineId uniqueness or a misplaced shipTo – or GET /v1/orders/submissions’s status/limit filter is malformed. detail names the exact violation. |
No – fix the request. |
invalid_submission_id |
400 | The submissionId path segment on GET /v1/orders/submissions/{submissionId} is not a well-formed UUID. |
No – fix the path. |
invalid_quantity |
400 | The quantity on POST /v1/products/{productId}/quote is missing or not a positive integer. |
No – fix the request body. |
invalid_token |
401 | The credential is missing, expired, or invalid. | No – mint a new token, retry once, then investigate the credential. |
insufficient_scope |
403 | The token lacks the scope required for this operation. | No – mint a token with the required scope. |
order_not_found |
404 | No such order, or one that exists outside your granted sites (see above). | No. |
product_not_found |
404 | No such product, or one that exists but belongs to a site outside your granted sites (same rule as order_not_found). |
No. |
quote_product_not_found |
404 | The product resolved in our own catalog but Collaterate could not price it. Rare. | No. |
submission_not_found |
404 | No submission exists with this id for your credential – whether it never existed or belongs to another partner, identically. | No. |
ordering_not_provisioned |
409 | POST /v1/orders’s siteId has no ordering user configured. This is set up per (partner, site) by staff at onboarding; a partner cannot provision it themselves. |
No – ask Partner Integrations to provision an ordering user for the site, then retry. |
partner_order_id_reused |
409 | POST /v1/orders’s partnerOrderId was already used, with a request body that does not match this one. Resending the identical body under the same partnerOrderId is safe and returns the original submission (see the operation description); reusing it for a materially different order is rejected instead of silently creating a second order. |
No – use a new partnerOrderId, or resend the exact original body to poll the existing submission. |
quote_invalid |
422 | Collaterate rejected the quote on business-validation grounds (e.g. quantity over the product’s configured maximum). detail carries Collaterate’s own validation message. |
No – fix the request body (e.g. reduce quantity). |
rate_limit_exceeded |
429 | Rate limit or daily quota exceeded. | Yes – honor Retry-After. |
internal_error |
500 | Unexpected server-side failure. Detail is always the fixed string below, never the underlying error. | No, or with caution – if persistent, contact Partner Integrations. |
service_unavailable |
503 | Transient failure – typically the database path, but also a Lambda that crashed, timed out, or hit its own concurrency limit before any handler ran. | Yes, with backoff. |
Three statuses are answered by the API gateway before your request reaches application
code: 401 (authorizer denial), 429 (usage-plan throttle), and 503 (the Lambda
integration itself failed). All three are configured to return this same document with
the codes above, so one parser and one branch on code covers every error this API
produces. The 403 on GET /v1/ping is the sole exception anywhere in the API – it
comes from the edge firewall, which is not ours to shape, and carries no problem
document.
object
Always the literal string about:blank today; reserved by RFC 9457 for future use.
Short, human-readable summary of the HTTP status (e.g. “Not Found”).
The HTTP status code, repeated in the body for convenience.
Stable, machine-readable error identifier. Safe to branch on. See the table above.
Human-readable explanation. Do not parse this – it may be reworded without notice.
Echoes the request’s id. Include this when contacting Partner Integrations about a specific failed call – it resolves directly to one log entry.
Example
{ "type": "about:blank", "title": "Internal Server Error", "status": 500, "code": "internal_error", "detail": "An unexpected error occurred.", "requestId": "8f3c1e2a-..."}Transient failure in the service or the database it reads from (for example, the Aurora reader could not be reached in time), or the request never reached application code at all because the Lambda behind it crashed, timed out, or hit its own concurrency limit. Retryable, with backoff.
RFC 9457 application/problem+json body. code is the published, stable,
machine-readable field to branch your integration logic on – detail is a
human-readable string that may be reworded over time and must not be parsed.
This table is the whole published set: every code this API can return appears below,
and nothing below is unreachable. test/docs/openapi-matches-reality.test.ts compares
the enum to the codes the handlers actually construct, so a code added to one side and
not the other fails the build rather than shipping.
Published code values:
code |
HTTP status | Meaning | Retry? |
|---|---|---|---|
invalid_cursor |
400 | The cursor query parameter could not be decoded. |
No – restart pagination with no cursor. Do not resend the same value. |
invalid_site_id |
400 | The siteId filter is not a positive integer, or it names a site outside your grant. detail says which. |
No – fix the parameter against GET /v1/me’s grantedSiteIds. |
invalid_order_number |
400 | The order number in the path is not a positive integer. | No – fix the path. |
invalid_product_id |
400 | The productId path segment on GET /v1/products/{productId} does not match the SLO_/SLS_-prefixed shape. |
No – fix the path. |
invalid_service_type |
400 | GET /v1/products’s serviceType filter is not one of the values this API can order (STOCK or POD). |
No – fix the parameter. |
updated_since_not_supported |
400 | An updatedSince parameter was sent. Rejected rather than ignored, on purpose – see “No updatedSince / no change polling” above. |
No – remove the parameter; there is no change-polling mechanism to switch to. |
invalid_request |
400 | POST /v1/orders’s request body failed validation – malformed JSON, a missing or malformed field, an unknown key, or a body-level rule such as partnerLineId uniqueness or a misplaced shipTo – or GET /v1/orders/submissions’s status/limit filter is malformed. detail names the exact violation. |
No – fix the request. |
invalid_submission_id |
400 | The submissionId path segment on GET /v1/orders/submissions/{submissionId} is not a well-formed UUID. |
No – fix the path. |
invalid_quantity |
400 | The quantity on POST /v1/products/{productId}/quote is missing or not a positive integer. |
No – fix the request body. |
invalid_token |
401 | The credential is missing, expired, or invalid. | No – mint a new token, retry once, then investigate the credential. |
insufficient_scope |
403 | The token lacks the scope required for this operation. | No – mint a token with the required scope. |
order_not_found |
404 | No such order, or one that exists outside your granted sites (see above). | No. |
product_not_found |
404 | No such product, or one that exists but belongs to a site outside your granted sites (same rule as order_not_found). |
No. |
quote_product_not_found |
404 | The product resolved in our own catalog but Collaterate could not price it. Rare. | No. |
submission_not_found |
404 | No submission exists with this id for your credential – whether it never existed or belongs to another partner, identically. | No. |
ordering_not_provisioned |
409 | POST /v1/orders’s siteId has no ordering user configured. This is set up per (partner, site) by staff at onboarding; a partner cannot provision it themselves. |
No – ask Partner Integrations to provision an ordering user for the site, then retry. |
partner_order_id_reused |
409 | POST /v1/orders’s partnerOrderId was already used, with a request body that does not match this one. Resending the identical body under the same partnerOrderId is safe and returns the original submission (see the operation description); reusing it for a materially different order is rejected instead of silently creating a second order. |
No – use a new partnerOrderId, or resend the exact original body to poll the existing submission. |
quote_invalid |
422 | Collaterate rejected the quote on business-validation grounds (e.g. quantity over the product’s configured maximum). detail carries Collaterate’s own validation message. |
No – fix the request body (e.g. reduce quantity). |
rate_limit_exceeded |
429 | Rate limit or daily quota exceeded. | Yes – honor Retry-After. |
internal_error |
500 | Unexpected server-side failure. Detail is always the fixed string below, never the underlying error. | No, or with caution – if persistent, contact Partner Integrations. |
service_unavailable |
503 | Transient failure – typically the database path, but also a Lambda that crashed, timed out, or hit its own concurrency limit before any handler ran. | Yes, with backoff. |
Three statuses are answered by the API gateway before your request reaches application
code: 401 (authorizer denial), 429 (usage-plan throttle), and 503 (the Lambda
integration itself failed). All three are configured to return this same document with
the codes above, so one parser and one branch on code covers every error this API
produces. The 403 on GET /v1/ping is the sole exception anywhere in the API – it
comes from the edge firewall, which is not ours to shape, and carries no problem
document.
object
Always the literal string about:blank today; reserved by RFC 9457 for future use.
Short, human-readable summary of the HTTP status (e.g. “Not Found”).
The HTTP status code, repeated in the body for convenience.
Stable, machine-readable error identifier. Safe to branch on. See the table above.
Human-readable explanation. Do not parse this – it may be reworded without notice.
Echoes the request’s id. Include this when contacting Partner Integrations about a specific failed call – it resolves directly to one log entry.
Example
{ "type": "about:blank", "title": "Service Unavailable", "status": 503, "code": "service_unavailable", "detail": "The service is temporarily unavailable. Please retry.", "requestId": "8f3c1e2a-..."}