Skip to content
Last updated

Errors & Idempotency

Every v5 error response uses the same envelope:

{
  "error": {
    "code": "validation_failed",
    "message": "Human-readable summary.",
    "details": {
      "field": ["Per-field error message"]
    }
  }
}

The HTTP status gives the broad category. The error.code tells you what specifically happened. Branch on the code, not the message text.

Common recovery paths

CodeWhat to do
validation_failedFix error.details before retrying.
unauthenticated, token_expired, token_revokedIssue or select a valid token.
scope_missingRe-issue a token with the missing scope.
insufficient_creditsTop up credits before purchasing labels.
too_many_requestsRetry with exponential backoff after the seconds reported by both the Retry-After response header and error.details.retry_after_seconds.
conflict, *_in_use, not_voidable, not_cancellableInspect the resource state and retry only after it changes.
internal_errorRetry; contact support with the request ID if persistent.

The API Reference documents the full error vocabulary.

Responses that are not in the envelope

An HTML 403 response whose body contains error code: 1010 did not come from Stallion; Cloudflare refused it at the edge because of a generic client signature. Send an Authorization header on every request (authenticated /api/ traffic is exempt from the browser checks) and a User-Agent that names your integration, then retry. See Getting Started.

Idempotency-Key

Every v5 endpoint that creates or charges accepts an optional Idempotency-Key header. Generate a unique value per logical operation and reuse the same key only when retrying the exact same request body.

KEY=$(uuidgen)
curl -X POST "$STALLION_BASE_URL/labels" \
  -H "Authorization: Bearer $STALLION_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $KEY" \
  -d '{ ... }'

Behavior:

  • Same key and same body within 24 hours returns the original response with Idempotent-Replay: true.
  • Same key with a different body returns 409 idempotency_conflict.
  • 5xx responses are not cached, so transient infrastructure failures can be retried with the same key.

Use this header for shipment creation, label purchase, pickups, LTL bookings, credit top-ups, product classification, and manufacturer verification.