Polivor

Errors and limits

Error format

Errors are RFC 9457 problem details (application/problem+json) with a stable code that your code can rely on. The text in title and detail can change; the code does not.

{
  "type": "about:blank",
  "title": "Unprocessable Entity",
  "status": 422,
  "code": "VALIDATION_FAILED",
  "detail": "The request is invalid",
  "errors": [{ "path": "/action/amount_minor", "message": "must be a whole number of minor units" }]
}

Error codes

Every code the API can return is listed here, with its HTTP status. A code is stable: match on it, not on the detail text. The MCP tools return the same codes inside a tool result.

HTTPCodeWhen
400MALFORMED_REQUESTThe body is not valid JSON, has the wrong shape, or a parameter has the wrong type.
400IDEMPOTENCY_KEY_REQUIREDauthorize without an Idempotency-Key of 1 to 128 characters.
400UNSUPPORTED_PROTOCOL_VERSIONAn MCP request names a protocol version the server does not support; the detail lists the supported ones.
401UNAUTHENTICATEDNo key, or an unknown or revoked key.
403FORBIDDENThe key's role may not call this operation.
403ORIGIN_NOT_ALLOWEDAn MCP request carries an Origin header: MCP clients are programs, not web pages.
404NOT_FOUNDNo such object, or it belongs to another tenant.
405METHOD_NOT_ALLOWEDThe path exists, but not for this HTTP method.
409IDEMPOTENCY_KEY_REUSEDThe key was used with a different body.
409IDEMPOTENCY_KEY_EXPIREDThe key is past its 24 hour retention.
409ALREADY_REPORTEDThe authorization already has its terminal report.
409AUTHORIZATION_STILL_VALIDAn admin tried to release an authorization the enforcement point can still use until it expires.
409MANDATE_REVOKED, MANDATE_SUSPENDED, MANDATE_NOT_ACTIVEThe mandate's state does not allow the operation.
409MANDATE_NOT_SUSPENDEDResume was called on a mandate that is not suspended (a draft is activated, not resumed).
409NOTHING_TO_ACTIVATEThe latest version of the mandate is already in force.
409POLICY_RETIREDA retired policy version cannot be published again.
409VERSION_EXISTSThis agent version is already registered.
409BENEFICIARY_EXISTSA beneficiary with this external_id already exists.
409LAST_ADMIN_KEYYou cannot revoke the last active admin key.
409AP2_ALREADY_IMPORTEDThis AP2 credential was already imported; the detail names the mandate.
410REPORT_WINDOW_CLOSEDMore than 24 hours after the authorization expired.
415UNSUPPORTED_MEDIA_TYPEThe request is not Content-Type: application/json.
422VALIDATION_FAILEDA field is missing, out of range or malformed; errors lists each.
422UNKNOWN_PRINCIPALThe principal named in the request does not exist.
422RANGE_TOO_LARGEAn evidence export of more than 10,000 records.
422MANDATE_INVALIDThe mandate document does not meet the schema; errors lists each problem.
422MANDATE_INCOMPLETEThe mandate lacks parts it needs before it can be activated; add a version with them.
422MANDATE_NOT_ACTIVATABLEThis mandate version cannot be activated yet; errors says why.
422POLICY_INVALIDThe policy is not valid Cedar for the Polivor schema; errors carries line and column.
422AP2_MALFORMEDThe credential is not a well-formed signed SD-JWT, or its mandate is not shaped as expected.
422AP2_SIGNATURE_INVALIDThe credential signature is wrong, or it is not signed with ES256.
422AP2_UNKNOWN_KEYThe credential names no signing key, or one that is not among the trusted issuer's keys.
422AP2_DISCLOSURE_INVALIDA disclosure is malformed, repeated, unreferenced or misplaced, or the credential is nested too deeply or uses a hash other than sha-256.
422AP2_ISSUER_KEYS_UNAVAILABLEThe issuer's key set could not be fetched, or is not acceptable.
422AP2_UNSUPPORTED_MANDATEThe credential is not an Open Payment Mandate.
422AP2_EXPIREDThe credential has expired, has no expiry, or its execution window leaves no valid time.
422AP2_NOT_YET_VALIDThe credential is issued in the future.
422AP2_NO_AGENT_KEYThe mandate does not name the agent's key.
422AP2_AMOUNT_NOT_INTEGERThe maximum amount is not a whole number of minor units.
422AP2_CONSTRAINT_INVALIDA constraint is malformed: no type, a bad currency or time, or a repeated amount range.
422AP2_UNENFORCED_CONSTRAINTSThe credential carries constraints Polivor does not enforce, and the import did not accept that.
422AP2_UNKNOWN_CONSTRAINTThe credential carries constraint types this adapter does not know.
429RATE_LIMITEDToo many requests; see below.
500INTERNALAn unexpected error. The detail carries a reference to quote when you ask for help.

Every operation in the reference lists the status codes it can return.

Rate limits

Each API key has its own limit: 20 requests per second for agent and enforcer keys and 5 per second for admin keys, with a burst of one second. Over the limit you get 429 RATE_LIMITED with a Retry-After header; wait that long and retry. If one key is not enough, issue more keys for the same agent.

Idempotency

Retrying authorize with the same Idempotency-Key and body is safe and returns the original response for 24 hours. Retry network failures and 5xx answers with the same key.

Conventions

  • Money: integer minor units and an ISO 4217 currency. No decimals.
  • Times: ISO 8601 in UTC, for example 2026-10-14T10:05:00Z.
  • Ids: UUIDs. IBANs: spaces and lower case are accepted and normalised; the checksum is verified.
  • Unknown fields in requests are ignored where the reference says so, and refused where it does not.
  • Response time: the authorize response carries a Server-Timing: authorize;dur=<milliseconds> header with the time the decision took inside Polivor.