# Resubmit an order that is on hold

`POST /orders/{orderId}/resubmit`

OMS API, Orders.

Asks the fulfillment provider to fulfill an order again, with the shipping address and customer details the order carries now. You can resubmit an order that is on hold (`holdStatus` `held`), and an order sent with customer details that break the provider's rules (`recipientFaults`) without waiting for the provider to hold it. Correct the customer first — both kinds of order pick up customer updates — then resubmit. An order on hold is resubmitted for you when you correct its customer's name, phone number or shipping address, unless its `holdReasonCode` is one such a correction does not fix; calling this after that, before the provider answers, is refused as already resubmitted, and you can treat that refusal as done. The provider takes the change only while it is holding the order, so it may refuse an order it has not held yet; resubmit that one once it does. The provider answers asynchronously: `holdStatus` becomes `resubmitted` immediately, then clears once the provider accepts the order, or becomes `held` with a new `holdReason` if it holds it. An order held because the provider found no shipping option for it is also re-quoted automatically for a while; resubmitting it ends that and asks at once. An order held because the provider could not charge your prepaid balance for it (`holdReasonCode` `insufficient_funds`) is sent again automatically once the balance covers it; resubmit it to send it sooner, for example right after you top up, while the provider has it (`externalOrderId` is set). When the provider refused it before creating it, `externalOrderId` is empty and there is nothing to resubmit: use `POST /orders/{orderId}/retry-submission` instead. Only orders sent to NextSmartShip are resubmitted. ShipBob takes no resubmission, and an order it holds is never sent to it a second time. When ShipBob holds the order because it could not validate the shipping address (`holdReasonCode` `address_invalid`), resubmitting sends ShipBob the shipping address the order carries now instead, for the shipments it holds, and ShipBob checks it again. The order stays `held` until ShipBob releases it. The order's history records ShipBob's answer as a `tpl_address_update_requested` entry. If ShipBob did not save the address for every shipment it holds, the request is refused with the reason: correct the address in ShipBob. It is also refused if you cancelled some of the order's items or recorded a shipment of it yourself, because ShipBob would still ship those items. Every other order ShipBob holds is refused: resolve the hold in ShipBob, which ships the order itself once it releases the hold.

**Authentication:** Send `Authorization: Bearer <token>`. Either an identity token issued by the auth service (dashboard flow; requires the selected merchant account id in the `X-Odus-Merchant` header), or a merchant secret key (`sk_...`) for server-to-server calls. Both are sent as `Authorization: Bearer <token>`.

## Parameters

### Path parameters

- `orderId` (string, required)

## Responses

### `200`

Type: object (OrderDTO).

- `createdAt` (string (date-time), required): The date and time when the entity was created. Example: `2024-02-18T12:00:00Z`.
- `updatedAt` (string (date-time), required, nullable): The date and time when the entity was last updated. Example: `2024-02-21T12:15:00Z`.
- `metadata` (map of string to string, required, nullable): Metadata used by merchants to store additional information about the entity.
- `id` (string, required)
- `status` (string, required): One of `unfulfilled`, `partially_fulfilled`, `fulfilled`, `not_fulfillable`, `cancelled`.
- `paymentId` (string, required)
- `amount` (number, required)
- `currency` (string, required): One of `usd`, `eur`, `gbp`, `cad`, `aud`, `pln`, `czk`, `sek`, `dkk`.
- `processor` (string, required, nullable): One of `stripe`, `adyen`, `checkout`, `paypal`.
- `gatewayProfileId` (string, required, nullable)
- `customerId` (string, required)
- `customerEmail` (string, required)
- `customerName` (string, required, nullable)
- `customerPhone` (string, required, nullable)
- `paymentAuthorizedAt` (string (date-time), required)
- `shippingAddress` (object, required)
  - `firstName` (string, required, nullable)
  - `lastName` (string, required, nullable)
  - `companyName` (string, required, nullable)
  - `line1` (string, required, nullable)
  - `line2` (string, required, nullable)
  - `city` (string, required, nullable)
  - `state` (string, required, nullable)
  - `postalCode` (string, required, nullable)
  - `country` (string, required, nullable)
