paybondpaybond
Sign in

Error envelope and status codes

How Paybond APIs format errors, which HTTP status codes to expect, and when a request is safe to retry.

Paybond uses one consistent error contract across Harbor, Gateway, and Signal. This page explains how failed requests are shaped, what each status code means, and when a retry is appropriate. If you use a Paybond SDK, the same responses are surfaced as typed errors; see Error handling.

Error response format

When a Paybond API returns a structured JSON error, it uses this envelope:

{
  "error": {
    "code": "intent.predicate.failed",
    "message": "predicate evaluation failed",
    "details": { "clause": "completion", "path": ["status"] }
  },
  "request_id": "01JABY5…"
}

Guidelines:

  • error.code is a stable, machine-readable identifier. New codes may be added over time, so clients should handle unknown codes by falling back to the broader error class.
  • error.message is safe to log. It does not include bearer tokens, secrets, or other tenants' identifiers.
  • error.details is optional structured context for diagnostics. Treat it as integration metadata, not end-user copy.
  • request_id is the primary support and trace identifier. Include it when contacting Paybond support.

Some older routes still return { "error": "message" } as a plain string. If you need backward compatibility, accept either form.

Status codes

StatusMeaningRetriable?
400 Bad RequestThe request is malformed or missing required fields. Settlement PUT /v1/admin/settlement/config may return 400 for invalid rail combinations, missing linked Stripe destination when enabling Stripe rails, invalid x402 address format, invalid MPP profile prefix for the tenant environment (profile_test_* sandbox vs live profile_*), or mpp_session_enabled without a valid Tempo recipient.No — correct the request and try again.
401 UnauthorizedCredentials are missing, expired, or do not match the requested tenant context.Yes — refresh credentials or sign in again.
403 ForbiddenThe caller is authenticated but does not have the required role or entitlement.No — use an account with the required access.
404 Not FoundThe resource does not exist in the authenticated tenant scope. Cross-tenant lookups also return 404 so resource existence is not leaked.Sometimes — retry only if the resource was just created.
409 ConflictThe request conflicts with the current resource state. Common examples are idempotency-key reuse with a different request body or an invalid state transition.No — inspect the current state or use a new key.
402 Payment RequiredA funding handshake needs a client credential before Harbor can advance the intent. Used by x402_usdc_base (payment-session challenge) and stripe_mpp (Payment Auth). Responses include rail-specific headers such as WWW-Authenticate, payment-required, or Cache-Control: no-store. Retry the same POST /fund with the credential on payment-signature (x402) or x-paybond-payment-authorization (MPP via Gateway). Invalid MPP credentials may return 402 with Content-Type: application/problem+json.Yes — retry with the correct credential; reuse the same idempotency-key and body.
410 GoneA temporary download or export is no longer available.No — request a fresh export.
422 Unprocessable EntityThe request is valid JSON but cannot be applied in the current business state.No — adjust the request or resolve the underlying state first.
428 Precondition RequiredThe request is missing an explicit confirmation or precondition contract. For example, Gateway policy rollback requires the expected current head, target digest, and confirm=true.No — include the required preconditions and retry.
429 Too Many RequestsThe request hit a rate limit. Honor Retry-After; Gateway rate-limit responses also return X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, RateLimit, and RateLimit-Policy.Yes — back off and retry later.
500 Internal Server ErrorPaybond hit an unexpected server-side error.Sometimes — retry idempotent requests with exponential backoff.
503 Service UnavailableA dependency or platform service is temporarily unavailable.Yes — retry with backoff.

Retry guidance

  • Retry GET requests on 500 or 503 with exponential backoff.
  • Retry supported Harbor POST requests only when you reuse the same idempotency-key with the same request body.
  • Treat most 4xx responses as non-retriable, except for 401 and 429.

The Harbor routes that currently honor idempotency-key are listed in the Harbor API reference. DELETE /v1/compliance/audit-exports/{job_id} is also idempotent: repeating the request does not create a second side effect.

Logging

Log the HTTP status, error.code, and request_id for troubleshooting. Do not log bearer tokens, secrets, or tenant data that is not needed for support.

SDK errors

ErrorThrown when
HarborHttpError (TS / Python)A Harbor HTTP call returns a non-2xx. Carries status_code, url, and body_text.
GatewayAuthErrorGateway principal lookup or service-account authorization failed while opening a hosted Kit session.
PaybondCapabilityErrorCapability verification failed (invalid signature, wrong tenant, expired, revoked).

See Error handling for language-level patterns such as retry policy, structured logging, and circuit breakers.