Errors

Every error uses the same envelope with a stable code, a message, optional validation and repair details, and the request id.

Envelope

{
  "error": {
    "type": "validation_error",
    "code": "validation_failed",
    "message": "Request validation failed.",
    "param": "type",
    "errors": [{ "path": "type", "message": "Use types instead." }],
    "suggestedAction": "replace_param",
    "repairCategory": "unknown_param",
    "documentationPath": "/api/v1/openapi.json",
    "doNotRetrySameRequest": true,
    "requestId": "request-id"
  }
}

Keep the requestId for debugging.

Repair metadata

v1.21 errors can include machine-readable repair fields, including write-readiness and impact details on supported product and Cost Book writes. Treat them as the next-request plan, not as hints that relax the schema.

FieldUse it for
repairCategoryClassify the failure, such as unknown_param, invalid_enum, unsupported_sync_filter, standalone_status, invalid_window, or rate_limited.
suggestedActionChoose the next action, such as add_required_filter, replace_param, choose_valid_value, pair_date_window, narrow_filter, wait_and_retry, or stop_and_fix_request.
validValuesUse only accepted values for the named parameter.
acceptedFiltersPick one of the endpoint's supported narrowing filters instead of inventing a broad sync request.
requiredCombinationSend the fields together, such as paired date-window parameters.
maxWindowDaysSplit changed-record discovery windows that are too wide.
documentationPathOpen /api/v1/openapi.json or /llms.txt for the exact contract guidance.
exampleShape the corrected request with an endpoint-specific example.
doNotRetrySameRequestChange the request before retrying. Do not loop the identical request.
writeReadinessReview machine-readable readiness details when a write request fails validation or policy checks.
impactAnalysisInspect product or product-family impact details before retrying a constrained catalog write.

For example, if /search rejects type, replace it with types. If /contacts rejects a broad list request, provide parentType and parentId. If /orders or /purchase-orders rejects standalone status, pair it with an exact identifier or a bounded date window.

Common codes

CodeCaller action
invalid_api_keyCheck the environment value and bearer header format.
api_key_revokedStop and request a new key.
api_key_expiredStop and request a new key.
api_actor_inactiveStop and issue a key to an active user.
missing_scopeUse a key with the required scope.
missing_permissionUse an acting user with the required ShelfCycle permission.
rate_limitedWait for Retry-After or retryAfterSeconds. Retry POSTs with the same idempotency key.
validation_failedFix the field named in param or errors[].
finder_filter_requiredAdd a supported narrowing predicate before retrying a root finder.
unsupported_sync_filterRemove sync-style filters such as updatedSince. Root finders are not exports. Reference directory and child-list routes support cursor paging only in v1.21. For sales orders and purchase orders, use paired updatedAtFrom/updatedAtTo only for bounded changed-record discovery.
not_foundRe-search and confirm the id. Cross-org, unsupported, archived, or invisible records can also return not_found.
idempotency_key_requiredSend a stable Idempotency-Key for POST requests.
idempotency_key_reusedRetry with the original body or choose a new key for a new source event.
duplicate_customerUse the existing customer or change the source data before retrying.
duplicate_supplierUse the existing supplier or change the source data before retrying.
duplicate_productUse the existing product or change product setup references before retrying.
duplicate_familyUse the existing product family or change the family identity before retrying.
duplicate_contactUse the existing contact or change the source data before retrying.
duplicate_customer_location, duplicate_customer_address, duplicate_supplier_ship_from_locationUse the existing child record or change source identity/address data before retrying.
duplicate_documentUse the existing attached document or change the source URL before retrying.
stale_recordRefresh context before retrying.
archived_recordDo not write to archived records.
unsupported_linked_recordRemove unsupported records. Orders and purchase orders are context, not note subjects or links.
not_api_createdDo not patch that note through the public API.
primary_change_unsupported, address_role_requiredRemove primary switching from customer location requests, or keep customer addresses marked billing or shipping.
unsupported_product_field, unsupported_family_field, invalid_variable_qty, reference_visibility_blockedKeep product setup inside the public contract, use quantity 1 for variable packaging, and verify referenced records are visible.
document_url_invalid, document_url_cross_org, unsupported_document_fieldSend only fileName and an HTTPS URL that belongs to the authenticated org when it points at a ShelfCycle bucket.
blocked_order_sensitive_updateChange only allowed metadata fields, or leave order-sensitive product identity, packaging, and supplier fields unchanged.

On dryRun=true, HTTP 200 can still return data.status: "blocked". Inspect blocked checks such as duplicate_candidate_found, idempotency_target_missing, idempotency_key_required, idempotency_key_reused, stale_record, archived_record, target_not_found_or_not_visible, unsupported_profile_shape, primary_change_unsupported, address_role_required, product_family_reference_active, product_packaging_reference_active, supplier_reference_active, reference_visibility_blocked, order_sensitive_update_blocked, unsupported_linked_record, not_api_created, or validation_failed before execution.

Rate limits

Default private v1 limits are 60 read requests per minute per key and endpoint, and 20 write requests per minute per key and endpoint.

On 429 rate_limited, read Retry-After and wait before retrying. Successful authenticated requests and rate-limited requests include X-RateLimit-Remaining when the rate-limit check runs.

Guardrail

Stop on stale, duplicate, missing access, unsupported sync, revoked, expired, archived, or rate-limit errors. Do not keep retrying without new information.