- `shippingAddressHash` (string, required)
- `orderItems` (array of object, required)
  - `createdAt` (string (date-time), required): The date and time when the entity was created. Example: `2024-02-18T12:00:00Z`.
  - `updatedAt` (string (date-time), required, nullable): The date and time when the entity was last updated. Example: `2024-02-21T12:15:00Z`.
  - `metadata` (map of string to string, required, nullable): Metadata used by merchants to store additional information about the entity.
  - `id` (string, required)
  - `shippable` (boolean, required): Whether this item physically ships. Digital add-ons (e.g. a warranty) are recorded on the order but never fulfilled.
  - `sku` (string, required, nullable): Stock Keeping Unit the warehouse ships this item under. Null for non-shippable items.
  - `quantity` (number, required, nullable): Units to ship, taken from the payment line item, whose quantity already covers the units a bundle price represents. Null for non-shippable items.
  - `fulfilledQuantity` (number, required)
  - `cancelledQuantity` (number, required)
  - `paymentId` (string, required)
  - `lineItemId` (string, required)
  - `priceId` (string, required)
  - `name` (string, required)
  - `productId` (string, required)
  - `productName` (string, required)
  - `order` (string, required)
- `fulfillments` (array of string, required)
- `externalOrderId` (string, required, nullable)
- `fulfillmentIntegrationId` (string, required, nullable)
- `fulfillmentIntegrationType` (string, required, nullable): Provider the order was submitted to — the type of the fulfillment integration behind `fulfillmentIntegrationId`, resolved at read time. `null` when the order was never submitted or the integration no longer exists. One of `shipbob`, `nextsmartship`. Example: `shipbob`.
- `fulfillmentIntegrationName` (string, required, nullable): Current user-given name of the fulfillment integration the order was submitted to. Resolved at read time from `fulfillmentIntegrationId`; `null` when the order was never submitted or the integration no longer exists. Example: `ShipBob US Warehouse`.
- `fulfillmentIntegrationEnvironment` (string, required, nullable): Environment of the fulfillment provider account the order was sent to. Use it to look `externalOrderId` up in the matching sandbox or production account; `null` when no environment is known for the order. One of `sandbox`, `production`. Example: `production`.
- `submittedAt` (string (date-time), required, nullable)
- `lastSubmissionAttemptedAt` (string (date-time), required, nullable)
- `lastSubmissionError` (string, required, nullable)
- `submissionAttempts` (number, required)
- `submitToTplAt` (string (date-time), required, nullable)
- `tplSubmissionStatus` (string, required, nullable): Where the order stands in its automatic submission to your fulfillment provider. `pending`: waiting to be sent. `submitted`: the provider accepted the order. `failed`: an attempt failed, and another is scheduled — or, while the order is on hold with `holdReasonCode` `insufficient_funds` and no `externalOrderId`, none is until your prepaid balance with the provider covers the order. `dead_letter`: submission stopped, and the order needs you. A value starting with `skipped_`: no provider receives the order, for example because no fulfillment route matches it. `null` when the order was never scheduled for submission. `GET /orders/{orderId}` returns when the next attempt is due, in `submitToTplAt`, and why the last one failed, in `lastSubmissionError`. The value is not cleared when you fulfill or cancel the order yourself, so read it together with `status`. Values may be added, so treat one you do not recognise as not sent yet. One of `pending`, `submitted`, `failed`, `dead_letter`, `skipped_no_route`, `skipped_no_country`, `skipped_no_shippable_items`, `skipped_route_conflict`, `skipped_integration_inactive`, `skipped_order_cancelled`. Example: `submitted`.
- `agedOutAt` (string (date-time), required, nullable)
- `cancelledUnitsShippedAt` (string (date-time), required, nullable): When your fulfillment provider first reported shipping units of this order that you had cancelled, for example by refunding the payment. The cancelled units stay cancelled and do not count as fulfilled. Each such shipment is in the order history as a `cancelled_units_shipped` entry with its tracking number and the units it carried, so you can recover the goods or charge for them. `null` when no cancelled units have shipped. Once set, it stays set.
- `holdStatus` (string, required, nullable): Set while the order is on hold: the fulfillment provider has it and is not shipping it, or it refused the order before creating it. Usually the provider put it on hold itself — it could not get a carrier to take the shipment — and waits for you to act. When the provider found no shipping option for the order, the hold is recorded here from the first attempt and the order is re-quoted automatically for a while; it is released once the provider accepts a fulfillment request, and you can resubmit it at any time meanwhile. When the provider refused the order because your prepaid balance with it could not cover it, the hold is recorded here too (`holdReasonCode` `insufficient_funds`), and the order is sent again automatically once the balance covers it. Usually the provider has such an order (`externalOrderId` is set, `tplSubmissionStatus` is `submitted`) and the hold is released once it accepts the order; when the provider refused it before creating it, `externalOrderId` is empty, `tplSubmissionStatus` is `failed` with nothing scheduled, and the hold is released when the order is sent again. When ShipBob holds the order — for an address it cannot validate, missing customs details, a payment method it could not charge, a hold placed by hand or any other reason it gives — the hold is recorded here too, with ShipBob’s reason, while the order still owes fulfillment here or is already on hold: a hold ShipBob raises after you have fulfilled or cancelled the order here is not recorded, and one recorded before that stays until ShipBob releases it. Resolve it in ShipBob, which ships the order itself once it releases the hold, and the hold is released here then. ShipBob is never sent such an order a second time. `held`: fix what `holdReason` names, then resubmit the order — or correct the customer, which resubmits it for you for most reasons (see `holdReasonCode`); for an order ShipBob holds, fix it in ShipBob instead, or correct the customer when `holdReasonCode` is `address_invalid`. Resubmitting that one sends ShipBob the address the order carries and leaves it `held`. `resubmitted`: the order was resubmitted and the provider has not answered yet; it clears when the provider accepts the order, or returns to `held` with a new reason. A correction to the customer made while the order is `resubmitted` is sent for you if the provider holds the order again for a reason that correction fixes. `null` when the order is not on hold. Independent of `status`, which the hold does not change. `held` applies to orders fulfilled through NextSmartShip or ShipBob, and `resubmitted` to orders fulfilled through NextSmartShip. Values may be added, so treat one you do not recognise as on hold. One of `held`, `resubmitted`. Example: `held`.
- `holdReason` (string, required, nullable): Why the order is on hold. Usually the reason the fulfillment provider gave, in its own words — typically what the carrier refused about the address. For an order ShipBob holds, it is how ShipBob describes the hold, such as `Invalid Address`. When the provider gave no reason — it found no shipping option for the order, was never asked to ship it, could not charge your prepaid balance for it, or could not charge your payment method for it — the reason describes that instead. Kept while the order is `resubmitted`; `null` when the order is not on hold. Example: `City does not match the postal code`.
- `holdReasonCode` (string, required, nullable): Why the fulfillment provider holds the order, as a code your integration can act on instead of reading `holdReason`. `null` when the order is not on hold. The same `holdReason` always has the same code. Codes may be added, so treat one you do not recognise as `other`. Correct what the code names, then resubmit the order. When the correction is to the customer — their name, phone number or shipping address — the order is resubmitted for you, except for `tax_id_missing`, `customs_details_invalid`, `shipping_restricted`, `carrier_unavailable`, `insufficient_funds`, `unspecified` and `other`. An order ShipBob holds is the exception to both: correct what the code names in ShipBob, which ships the order itself once it releases the hold. ShipBob is never sent such an order a second time, so resubmitting one is refused, except for `address_invalid`. For `address_invalid` you can correct the customer instead, unless you cancelled some of the order’s items or recorded a shipment of it yourself: their corrected name, phone number and shipping address are sent to ShipBob, which validates the address again, and the order’s history records ShipBob’s answer. Resubmitting such an order sends ShipBob the address the order already carries, in the same way. A correction for any other code is not sent to ShipBob. The codes: - `postal_code_invalid`: the postal code is not valid for the country. Correct it. - `postal_code_city_mismatch`: the city and the postal code do not match. Correct whichever is wrong. - `postal_code_not_served`: the carrier does not deliver to the postal code. Confirm it with the customer, and ask your provider for a carrier that delivers there. - `state_invalid`: the state, province or region does not match the postal code or the country. Correct it. - `street_not_found`: the carrier cannot find the street. Check its spelling, and put the street and house number on the first address line. - `house_number_missing`: the street address has no house or building number. Add it. - `address_incomplete`: the address is missing details, such as the house number or the apartment. Complete it. - `address_invalid_characters`: the address contains characters the carrier does not accept. Rewrite it in Latin letters and digits. - `name_or_address_too_long`: the recipient’s name, company or an address line is longer than the carrier accepts. Shorten it, moving the rest of a long street to the second line. - `po_box_not_accepted`: the carrier does not deliver to PO boxes. Replace the PO box with a street address. - `address_invalid`: the provider could not validate the shipping address and did not say which part of it is wrong. Check the whole address and correct it. - `recipient_name_invalid`: the recipient’s name is too short or is not a name. Enter their full first and last name. - `phone_invalid`: the phone number is not valid. Correct it, including the country code. - `tax_id_missing`: the destination country requires the recipient’s tax ID. Add it to the order in your provider’s dashboard. - `customs_details_invalid`: the provider or its carrier needs customs details the order does not have, such as a product’s material, use or HS code. Complete them in your provider’s dashboard. - `shipping_restricted`: the provider’s or the carrier’s rules do not allow this shipment, for example hazardous items shipped abroad. Ask your provider how to ship it. - `carrier_unavailable`: the carrier is temporarily unavailable. Nothing on the order needs correcting; resubmit it later. - `no_shipping_options`: no carrier offered to ship the order. Check the address, and that the items can be shipped to the country. - `fulfillment_not_requested`: the provider has the order but was never asked to ship it. Check the address. - `refused_before_fulfillment`: the provider refused the order before it was asked to ship it, and gave no reason. Check the address. - `insufficient_funds`: the provider could not charge you for the order, so it is not shipping it yet. Nothing on the order needs correcting, and `holdReason` says what could not be charged. If it was your prepaid balance with the provider (NextSmartShip), top up the balance: the order is sent again automatically once the balance covers it. To send it sooner, resubmit it while `externalOrderId` is set, or retry it with `POST /orders/{orderId}/retry-submission` while it is empty. If it was your payment method (ShipBob), update the payment method with the provider, which ships the order itself once a payment goes through. Such an order cannot be resubmitted or retried. - `unspecified`: the provider gave no reason. Look the order up in your provider’s dashboard. - `other`: no code covers the reason yet. Read `holdReason`. ShipBob’s holds for a pick date, a hold placed by hand, a packaging preference not set and an automatic processing pause read `other`, with ShipBob’s description in `holdReason`. One of `postal_code_invalid`, `postal_code_city_mismatch`, `postal_code_not_served`, `state_invalid`, `street_not_found`, `house_number_missing`, `address_incomplete`, `address_invalid_characters`, `name_or_address_too_long`, `po_box_not_accepted`, `address_invalid`, `recipient_name_invalid`, `phone_invalid`, `tax_id_missing`, `customs_details_invalid`, `shipping_restricted`, `carrier_unavailable`, `no_shipping_options`, `fulfillment_not_requested`, `refused_before_fulfillment`, `insufficient_funds`, `unspecified`, `other`. Example: `postal_code_city_mismatch`.
- `heldAt` (string (date-time), required, nullable): When the current hold was detected. A resubmission that is held again starts a new hold with its own timestamp. `null` when the order is not on hold.
- `recipientFaults` (array of object, required, nullable): Problems with the recipient details — name, company, address and phone — that would make NextSmartShip hold or refuse the order, as of the latest check. Each names the detail and the rule it breaks, never the value. The order is checked when it is created, when a change to the customer’s details reaches it, and each time it is submitted automatically; adding, activating or deactivating an integration does not re-check existing orders. `null` when the order has not been checked yet, when the latest check found nothing, or when it did not apply NextSmartShip’s rules because the order was sent to another provider, or had not been sent while you had no active NextSmartShip integration. Always `null` once the order is fulfilled or cancelled. To check an order now, call `GET /orders/{orderId}/recipient-validation`.
  - `field` (string, required): The recipient detail at fault. `name` is the first and last name together, and `address` is both address lines together. One of `first_name`, `last_name`, `name`, `company`, `address`, `address_line_1`, `address_line_2`, `city`, `state`, `postal_code`, `country`, `phone`. Example: `city`.
  - `rule` (string, required): The rule the detail breaks. `missing`: the provider does not accept the order without it, so the order is not sent while it is missing. `placeholder`: a stand-in such as `N/A` rather than a real value. `no_latin_form`: the text has no Latin-alphabet form to print on a shipping label. `too_long`: longer than the provider accepts, after any shortening the rules apply to names and addresses. `too_short`: shorter than the provider accepts. `invalid_format`: not a valid postal code for the country. `postal_code_mismatch`: the city is not a locality of the postal code. `unrecognized`: neither the state nor the postal code identifies a state or province. Every rule but `missing` still lets the order be sent, and the provider is likely to hold it. One of `missing`, `placeholder`, `no_latin_form`, `too_long`, `too_short`, `invalid_format`, `postal_code_mismatch`, `unrecognized`. Example: `postal_code_mismatch`.

