Skip to content

Errors

The API uses conventional HTTP status codes and returns a JSON error body. There are three error shapes.

Validation errors (400) return an error string plus a details array, one entry per invalid field:

{
"error": "Validation failed",
"details": [
{ "field": "clientId", "message": "Invalid client ID format" },
{ "field": "firstName", "message": "First name is required" }
]
}

Most other errors return an error label and a human-readable message:

{
"error": "Unauthorized",
"message": "Invalid organization authentication token"
}

Some errors return just an error label, with no message. An unmatched route and an unexpected server error are both this shape, so treat message as optional on every error:

{
"error": "Not Found"
}
{
"error": "Internal Server Error"
}
Status error label When it happens
400 Validation failed / Bad Request / Invalid request Request body, params or query failed schema validation; a path parameter is not a valid resource reference; malformed or expired token on revoke; missing X-Idempotency-Key on a request that requires one.
401 Unauthorized Missing/invalid/expired/revoked token, missing x-client-id, x-client-id ≠ token, invalid credentials, no signing key registered, or failed signature / Content-Digest verification.
403 Forbidden Client IP is not in the credential’s allowlist (trustedIps).
404 Not found / Transaction not found / Not Found The resource does not exist or does not belong to your organization. An unmatched route returns { "error": "Not Found" } with no message.
409 Conflict A concurrent request with the same X-Idempotency-Key is still in flight. Retry once it settles.
422 Unprocessable Entity An X-Idempotency-Key was reused with a different request payload.
429 Too Many Requests A rate limit was exceeded — the global 300/min budget, or the stricter 10 per 15 min on POST /v1/oauth/token. Both are keyed per IP. Honour Retry-After.
500 Internal Server Error Unexpected server error, and any request body the parser rejects — see Request body limits. The body is the error label alone — Pipevest never returns an exception message, stack frame or database detail to a partner. Safe to retry idempotent requests with backoff.
503 Service Unavailable A dependency the endpoint needs is not configured or not reachable. Retry with backoff.

JSON request bodies are capped at 100 kB (102,400 bytes). A body over that limit, and a body that is not well-formed JSON, are both rejected before the request reaches any route.

Both cases answer 500 with the bare Internal Server Error label — not 400, and not 413:

{
"error": "Internal Server Error"
}

Send Content-Type: application/json exactly. A +json suffix type such as application/vnd.api+json is not parsed at all, and the request then fails validation at the root with an empty field:

{
"error": "Validation failed",
"details": [
{ "field": "", "message": "Invalid input: expected object, received undefined" }
]
}

An empty field always means the failure is about the body as a whole rather than about one property, so key your error handling on field being empty rather than assuming every entry names a property.

Missing x-client-id header (401)

{
"error": "Unauthorized",
"message": "x-client-id header is required"
}

x-client-id does not match the token (401)

{
"error": "Unauthorized",
"message": "Client ID mismatch"
}

Client IP not allowlisted (403)

{
"error": "Forbidden",
"message": "Client IP not allowed"
}

Rate limit exceeded (429)

{
"error": "Too Many Requests",
"message": "Too many requests. Please slow down and try again shortly."
}

The token endpoint has its own limiter and its own message — see Rate Limits.

Request not signed, or signature does not verify (401)

{
"error": "Unauthorized",
"message": "Signature verification failed"
}

Returned when Signature / Signature-Input are missing, malformed, expired, cover a component the request does not carry, or do not verify against your registered key.

Body does not match the digest (401)

{
"error": "Unauthorized",
"message": "Content-Digest verification failed"
}

No public key registered for your credential (401)

{
"error": "Unauthorized",
"message": "No signing key registered for this client"
}

You cannot fix this one by re-signing — your credential has no public key on file. Contact engineering.support@pipevest.com to register or rotate it.

Missing idempotency key on a mutation (400)

{
"error": "Bad Request",
"message": "X-Idempotency-Key header is required for this request"
}