code and nested error codes; reserve detail and message for logs and
developer-facing output. Nested field values are JSON paths into the request
body (claims[0].principal_amount, debtor_id,
additional_debtor_ids[0]) or, for query strings, the parameter name.
Retry writes safely
Every effectfulPOST requires Idempotency-Key. Generate one opaque key per
logical command and retain it until the outcome is known.
{}. A successful call returns the
complete Order representation defined by the operation reference; the fully
valid error above shows a lifecycle conflict that must be resolved rather than
blindly retried.
The key is scoped by tenant, method, operation, and normalized path. For Case
Management commands the tenant is the selected company; for Partner management
commands it is the Partner owner. Direct and Partner credentials authorized for
the same Case company share its retry namespace. The path is compared
case-insensitively, so an upper-case resource id names the same command as its
lower-case form. Equivalent JSON object-key order and multipart part order
replay; array order remains significant.
Rotating an API secret or replacing a token preserves retry protection. Retry
with the same Idempotency-Key and request after changing credentials; the
replacement credential must still have the operation’s required scopes and
current access to the tenant. A changed request returns
409 idempotency_key_conflict. Use different keys for different logical
commands, including when several integrations act for the same company.
- An exact completed retry replays the original status, body, and application
headers and adds
Idempotency-Replayed: true. - The same key with a different request returns typed
409. - A retry while the original call is running waits up to 2 seconds for it. If
the original finishes in that time, the retry receives its response with
Idempotency-Replayed: true; otherwise it returns409 idempotency_request_in_progresswithRetry-After: 2. - A completed response replays for 24 hours. After that the key answers
409 idempotency_key_expiredfor another 24 hours and is then forgotten (48 hours in total): a request with it executes as a new command. When a Partner’s access to a company ends, its stored responses for that company expire at once: they answer409 idempotency_key_expiredfor 24 hours and are then forgotten. - A
5xxoutcome is never stored: a failure raised inside the command — including503 service_unavailablefrom a transient database or storage fault — releases the key, so retrying the same key re-executes the command instead of replaying the failure. Only an error status the command itself returns as its result claims the key. The same release applies to a raised4xx: a corrected retry under the same key executes normally. - The header holds exactly one key; a value containing
,(typically twoIdempotency-Keyheaders folded together) is400 validation_error.
Recover by status
Common error codes
The top-levelcode names the failure class; nested errors[].code names the
rule a field broke. Codes you should branch on beyond required,
invalid, blank, max_length, invalid_choice, and unknown_field:
Record the fresh
X-Paywise-Request-Id when contacting support. Caller-supplied
request IDs are ignored. Validation failures and idempotent replays consume
rate-limit capacity; authentication, tenant-context, and access failures do not.
Inspect rate-limit headroom
GET /v2/usage/ and GET /partner/v2/usage/ return the live buckets used for
enforcement. Usage and info are ordinary reads, consume principal capacity,
and can return 429; usage includes its own request in the used count.
Direct Case and Mahnservice requests charge credential and company buckets;
Partner management charges credential and Partner; Partner-on-behalf Case
requests charge credential, Partner, and selected company. Each allows 600
requests per minute. Reads have no per-operation bucket; every write also
charges endpoint:<basename>.<action> at 120 per minute.
Webhook test delivery and manual redelivery share a company-scoped
20-per-hour expensive-operation bucket. Expensive buckets are checked before
the operation and charged only after a qualifying success (200 download,
202 accepted dispatch); other outcomes do not charge. They do not reserve
capacity for in-flight work, so concurrent successes can all pass the
pre-check. Once the stored bucket is full, later requests answer 429 up
front.
There are no X-RateLimit-* headers. If the shared counter store is
temporarily unavailable, normal enforcement fails open and emits an
operational signal; the usage operation fails closed with typed 503 instead
of returning fabricated counters.
See finalize an order,
Case usage, and
Partner usage for the current
operation contracts.