### `202`

The merchant is entitled but its OMS environment is not provisioned yet. Provisioning has been kicked off (exactly once) and is in progress; retry the request — it succeeds once the environment is ready. Returned only for identity-token (dashboard) requests bound to an active-entitled merchant, not for secret-key API calls; any such endpoint can return it while provisioning is underway.

Type: object (ProvisioningInProgress).

- `status` (string, required): Signals the merchant OMS environment is still being provisioned. One of `provisioning`.
- `merchantAccountId` (string, required): The merchant account whose OMS environment is being provisioned. Example: `dAI3aa87ROOeupeBCjNSKCOBOisBCYjB`.

### `400`

The request was rejected. `type` is `invalid_request_error`; when the failure is a validation failure `code` is `validation_failed` and `errors` lists every problem found, with field-attributable entries prefixed by the field’s path.

Type: object (ValidationErrorResponse).

- `statusCode` (number, required): HTTP status code. Example: `400`.
- `requestId` (string, required): Unique identifier for the request. Example: `dfc10de3-36bb-4bcc-b081-316216194033`.
- `message` (string, required): The first error message from the validation errors. Example: `note must be a string`.
- `type` (string, required): Coarse, stable classifier for the failure. Present on every error response including 5xx. This is the field to branch on: `statusCode` is too coarse and `message` is human prose that may be reworded. The set is closed and every member is permanent, so it is safe to handle exhaustively. One of `invalid_request_error`, `authentication_error`, `permission_error`, `not_found_error`, `invalid_state_error`, `conflict_error`, `rate_limit_error`, `payment_error`, `api_error`. Example: `invalid_request_error`.
- `code` (string): Fine-grained identifier for the failure, present only where it adds something `type` does not — for example separating a replayed idempotency key from a held lock, or naming the reason a payment was declined. The set is open and grows over time, so treat an unrecognised value as absent and fall back to `type`. Example: `validation_failed`.
- `errors` (array of string): Complete list of validation errors.

