{
  "schemaVersion": "1.0.0",
  "contractVersion": "2026-08-25.9",
  "dictionaries": {
    "businessErrors": {
      "id": "business-errors",
      "title": "Error catalog",
      "formatVersion": 2,
      "description": "This is not an exhaustive catalog. Owner-confirmed HTTP mappings are identified per item; other conditions retain their documented or observed scope.",
      "exhaustive": false,
      "globalCascadeRule": "For any create error, 499+, timeout, broken connection, or missing response, check order status before initiating another attempt/cascade.",
      "errorResponseContract": {
        "scope": "PayStar business errors; excludes HTTP/framework errors such as 415",
        "json_body_fields": [
          {
            "name": "label",
            "type": "string",
            "required_when_json_body_present": true,
            "description": "Machine-readable error category. Observed values include VALIDATION_ERROR, REQUEST_VALIDATION_ERROR, TEMPORARY_ERROR, NOT_FOUND and INTERNAL_SERVER_ERROR."
          },
          {
            "name": "message",
            "type": "string",
            "required_when_json_body_present": true,
            "description": "Human-readable or framework validation message; exact text is not stable enough for client branching."
          },
          {
            "name": "statusDescrption",
            "type": "string|null",
            "required_when_json_body_present": false,
            "description": "Owner-approved current wire spelling, intentionally preserved including the typo."
          },
          {
            "name": "externalTransactionId",
            "type": "string|null",
            "required_when_json_body_present": false
          },
          {
            "name": "code",
            "type": "string|null",
            "required_when_json_body_present": false,
            "description": "Application error code when supplied. Do not branch on undocumented values."
          }
        ],
        "body_exceptions": [
          "401 responses may have an empty body.",
          "Framework-level 415 responses use application/problem+json and are not PayStar business errors."
        ],
        "client_guidance": [
          "Branch primarily on HTTP status and documented stable application codes, not exact message text.",
          "For create-order 5xx, timeout or missing response, query status using the original externalTransactionId before retrying."
        ]
      },
      "groups": {
        "commonCreate": [
          "created_failed",
          "channel_not_found",
          "limit_reached",
          "duplicate_merchant_id",
          "required_field_missing"
        ],
        "json": [
          "created_failed",
          "channel_not_found",
          "insufficient_balance",
          "limit_reached",
          "duplicate_merchant_id",
          "required_field_missing",
          "deposit_unknown_currency",
          "validation_error",
          "temporary_or_no_route"
        ],
        "http": [
          "unauthorized",
          "forbidden",
          "payment_not_found",
          "unsupported_media_type",
          "internal_or_configuration_error",
          "transport_failure"
        ],
        "payoutOnlyCreate": [
          "insufficient_balance"
        ]
      },
      "items": [
        {
          "id": "created_failed",
          "title": "Order created, processing failed",
          "group": "json",
          "appliesTo": [
            "P2P deposit H2H/H2C",
            "ECOM H2H deposit",
            "Hosted H2C deposit",
            "Tokenized deposit",
            "Payout"
          ],
          "orderCreated": true,
          "description": "The request produced an order, but processing failed. Keep the PayStar externalId and your original merchant order ID. This is not a rejection without an order.",
          "handling": "HTTP 200 means the order was created, not that the payment succeeded. This body uses orderStatus, not status, and does not include payment details or a form URL. Inspect orderStatus and retain both order identifiers.",
          "http": {
            "status": 200,
            "basis": "Owner-confirmed HTTP mapping (CREATE-HTTP-001, 15 September 2026) for this response example; not new per-flow live verification.",
            "scope": "Deposit creation and payout",
            "decision": "CREATE-HTTP-001",
            "approvedAt": "2026-09-15"
          },
          "payload": {
            "externalId": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
            "orderStatus": "Failed"
          }
        },
        {
          "id": "channel_not_found",
          "title": "No matching channel or route",
          "group": "json",
          "appliesTo": [
            "P2P deposit H2H/H2C",
            "ECOM H2H deposit",
            "Hosted H2C deposit",
            "Tokenized deposit",
            "Payout"
          ],
          "orderCreated": false,
          "description": "The currency, amount, or other request parameters do not match available routing conditions for this pipeline. No order is created.",
          "handling": "Check the request parameters and the pipeline routing conditions with your manager.",
          "http": {
            "status": 423,
            "basis": "Owner-confirmed HTTP mapping (CREATE-HTTP-001, 15 September 2026) for this response example; not new per-flow live verification.",
            "scope": "Deposit creation and payout",
            "decision": "CREATE-HTTP-001",
            "approvedAt": "2026-09-15"
          },
          "payload": {
            "label": "TEMPORARY_ERROR",
            "message": "TEMPORARY_ERROR",
            "statusDescrption": "0000-2",
            "externalTransactionId": null,
            "code": "1.2.4.3"
          },
          "provenance": {
            "decision": "CREATE-ERRORS-001",
            "approvedAt": "2026-09-10",
            "flow": "Deposit H2H",
            "currency": "EUR",
            "observedAtUtc": "2026-09-08T10:16:16.62731Z",
            "evidence": "20260908T101615299Z-currency-three-cases.json#/results/4",
            "httpDecision": "CREATE-HTTP-001",
            "httpApprovedAt": "2026-09-15"
          }
        },
        {
          "id": "insufficient_balance",
          "title": "Insufficient balance",
          "group": "json",
          "appliesTo": [
            "Payout"
          ],
          "orderCreated": false,
          "description": "Insufficient balance to create the payout. No order is created.",
          "handling": "Confirm the balance involved with your manager; the payload alone does not identify an account or wallet.",
          "http": {
            "status": 422,
            "basis": "Owner-confirmed HTTP mapping (CREATE-HTTP-001, 15 September 2026) for this response example; not new per-flow live verification.",
            "scope": "Payout only",
            "decision": "CREATE-HTTP-001",
            "approvedAt": "2026-09-15"
          },
          "payload": {
            "label": "TEMPORARY_ERROR",
            "message": "TEMPORARY_ERROR",
            "statusDescrption": "1-4010",
            "externalTransactionId": null,
            "code": "1.1.4.3"
          }
        },
        {
          "id": "limit_reached",
          "title": "Configured limit reached",
          "group": "json",
          "appliesTo": [
            "P2P deposit H2H/H2C",
            "ECOM H2H deposit",
            "Hosted H2C deposit",
            "Tokenized deposit",
            "Payout"
          ],
          "orderCreated": false,
          "description": "A configured limit was reached. No order is created.",
          "handling": "The limit ID is illustrative. This example has no code field; do not map the error by a particular UUID or exact message text.",
          "http": {
            "status": 400,
            "basis": "Owner-confirmed HTTP mapping (CREATE-HTTP-001, 15 September 2026) for this response example; not new per-flow live verification.",
            "scope": "Deposit creation and payout",
            "decision": "CREATE-HTTP-001",
            "approvedAt": "2026-09-15"
          },
          "payload": {
            "label": "LIMITS_ERROR",
            "message": "Limit id: aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa was reached",
            "statusDescrption": "0001-0",
            "externalTransactionId": null
          }
        },
        {
          "id": "duplicate_merchant_id",
          "title": "Duplicate merchant order ID",
          "group": "json",
          "appliesTo": [
            "P2P deposit H2H/H2C",
            "ECOM H2H deposit",
            "Hosted H2C deposit",
            "Tokenized deposit",
            "Payout"
          ],
          "orderCreated": false,
          "description": "An order with this merchant ID already exists. No new order is created by this rejected attempt.",
          "handling": "Query the existing order using the original externalTransactionId from your request, even when externalTransactionId is null in this error. Do not replace the ID for a blind retry.",
          "http": {
            "status": 400,
            "basis": "Owner-confirmed HTTP mapping (CREATE-HTTP-001, 15 September 2026) for this response example; not new per-flow live verification.",
            "scope": "Deposit creation and payout",
            "decision": "CREATE-HTTP-001",
            "approvedAt": "2026-09-15"
          },
          "payload": {
            "label": "VALIDATION_ERROR",
            "message": "Order with this external_transaction_id already exist",
            "statusDescrption": "1-4007",
            "externalTransactionId": null,
            "code": "1.1.5.1"
          },
          "legacyIds": [
            "duplicate_external_transaction_id"
          ],
          "legacyWireDifferences": {
            "label": "VALIDATION_ERROR.",
            "omittedFields": [
              "code",
              "externalTransactionId"
            ],
            "note": "Historical reduced example, not a second current error or interchangeable label guarantee."
          }
        },
        {
          "id": "required_field_missing",
          "title": "Required parameter missing",
          "group": "json",
          "appliesTo": [
            "P2P deposit H2H/H2C",
            "ECOM H2H deposit",
            "Hosted H2C deposit",
            "Tokenized deposit",
            "Payout"
          ],
          "orderCreated": false,
          "description": "A field required by the configured terminal is missing. No order is created.",
          "handling": "BankAccount is an example of a configured requirement, not a mandatory field for every flow. Use the required-field list supplied for your terminal.",
          "http": {
            "status": 400,
            "basis": "Owner-confirmed HTTP mapping (CREATE-HTTP-001, 15 September 2026) for this response example; not new per-flow live verification.",
            "scope": "Deposit creation and payout",
            "decision": "CREATE-HTTP-001",
            "approvedAt": "2026-09-15"
          },
          "payload": {
            "label": "VALIDATION_ERROR",
            "message": "additionalField BankAccount not found in request data. Description: Beneficiary’s bank account number, e.g. 1234567890",
            "statusDescrption": "0000-0",
            "externalTransactionId": null,
            "code": "1.2.4.8"
          }
        },
        {
          "id": "deposit_unknown_currency",
          "title": "Unknown currency",
          "group": "json",
          "appliesTo": [
            "deposit_h2h",
            "deposit_h2c"
          ],
          "description": "CUR-002 (9 Sep 2026): unrecognized currency values, including RU and ZZZ, return the unknown-currency response. This is distinct from routing failure.",
          "handling": "Use the exact currency key enabled for your integration; do not impose an alpha-3 format check. Unknown currency is detected during internal dictionary lookup, before route lookup. Do not branch on exact message text or automatically retry an unchanged request. The refined message is owner-confirmed, not yet live-verified.",
          "http": {
            "status": 423,
            "basis": "Owner-confirmed CUR-002; refined message not yet live-verified.",
            "scope": "Deposit H2H/H2C only; does not extend to Balance or payout"
          },
          "payload": {
            "label": "TEMPORARY_ERROR",
            "message": "Currency value \"RU\" is unknown",
            "statusDescrption": "2-00100-2",
            "externalTransactionId": null,
            "code": "1.2.4.9"
          },
          "provenance": {
            "decision": "CUR-002",
            "approvedAt": "2026-09-09",
            "discussedValues": [
              "RU",
              "ZZZ"
            ],
            "messageTemplate": "Currency value \"{currencyKey}\" is unknown",
            "excluded": [
              "Balance",
              "payout",
              "missing/null/empty currency",
              "lowercase policy",
              "retry policy",
              "request schema relaxation (separately approved by CUR-CRYPTO-001)"
            ]
          }
        },
        {
          "id": "validation_error",
          "title": "General request validation",
          "group": "json",
          "appliesTo": [
            "deposit_create",
            "payout_create"
          ],
          "description": "Malformed request, missing required field, or invalid field value.",
          "handling": "Fix the request contract. Confirm flow-specific additional fields with the Account Manager.",
          "http": {
            "status": 400,
            "basis": "Legacy documented examples; distinguish these from configured-field validation.",
            "scope": "Create requests"
          },
          "payload": {
            "label": "VALIDATION_ERROR.",
            "message": "External_transaction_id is required property",
            "statusDescrption": "0-0000"
          },
          "messageVariants": [
            "Amount is required property",
            "Currency is required property",
            "currency has invalide value"
          ],
          "note": "Historical label VALIDATION_ERROR. and statusDescrption 0-0000 are retained verbatim. Message variants replace only message; do not match exact text or restore alpha-3 validation from the historical currency message."
        },
        {
          "id": "temporary_or_no_route",
          "title": "Payment temporarily unavailable — legacy variant",
          "group": "json",
          "appliesTo": [
            "deposit_create",
            "payout_create"
          ],
          "description": "Distinct legacy payload with statusDescrption 0000-1, not the owner-confirmed 0000-2 routing response.",
          "handling": "Contact the Account Manager and check route/amount/currency/additional-field constraints.",
          "http": {
            "status": 423,
            "basis": "Legacy/general reference, not a universal routing mapping.",
            "scope": "Legacy documented create response"
          },
          "payload": {
            "label": "TEMPORARY_ERROR",
            "statusDescrption": "0000-1",
            "message": "There is currently no possibility to make a payment, please try again later"
          }
        },
        {
          "id": "unauthorized",
          "title": "Authentication",
          "group": "http",
          "appliesTo": [
            "all"
          ],
          "http": {
            "status": 401,
            "basis": "Documented outcome.",
            "scope": "All operations"
          },
          "description": "Authorization header/key is missing or invalid.",
          "handling": "Verify the Bearer token and that the correct deposit/payout key is used.",
          "body": "May be empty; no JSON example is supplied."
        },
        {
          "id": "forbidden",
          "title": "Forbidden",
          "group": "http",
          "appliesTo": [
            "all"
          ],
          "http": {
            "status": 403,
            "basis": "Documented outcome.",
            "scope": "All operations"
          },
          "description": "Access denied. The HTTP status or an empty body does not identify a single cause.",
          "handling": "Ask your manager to check the key, flow capability, pipeline and IP allowlist.",
          "body": "May be empty; no JSON example is supplied.",
          "possibleCauses": [
            {
              "id": "forbidden_pipeline",
              "description": "The key/pipeline is not activated or lacks permission.",
              "handling": "Contact the Account Manager."
            },
            {
              "id": "invalid_pipeline_type",
              "description": "The key is active but belongs to another flow type, e.g. payout key used for deposit.",
              "handling": "Use the dedicated key for the requested operation."
            },
            {
              "id": "forbidden_ip",
              "description": "Source IP is not whitelisted.",
              "handling": "Ask the Account Manager to whitelist the IP; documentation says propagation can take up to one hour."
            }
          ],
          "note": "The legacy IP propagation estimate is not a newly verified SLA."
        },
        {
          "id": "payment_not_found",
          "title": "Payment not found",
          "group": "http",
          "appliesTo": [
            "status_endpoints"
          ],
          "http": {
            "status": 404,
            "basis": "Documented status-lookup outcome.",
            "scope": "Status lookups, not create rejection"
          },
          "description": "No order found by this lookup.",
          "handling": "Verify whether a PayStar externalId or merchant externalTransactionId is expected by this endpoint. Continue the agreed uncertainty-resolution process.",
          "body": "Use the response model documented for the status method; this catalog does not invent a body."
        },
        {
          "id": "unsupported_media_type",
          "title": "Media type",
          "group": "http",
          "appliesTo": [
            "JSON requests"
          ],
          "http": {
            "status": 415,
            "basis": "Documented framework outcome.",
            "scope": "Request media type"
          },
          "description": "Unsupported request content type.",
          "handling": "Send application/json. ProblemDetails is a separate response model.",
          "body": "application/problem+json; not the PayStar BusinessError envelope."
        },
        {
          "id": "internal_or_configuration_error",
          "title": "Server or configuration error",
          "group": "http",
          "appliesTo": [
            "create_and_some_status_endpoints"
          ],
          "http": {
            "status": 500,
            "basis": "Documented server-error outcome; other 5xx may also occur.",
            "scope": "Affected operations"
          },
          "description": "A server or configuration failure does not establish whether an order was created.",
          "handling": "Do not assume the order was not created. Query status before any cascade/retry.",
          "body": "No universal JSON body is established."
        },
        {
          "id": "transport_failure",
          "title": "No HTTP response",
          "group": "http",
          "appliesTo": [
            "all"
          ],
          "http": {
            "status": null,
            "basis": "No HTTP response is a transport failure, not an API status code.",
            "scope": "Timeout, missing response or broken connection"
          },
          "description": "The create result may be unresolved.",
          "handling": "Retain the original merchant ID. Query status by that ID before another create attempt or cascade; do not replace the ID for a blind retry.",
          "body": "No HTTP response body."
        }
      ]
    }
  },
  "reviewRevision": "2026-09-15.5"
}
