The Platform, Management and VKS HTTP APIs use Problem Details (application/problem+json). Check the status and machine-readable code together with the operation you called. Codes are open strings, not an exhaustive enum; keep a fallback for unfamiliar values. Human-readable title and detail are not branching keys.
Problem Details · problem+json Check code Schema-specific fields RPC: protocol errors
| Field | Required | Meaning |
|---|---|---|
type | yes | URI identifying the problem category |
title | yes | Human-readable label |
status | yes | HTTP status |
code | yes | Machine-readable service code; sometimes unspecified |
detail | no | Explanation for this occurrence |
instance | no | Occurrence identifier; include it in support requests |
{
"type": "https://docs.vilna.io/apis/errors#not-found",
"title": "Not Found",
"status": 404,
"code": "address.not_found",
"detail": "address not found",
"instance": "/traces/0123456789abcdef0123456789abcdef"
}Use the schema declared by the operation for fields such as fields, max or window_seconds.
Invalid Request
Fix malformed input. Platform and Management may use different codes for the same status.
{
"type": "https://docs.vilna.io/apis/errors#invalid-request",
"title": "Invalid Request",
"status": 400,
"code": "request.malformed",
"detail": "The request could not be decoded.",
"instance": "/traces/0123456789abcdef0123456789abcdef"
}Unauthorized
Check the credential and its service.
{
"type": "https://docs.vilna.io/apis/errors#unauthorized",
"title": "Unauthorized",
"status": 401,
"code": "unspecified",
"detail": "You are not authorized to access this resource. If the problem persists, please contact our support team.",
"instance": "/unauthorized?method=createInvoice"
}Forbidden
The caller lacks access. Check current permissions; an idempotency key grants no access.
Not Found
The resource is absent or not visible to this caller.
{
"type": "https://docs.vilna.io/apis/errors#not-found",
"title": "Not Found",
"status": 404,
"code": "project.not_found",
"detail": "project not found",
"instance": "/traces/0199ce911a2b7c019c2a9d0010eaa310"
}Method Not Allowed
Use a method supported by the route.
Request Canceled
A canceled connection does not prove that a mutation failed. Retry with its original intent key and inputs when required.
Conflict
The operation conflicts with resource state or its idempotency binding. Inspect code before deciding what to do.
{
"type": "https://docs.vilna.io/apis/errors#conflict",
"title": "Conflict",
"status": 409,
"code": "invoice.address_occupied",
"detail": "address already has an active invoice with different parameters",
"instance": "/traces/0123456789abcdef0123456789abcdef"
}Request Too Large
Reduce the payload to the endpoint’s size limit.
Precondition Failed
A business rule or state precondition rejected the request. Fix that condition before retrying.
{
"type": "https://docs.vilna.io/apis/errors#precondition",
"title": "Precondition Failed",
"status": 422,
"code": "invoice.not_cancellable",
"detail": "invoice cannot be cancelled in current status",
"instance": "/traces/0123456789abcdef0123456789abcdef",
"fields": [
{
"name": "status",
"reason": "confirmed"
}
]
}Too Many Requests
This can mean a resource quota, an action window or a resend cooldown. See Rate limits for the different recovery paths.
Not Implemented
The operation is unsupported. Repeating unchanged input will not add support.
Bad Gateway
A required service was unavailable. Retry with backoff and the same mutation intent.
Service Unavailable
The operation is temporarily unavailable. Retry with backoff, preserving the mutation key and inputs.
{
"type": "https://docs.vilna.io/apis/errors#service-unavailable",
"title": "Service Unavailable",
"status": 503,
"code": "service.temporarily_unavailable",
"detail": "The operation is temporarily unavailable. Please try again later."
}Gateway Timeout
The request exceeded its deadline. The outcome may be uncertain; preserve the original intent on retry.
Server Error
An unexpected server error does not establish whether a side effect occurred. Use backoff and the original mutation key; reconcile if its replay is unavailable.
The conflicts idempotency_in_progress, idempotency_request_mismatch, idempotency_result_expired and idempotency_result_unavailable require different recovery steps. Keep the original key and request inputs; never automatically substitute a new key for an unknown outcome. See Idempotency for scope, windows and per-service recovery. An invalid or repeated header returns 400, rather than an idempotency 409.
400 and 422 schemas can include fields, an array of { "name": "…", "reason": "…" } entries. Entries can describe invalid input or diagnostic state, such as name: status, reason: confirmed when an invoice cannot be cancelled. A malformed JSON request need not identify a single field.
A QuotaExceededProblem adds max, the effective configured resource limit in the operation’s scope. It is not usage or remaining capacity. Waiting does not free capacity: reduce usage where the product permits it, or arrange a limit change. A zero limit prohibits new admissions without disabling resources already held.
{
"type": "https://docs.vilna.io/apis/errors#too-many-requests",
"title": "Too Many Requests",
"status": 429,
"code": "address.quota_exceeded",
"detail": "the project has reached its address limit",
"max": 100
}{
"type": "https://docs.vilna.io/apis/errors#too-many-requests",
"title": "Too Many Requests",
"status": 429,
"code": "project.limit_exceeded",
"detail": "project limit exceeded",
"max": 2
}For balance refresh, RateLimitExceededProblem adds max and window_seconds. The window duration is not the remaining wait. Retry-After gives whole seconds until an earliest retry when max > 0 and the deadline is known; it is omitted for max: 0 or an unknown deadline. A zero limit requires a policy change, not backoff alone. The next attempt checks capacity again.
{
"type": "https://docs.vilna.io/apis/errors#too-many-requests",
"title": "Too Many Requests",
"status": 429,
"code": "balance.refresh_rate_exceeded",
"detail": "the project has reached its balance refresh rate limit",
"max": 1,
"window_seconds": 60
}Notification resend can return 429 with notification.resend_delayed. Its Retry-After is the rounded-up wait to the later of the delivery pause and the cooldown since the last attempt. It is a hint, not a reservation. Retry the same request and intent key after waiting. A queued/running send is instead 409 notification.send_in_progress; expired content is 409 notification.payload_unavailable. Inspect the notification and its logs before another action.
{
"type": "https://docs.vilna.io/apis/errors#too-many-requests",
"title": "Too Many Requests",
"status": 429,
"code": "notification.resend_delayed",
"detail": "notification resend is delayed",
"instance": "/traces/0123456789abcdef0123456789abcdef"
}These type fragments are used by public VKS response examples. They are examples of open codes, not the complete set of possible responses. Preserve the supplied type URI when logging an error.
Unexpected failure; retry the original intent with backoff, then reconcile if the outcome remains uncertain.
{
"type": "https://docs.vilna.io/apis/errors#backend.failure",
"title": "Internal Server Error",
"status": 500,
"code": "backend.failure",
"detail": "internal error"
}Correct the request against the operation schema.
{
"type": "https://docs.vilna.io/apis/errors#request.invalid",
"title": "Bad Request",
"status": 400,
"code": "request.invalid",
"detail": "invalid request"
}Check the transaction identity and workspace access.
{
"type": "https://docs.vilna.io/apis/errors#transaction.not_found",
"title": "Not Found",
"status": 404,
"code": "transaction.not_found",
"detail": "transaction not found"
}Read the account state and check which states the operation permits. Wait only if setup is still progressing; some operations remain unavailable for an active account.
{
"type": "https://docs.vilna.io/apis/errors#account.state_invalid",
"title": "Conflict",
"status": 409,
"code": "account.state_invalid",
"detail": "account state does not allow this operation"
}Read the transaction state before choosing another action.
{
"type": "https://docs.vilna.io/apis/errors#transaction.state_invalid",
"title": "Conflict",
"status": 409,
"code": "transaction.state_invalid",
"detail": "transaction state does not allow this operation"
}A send is already pending. Check send history rather than queueing another send.
{
"type": "https://docs.vilna.io/apis/errors#transaction.send_in_progress",
"title": "Conflict",
"status": 409,
"code": "transaction.send_in_progress",
"detail": "transaction has a pending send attempt"
}The node already accepted the transaction. Check send history; this does not establish chain confirmation.
{
"type": "https://docs.vilna.io/apis/errors#transaction.already_sent",
"title": "Conflict",
"status": 409,
"code": "transaction.already_sent",
"detail": "transaction was already accepted by RPC"
}max is the transaction’s shared manual and automatic attempt limit. Waiting alone does not reset it.
{
"type": "https://docs.vilna.io/apis/errors#transaction.send_limit_exceeded",
"title": "Too Many Requests",
"status": 429,
"code": "transaction.send_limit_exceeded",
"detail": "transaction send limit exceeded",
"max": 10
}max is the workspace limit for registered signers plus unexpired invitations. Offline signers still count. Remove unused invitations or signers that are eligible for deletion, or contact support@vilna.io about the limit.
{
"type": "https://docs.vilna.io/apis/errors#signer.limit_exceeded",
"title": "Too Many Requests",
"status": 429,
"code": "signer.limit_exceeded",
"detail": "workspace signer limit exceeded",
"max": 10
}The result is not a broadcastable transaction; an ingredient cannot be sent through this action.
{
"type": "https://docs.vilna.io/apis/errors#transaction.send_unsupported",
"title": "Unprocessable Entity",
"status": 422,
"code": "transaction.send_unsupported",
"detail": "signed result is not a broadcastable transaction"
}VKS cannot submit transactions to this network because no node is configured for it. Contact support@vilna.io about network availability before retrying.
{
"type": "https://docs.vilna.io/apis/errors#transaction.rpc_not_configured",
"title": "Unprocessable Entity",
"status": 422,
"code": "transaction.rpc_not_configured",
"detail": "RPC is not configured for this network"
}Platform, Management and VKS use the HTTP problem envelope above, with service-specific codes and extensions. Blockchain RPC has its own protocol errors; see JSON-RPC error handling.
A rate-limited JSON-RPC call returns the following protocol error; gRPC returns HTTP 429 with an empty body.
{
"jsonrpc": "2.0",
"error": {
"code": -32005,
"message": "rate limit exceeded",
"data": {
"source": "vilna"
}
},
"id": null
}There are no X-RateLimit-* headers. Use the response-specific Retry-After rules above; do not treat every 429 as a temporary window. For retryable network and server failures, use backoff and preserve mutation intent.