### `401`

No credentials were supplied, or the identity token / secret key is not valid for the target merchant. `type` is `authentication_error`.

Type: object (ErrorResponse).

- `statusCode` (number, required): HTTP status code. Example: `400`.
- `requestId` (string, required): Unique identifier for the request. Example: `dfc10de3-36bb-4bcc-b081-316216194033`.
- `message` (string, required): Human-readable description of the failure. Example: `An error occurred`.
- `type` (string, required): Coarse, stable classifier for the failure. Present on every error response including 5xx. This is the field to branch on: `statusCode` is too coarse and `message` is human prose that may be reworded. The set is closed and every member is permanent, so it is safe to handle exhaustively. One of `invalid_request_error`, `authentication_error`, `permission_error`, `not_found_error`, `invalid_state_error`, `conflict_error`, `rate_limit_error`, `payment_error`, `api_error`. Example: `invalid_request_error`.
- `code` (string): Fine-grained identifier for the failure, present only where it adds something `type` does not — for example separating a replayed idempotency key from a held lock, or naming the reason a payment was declined. The set is open and grows over time, so treat an unrecognised value as absent and fall back to `type`. Example: `validation_failed`.

### `403`

The credentials are valid but lack the permission this operation requires. `type` is `permission_error`.

Type: object (ErrorResponse).

- `statusCode` (number, required): HTTP status code. Example: `400`.
- `requestId` (string, required): Unique identifier for the request. Example: `dfc10de3-36bb-4bcc-b081-316216194033`.
- `message` (string, required): Human-readable description of the failure. Example: `An error occurred`.
- `type` (string, required): Coarse, stable classifier for the failure. Present on every error response including 5xx. This is the field to branch on: `statusCode` is too coarse and `message` is human prose that may be reworded. The set is closed and every member is permanent, so it is safe to handle exhaustively. One of `invalid_request_error`, `authentication_error`, `permission_error`, `not_found_error`, `invalid_state_error`, `conflict_error`, `rate_limit_error`, `payment_error`, `api_error`. Example: `invalid_request_error`.
- `code` (string): Fine-grained identifier for the failure, present only where it adds something `type` does not — for example separating a replayed idempotency key from a held lock, or naming the reason a payment was declined. The set is open and grows over time, so treat an unrecognised value as absent and fall back to `type`. Example: `validation_failed`.

### `404`

No resource exists with the requested identifier. `type` is `not_found_error`.

Type: object (ErrorResponse).

- `statusCode` (number, required): HTTP status code. Example: `400`.
- `requestId` (string, required): Unique identifier for the request. Example: `dfc10de3-36bb-4bcc-b081-316216194033`.
- `message` (string, required): Human-readable description of the failure. Example: `An error occurred`.
- `type` (string, required): Coarse, stable classifier for the failure. Present on every error response including 5xx. This is the field to branch on: `statusCode` is too coarse and `message` is human prose that may be reworded. The set is closed and every member is permanent, so it is safe to handle exhaustively. One of `invalid_request_error`, `authentication_error`, `permission_error`, `not_found_error`, `invalid_state_error`, `conflict_error`, `rate_limit_error`, `payment_error`, `api_error`. Example: `invalid_request_error`.
- `code` (string): Fine-grained identifier for the failure, present only where it adds something `type` does not — for example separating a replayed idempotency key from a held lock, or naming the reason a payment was declined. The set is open and grows over time, so treat an unrecognised value as absent and fall back to `type`. Example: `validation_failed`.

### `429`

Too many requests. The rate limit is applied per client across all operations. `type` is `rate_limit_error`.

Type: object (ErrorResponse).

- `statusCode` (number, required): HTTP status code. Example: `400`.
- `requestId` (string, required): Unique identifier for the request. Example: `dfc10de3-36bb-4bcc-b081-316216194033`.
- `message` (string, required): Human-readable description of the failure. Example: `An error occurred`.
- `type` (string, required): Coarse, stable classifier for the failure. Present on every error response including 5xx. This is the field to branch on: `statusCode` is too coarse and `message` is human prose that may be reworded. The set is closed and every member is permanent, so it is safe to handle exhaustively. One of `invalid_request_error`, `authentication_error`, `permission_error`, `not_found_error`, `invalid_state_error`, `conflict_error`, `rate_limit_error`, `payment_error`, `api_error`. Example: `invalid_request_error`.
- `code` (string): Fine-grained identifier for the failure, present only where it adds something `type` does not — for example separating a replayed idempotency key from a held lock, or naming the reason a payment was declined. The set is open and grows over time, so treat an unrecognised value as absent and fall back to `type`. Example: `validation_failed`.

### `500`

The request could not be completed because of an unexpected error. `type` is `api_error`.

Type: object (ErrorResponse).

- `statusCode` (number, required): HTTP status code. Example: `400`.
- `requestId` (string, required): Unique identifier for the request. Example: `dfc10de3-36bb-4bcc-b081-316216194033`.
- `message` (string, required): Human-readable description of the failure. Example: `An error occurred`.
- `type` (string, required): Coarse, stable classifier for the failure. Present on every error response including 5xx. This is the field to branch on: `statusCode` is too coarse and `message` is human prose that may be reworded. The set is closed and every member is permanent, so it is safe to handle exhaustively. One of `invalid_request_error`, `authentication_error`, `permission_error`, `not_found_error`, `invalid_state_error`, `conflict_error`, `rate_limit_error`, `payment_error`, `api_error`. Example: `invalid_request_error`.
- `code` (string): Fine-grained identifier for the failure, present only where it adds something `type` does not — for example separating a replayed idempotency key from a held lock, or naming the reason a payment was declined. The set is open and grows over time, so treat an unrecognised value as absent and fall back to `type`. Example: `validation_failed`.

### `503`

A dependency needed to serve the request is temporarily unavailable — for every operation the auth service that verifies credentials and resolves entitlement, and on the provisioning routes also the ODUS API the OMS reconciles against. `type` is `api_error`. Unlike a plain 500 the condition is transient rather than a fault in the request, so it is worth retrying with backoff.

Type: object (ErrorResponse).

- `statusCode` (number, required): HTTP status code. Example: `400`.
- `requestId` (string, required): Unique identifier for the request. Example: `dfc10de3-36bb-4bcc-b081-316216194033`.
- `message` (string, required): Human-readable description of the failure. Example: `An error occurred`.
- `type` (string, required): Coarse, stable classifier for the failure. Present on every error response including 5xx. This is the field to branch on: `statusCode` is too coarse and `message` is human prose that may be reworded. The set is closed and every member is permanent, so it is safe to handle exhaustively. One of `invalid_request_error`, `authentication_error`, `permission_error`, `not_found_error`, `invalid_state_error`, `conflict_error`, `rate_limit_error`, `payment_error`, `api_error`. Example: `invalid_request_error`.
- `code` (string): Fine-grained identifier for the failure, present only where it adds something `type` does not — for example separating a replayed idempotency key from a held lock, or naming the reason a payment was declined. The set is open and grows over time, so treat an unrecognised value as absent and fall back to `type`. Example: `validation_failed`.

### `504`

The request exceeded the processing time limit and was abandoned. `type` is `api_error` and `code` is `timeout` — unlike a plain 500 the request may still have taken effect.

Type: object (ErrorResponse).

- `statusCode` (number, required): HTTP status code. Example: `400`.
- `requestId` (string, required): Unique identifier for the request. Example: `dfc10de3-36bb-4bcc-b081-316216194033`.
- `message` (string, required): Human-readable description of the failure. Example: `An error occurred`.
- `type` (string, required): Coarse, stable classifier for the failure. Present on every error response including 5xx. This is the field to branch on: `statusCode` is too coarse and `message` is human prose that may be reworded. The set is closed and every member is permanent, so it is safe to handle exhaustively. One of `invalid_request_error`, `authentication_error`, `permission_error`, `not_found_error`, `invalid_state_error`, `conflict_error`, `rate_limit_error`, `payment_error`, `api_error`. Example: `invalid_request_error`.
- `code` (string): Fine-grained identifier for the failure, present only where it adds something `type` does not — for example separating a replayed idempotency key from a held lock, or naming the reason a payment was declined. The set is open and grows over time, so treat an unrecognised value as absent and fall back to `type`. Example: `validation_failed`.

---

Generated from the OMS API OpenAPI document, https://sandbox-oms-api.odus.com/openapi.json. Interactive page: https://docs.odus.com/docs/api/oms/order-resubmission-controller-resubmit
