openapi: 3.1.0
info:
  title: CentaPay S2S CARD API
  version: 5.6.4
  summary: Server-to-server card payments, payouts, and recurring operations across Central Asia.
  description: |
    All operations are POST requests to a single endpoint. The `action` field selects the operation.
    Requests are signed with an MD5 hash placed in the `hash` field - see the guide's Hash Formulas
    (Formulas 1-8). If a formula references an optional parameter you do not send, omit it from the
    hash calculation. There is no header-based authentication.

    Human guide: https://www.centapay.com/docs
    Markdown mirror (for AI-assisted integration): https://www.centapay.com/centapay-api-guide.md

    Sandbox and production endpoints, `CLIENT_KEY`, and `PASSWORD` are provided during onboarding.
  contact:
    name: CentaPay integration support
    email: info@centapay.com
    url: https://www.centapay.com/docs
servers:
  - url: https://{PAYMENT_URL}
    description: Payment platform host, provided during onboarding (separate sandbox and production hosts).
    variables:
      PAYMENT_URL:
        default: sandbox.example.centapay.com
        description: Host issued to your account at onboarding.

paths:
  /post:
    post:
      operationId: post
      summary: Execute an S2S CARD operation (selected by `action`)
      description: |
        Single endpoint for all operations. Content type is `application/x-www-form-urlencoded`.
        The synchronous response confirms acceptance or immediate failure; the authoritative
        transaction outcome for payment operations arrives via callback (see webhooks). Never
        treat the synchronous response as final settlement.
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              oneOf:
                - $ref: '#/components/schemas/SaleRequest'
                - $ref: '#/components/schemas/CaptureRequest'
                - $ref: '#/components/schemas/CreditvoidRequest'
                - $ref: '#/components/schemas/VoidRequest'
                - $ref: '#/components/schemas/Credit2CardRequest'
                - $ref: '#/components/schemas/GetTransStatusRequest'
                - $ref: '#/components/schemas/GetTransDetailsRequest'
                - $ref: '#/components/schemas/GetTransStatusByOrderRequest'
                - $ref: '#/components/schemas/RecurringSaleRequest'
                - $ref: '#/components/schemas/RetryRequest'
                - $ref: '#/components/schemas/CreateScheduleRequest'
                - $ref: '#/components/schemas/PauseScheduleRequest'
                - $ref: '#/components/schemas/RunScheduleRequest'
                - $ref: '#/components/schemas/DeleteScheduleRequest'
                - $ref: '#/components/schemas/ScheduleInfoRequest'
                - $ref: '#/components/schemas/DescheduleRequest'
              discriminator:
                propertyName: action
                mapping:
                  SALE: '#/components/schemas/SaleRequest'
                  CAPTURE: '#/components/schemas/CaptureRequest'
                  CREDITVOID: '#/components/schemas/CreditvoidRequest'
                  VOID: '#/components/schemas/VoidRequest'
                  CREDIT2CARD: '#/components/schemas/Credit2CardRequest'
                  GET_TRANS_STATUS: '#/components/schemas/GetTransStatusRequest'
                  GET_TRANS_DETAILS: '#/components/schemas/GetTransDetailsRequest'
                  GET_TRANS_STATUS_BY_ORDER: '#/components/schemas/GetTransStatusByOrderRequest'
                  RECURRING_SALE: '#/components/schemas/RecurringSaleRequest'
                  RETRY: '#/components/schemas/RetryRequest'
                  CREATE_SCHEDULE: '#/components/schemas/CreateScheduleRequest'
                  PAUSE_SCHEDULE: '#/components/schemas/PauseScheduleRequest'
                  RUN_SCHEDULE: '#/components/schemas/RunScheduleRequest'
                  DELETE_SCHEDULE: '#/components/schemas/DeleteScheduleRequest'
                  SCHEDULE_INFO: '#/components/schemas/ScheduleInfoRequest'
                  DESCHEDULE: '#/components/schemas/DescheduleRequest'
      responses:
        '200':
          description: |
            Synchronous response. Shape depends on `action` and outcome. Errors return the
            Error object (`result=ERROR`) - see the error code table in the guide.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/SaleSyncSuccess'
                  - $ref: '#/components/schemas/SaleSyncDeclined'
                  - $ref: '#/components/schemas/SaleSyncRedirect'
                  - $ref: '#/components/schemas/SaleSyncUndefined'
                  - $ref: '#/components/schemas/AcceptedResponse'
                  - $ref: '#/components/schemas/Credit2CardSyncResponse'
                  - $ref: '#/components/schemas/TransStatusResponse'
                  - $ref: '#/components/schemas/TransDetailsResponse'
                  - $ref: '#/components/schemas/ScheduleResponse'
                  - $ref: '#/components/schemas/ErrorResponse'

webhooks:
  saleCallback:
    post:
      summary: SALE / RECURRING_SALE result callback
      description: |
        Sent to your registered callback URL. Events: SUCCESS, FAIL (DECLINED), WAITING (3DS
        redirect pending), UNDEFINED. Respond HTTP 200 with body `OK`. Delivery retry: up to 5
        attempts, then blocked 5 minutes, then 15 minutes on repeated failure. Validate `hash`
        with Formula 2 (Formula 8-based flows still validate with Formula 2 using the stored
        card mask).
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              oneOf:
                - $ref: '#/components/schemas/SaleCallbackSuccess'
                - $ref: '#/components/schemas/SaleCallbackDeclined'
                - $ref: '#/components/schemas/SaleCallbackRedirect'
                - $ref: '#/components/schemas/SaleCallbackUndefined'
      responses:
        '200':
          description: Acknowledge with body `OK`.
  captureCallback:
    post:
      summary: CAPTURE result callback
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              oneOf:
                - $ref: '#/components/schemas/CaptureCallbackSuccess'
                - $ref: '#/components/schemas/CaptureCallbackDeclined'
                - $ref: '#/components/schemas/CaptureCallbackUndefined'
      responses:
        '200':
          description: Acknowledge with body `OK`.
  creditvoidCallback:
    post:
      summary: CREDITVOID (refund / reversal) result callback
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              oneOf:
                - $ref: '#/components/schemas/CreditvoidCallbackSuccess'
                - $ref: '#/components/schemas/CreditvoidCallbackDeclined'
                - $ref: '#/components/schemas/CreditvoidCallbackUndefined'
      responses:
        '200':
          description: Acknowledge with body `OK`.
  voidCallback:
    post:
      summary: VOID result callback
      description: |
        Hash validation for VOID callbacks uses a dedicated "Void signature" referenced by the
        upstream documentation; its formula is pending confirmation from the platform vendor.
        Until confirmed, do not hard-fail VOID callbacks on hash mismatch alone.
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              oneOf:
                - $ref: '#/components/schemas/VoidCallbackSuccess'
                - $ref: '#/components/schemas/VoidCallbackDeclined'
                - $ref: '#/components/schemas/VoidCallbackUndefined'
      responses:
        '200':
          description: Acknowledge with body `OK`.
  credit2cardCallback:
    post:
      summary: CREDIT2CARD (payout) result callback
      description: Validate `hash` with Formula 6.
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              oneOf:
                - $ref: '#/components/schemas/Credit2CardCallbackSuccess'
                - $ref: '#/components/schemas/Credit2CardCallbackDeclined'
                - $ref: '#/components/schemas/Credit2CardCallbackUndefined'
      responses:
        '200':
          description: Acknowledge with body `OK`.
  retryCallback:
    post:
      summary: RETRY result callback
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              oneOf:
                - $ref: '#/components/schemas/RetryCallbackSuccess'
                - $ref: '#/components/schemas/RetryCallbackDeclined'
      responses:
        '200':
          description: Acknowledge with body `OK`.
  chargebackNotification:
    post:
      summary: CHARGEBACK notification
      description: Sent whenever a chargeback is registered. Validate `hash` with Formula 2.
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/ChargebackNotification'
      responses:
        '200':
          description: Acknowledge with body `OK`.

components:
  schemas:
    # ---------- shared field groups ----------
    OrderFields:
      type: object
      properties:
        order_id:
          type: string
          maxLength: 255
          description: Your unique order ID.
        order_amount:
          type: string
          description: Integer for KZT/UZS. Float XX.XX for USD. 0 allowed with `auth=Y` (SALE).
        order_currency:
          type: string
          description: 3-letter code (KZT, UZS, USD).
        order_description:
          type: string
          maxLength: 1024
    PayerFields:
      type: object
      description: Cardholder identity fields (SALE).
      properties:
        payer_first_name: { type: string, maxLength: 32 }
        payer_last_name: { type: string, maxLength: 32 }
        payer_middle_name: { type: string, maxLength: 32 }
        payer_birth_date: { type: string, description: yyyy-MM-dd }
        payer_address: { type: string, maxLength: 255 }
        payer_address2: { type: string, maxLength: 255 }
        payer_house_number: { type: string, maxLength: 9 }
        payer_country: { type: string, description: 2-letter ISO 3166-1 }
        payer_state: { type: string, maxLength: 32 }
        payer_city: { type: string, maxLength: 40 }
        payer_district: { type: string, maxLength: 32 }
        payer_zip: { type: string, maxLength: 10 }
        payer_email: { type: string, maxLength: 256 }
        payer_phone: { type: string, maxLength: 32 }
        payer_phone_country_code: { type: string }
        payer_ip: { type: string, description: IPv4 and IPv6 supported. }
    ExtendedCallbackData:
      type: object
      description: Present only if "Add Extended Data to Callback" is enabled for the account.
      properties:
        connector_name: { type: string, description: Payment gateway name }
        rrn: { type: string, description: Retrieval Reference Number }
        approval_code: { type: string }
        gateway_id: { type: string }
        extra_gateway_id: { type: string }
        merchant_name: { type: string }
        mid_name: { type: string }
        issuer_country: { type: string }
        issuer_bank: { type: string }

    # ---------- requests ----------
    SaleRequest:
      type: object
      x-hash-formula: "Formula 1 (cards); Formula 8 (digital wallets)"
      required: [action, client_key, order_id, order_amount, order_currency, order_description,
                 payer_first_name, payer_last_name, payer_address, payer_country, payer_city,
                 payer_zip, payer_email, payer_phone, payer_ip, term_url_3ds, hash]
      allOf:
        - $ref: '#/components/schemas/OrderFields'
        - $ref: '#/components/schemas/PayerFields'
        - type: object
          properties:
            action: { const: SALE }
            client_key: { type: string, format: uuid, description: Account key. }
            channel_id: { type: string, maxLength: 16, description: Sub-account routing. }
            card_number:
              type: string
              description: Card PAN. Required unless `card_token` or a digital wallet is used.
            card_exp_month: { type: string, description: MM. Required with `card_number`. }
            card_exp_year: { type: string, description: YYYY. Required with `card_number`. }
            card_cvv2:
              type: string
              description: 3-4 digits. Required with `card_number` unless account configured otherwise.
            card_token:
              type: string
              maxLength: 64
              description: Stored card token; replaces card fields.
            digital_wallet:
              type: string
              enum: [googlepay, applepay]
              description: Pair with `payment_token`; omit card fields entirely.
            payment_token:
              type: string
              description: Wallet payment token from Apple Pay or Google Pay.
            term_url_3ds: { type: string, maxLength: 1024, description: 3DS return URL. }
            term_url_target:
              type: string
              description: Browsing context for 3DS return. `_blank`, `_self`, `_parent`, `_top` (default), or iframe name.
            auth: { type: string, enum: [Y, N], description: AUTH only (DMS). Default N. }
            req_token: { type: string, enum: [Y, N], description: Request a card token. Default N. }
            recurring_init: { type: string, enum: [Y, N], description: Initialise recurring sequence. Default N. }
            schedule_id: { type: string, description: Link to a recurring schedule. }
            parameters:
              type: object
              additionalProperties: { type: string }
              description: Acquirer-specific extras, sent as `parameters[key]=value`.
            custom_data:
              type: object
              additionalProperties: { type: string }
              description: Arbitrary data echoed in the callback, sent as `custom_data[key]=value`.
            hash: { type: string, description: MD5 hex request signature. }
    CaptureRequest:
      type: object
      x-hash-formula: "Formula 2"
      required: [action, client_key, trans_id, hash]
      properties:
        action: { const: CAPTURE }
        client_key: { type: string, format: uuid }
        trans_id: { type: string, format: uuid, description: trans_id of the AUTH to capture. }
        amount: { type: string, description: Partial capture amount; omit for full capture. }
        hash: { type: string }
    CreditvoidRequest:
      type: object
      x-hash-formula: "Formula 2"
      required: [action, client_key, trans_id, hash]
      properties:
        action: { const: CREDITVOID }
        client_key: { type: string, format: uuid }
        trans_id: { type: string, format: uuid, description: trans_id of the settled transaction. }
        amount: { type: string, description: Partial refund amount; omit for full refund/reversal. }
        hash: { type: string }
    VoidRequest:
      type: object
      x-hash-formula: "Formula 2"
      required: [action, client_key, trans_id, hash]
      properties:
        action: { const: VOID }
        client_key: { type: string, format: uuid }
        trans_id: { type: string, format: uuid, description: trans_id of a SALE, CAPTURE, or RECURRING_SALE. }
        hash: { type: string }
    Credit2CardRequest:
      type: object
      x-hash-formula: "Formula 5"
      required: [action, client_key, order_id, order_amount, order_currency, order_description,
                 card_number, hash]
      allOf:
        - $ref: '#/components/schemas/OrderFields'
        - type: object
          properties:
            action: { const: CREDIT2CARD }
            client_key: { type: string, format: uuid }
            channel_id: { type: string, maxLength: 16 }
            card_number: { type: string, description: Recipient card PAN. }
            payee_first_name: { type: string, maxLength: 32 }
            payee_last_name: { type: string, maxLength: 32 }
            payee_middle_name: { type: string, maxLength: 32 }
            payee_birth_date: { type: string, description: yyyy-MM-dd }
            payee_address: { type: string, maxLength: 255 }
            payee_address2: { type: string, maxLength: 255 }
            payee_country: { type: string, description: 2-letter }
            payee_state: { type: string, maxLength: 32 }
            payee_city: { type: string, maxLength: 32 }
            payee_zip: { type: string, maxLength: 10 }
            payee_email: { type: string, maxLength: 256 }
            payee_phone: { type: string, maxLength: 32 }
            payer_first_name: { type: string, maxLength: 32, description: Sender name. }
            payer_last_name: { type: string, maxLength: 32 }
            payer_middle_name: { type: string, maxLength: 32 }
            payer_birth_date: { type: string, description: yyyy-MM-dd }
            payer_address: { type: string, maxLength: 255 }
            payer_address2: { type: string, maxLength: 255 }
            payer_country: { type: string, description: 2-letter }
            payer_state: { type: string, maxLength: 32 }
            payer_city: { type: string, maxLength: 32 }
            payer_zip: { type: string, maxLength: 10 }
            payer_email: { type: string, maxLength: 256 }
            payer_phone: { type: string, maxLength: 32 }
            payer_ip: { type: string, description: IPv4 }
            parameters:
              type: object
              additionalProperties: { type: string }
            hash: { type: string }
    GetTransStatusRequest:
      type: object
      x-hash-formula: "Formula 2 (Formula 6 for CREDIT2CARD transactions)"
      required: [action, client_key, trans_id, hash]
      properties:
        action: { const: GET_TRANS_STATUS }
        client_key: { type: string, format: uuid }
        trans_id: { type: string, format: uuid }
        hash: { type: string }
    GetTransDetailsRequest:
      type: object
      x-hash-formula: "Formula 2 (Formula 6 for CREDIT2CARD transactions)"
      required: [action, client_key, trans_id, hash]
      properties:
        action: { const: GET_TRANS_DETAILS }
        client_key: { type: string, format: uuid }
        trans_id: { type: string, format: uuid }
        hash: { type: string }
    GetTransStatusByOrderRequest:
      type: object
      x-hash-formula: "Formula 7 (Formula 6 for CREDIT2CARD transactions)"
      required: [action, client_key, order_id, hash]
      properties:
        action: { const: GET_TRANS_STATUS_BY_ORDER }
        client_key: { type: string, format: uuid }
        order_id: { type: string, maxLength: 255 }
        hash: { type: string }
    RecurringSaleRequest:
      type: object
      x-hash-formula: "Formula 1 (stored card first6/last4 and original email)"
      required: [action, client_key, order_id, order_amount, order_description,
                 recurring_first_trans_id, recurring_token, hash]
      properties:
        action: { const: RECURRING_SALE }
        client_key: { type: string, format: uuid }
        order_id: { type: string, maxLength: 255, description: New unique order ID. }
        order_amount: { type: string }
        order_description: { type: string, maxLength: 1024 }
        recurring_first_trans_id: { type: string, format: uuid, description: trans_id of the initial transaction. }
        recurring_token: { type: string, format: uuid, description: Token from the initial transaction. }
        schedule_id: { type: string }
        auth: { type: string, enum: [Y, N], description: AUTH only. }
        custom_data:
          type: object
          additionalProperties: { type: string }
          description: Overrides the initial SALE custom_data.
        hash: { type: string }
    RetryRequest:
      type: object
      x-hash-formula: "Formula 1"
      required: [action, client_key, trans_id, hash]
      properties:
        action: { const: RETRY }
        client_key: { type: string, format: uuid }
        trans_id: { type: string, format: uuid, description: Declined recurring trans_id. }
        hash: { type: string }
    CreateScheduleRequest:
      type: object
      x-hash-formula: "Formula 3"
      required: [action, client_key, name, interval_unit, hash]
      properties:
        action: { const: CREATE_SCHEDULE }
        client_key: { type: string, format: uuid }
        name: { type: string, description: Schedule name. }
        interval_unit: { type: string, enum: [day, week, month], description: Billing interval unit. }
        interval_length: { type: string, description: Interval length. Default 1. }
        payments_count: { type: string, description: Number of payments; omit for unlimited. }
        delays: { type: string, description: Delay in interval units before the first payment. }
        day_of_month: { type: string, description: Day of month for monthly schedules. }
        hash: { type: string }
    PauseScheduleRequest:
      type: object
      x-hash-formula: "Formula 4"
      required: [action, client_key, schedule_id, hash]
      properties:
        action: { const: PAUSE_SCHEDULE }
        client_key: { type: string, format: uuid }
        schedule_id: { type: string, format: uuid }
        hash: { type: string }
    RunScheduleRequest:
      type: object
      x-hash-formula: "Formula 4"
      required: [action, client_key, schedule_id, hash]
      properties:
        action: { const: RUN_SCHEDULE }
        client_key: { type: string, format: uuid }
        schedule_id: { type: string, format: uuid }
        hash: { type: string }
    DeleteScheduleRequest:
      type: object
      x-hash-formula: "Formula 4"
      required: [action, client_key, schedule_id, hash]
      properties:
        action: { const: DELETE_SCHEDULE }
        client_key: { type: string, format: uuid }
        schedule_id: { type: string, format: uuid }
        hash: { type: string }
    ScheduleInfoRequest:
      type: object
      x-hash-formula: "Formula 4"
      required: [action, client_key, schedule_id, hash]
      properties:
        action: { const: SCHEDULE_INFO }
        client_key: { type: string, format: uuid }
        schedule_id: { type: string, format: uuid }
        hash: { type: string }
    DescheduleRequest:
      type: object
      x-hash-formula: "Formula 4"
      required: [action, client_key, recurring_token, schedule_id, hash]
      properties:
        action: { const: DESCHEDULE }
        client_key: { type: string, format: uuid }
        recurring_token: { type: string, format: uuid, description: Value obtained during the primary transaction. }
        schedule_id: { type: string, format: uuid }
        hash: { type: string }

    # ---------- synchronous responses ----------
    SaleSyncSuccess:
      type: object
      description: SALE synchronous success.
      properties:
        action: { const: SALE }
        result: { const: SUCCESS }
        status: { type: string, enum: [SETTLED, PENDING, PREPARE], description: PENDING only when `auth=Y`. }
        order_id: { type: string }
        trans_id: { type: string }
        trans_date: { type: string, description: YYYY-MM-DD hh:mm:ss }
        descriptor: { type: string, description: What the cardholder sees on their statement. }
        amount: { type: string }
        currency: { type: string }
        recurring_token: { type: string, description: If `recurring_init=Y` and account supports recurring. }
        schedule_id: { type: string }
        card_token: { type: string, description: If `req_token=Y`. }
        digital_wallet: { type: string, enum: [googlepay, applepay] }
        pan_type: { type: string, enum: [DPAN, FPAN], description: Wallet transactions only. }
    SaleSyncDeclined:
      type: object
      properties:
        action: { const: SALE }
        result: { const: DECLINED }
        status: { const: DECLINED }
        order_id: { type: string }
        trans_id: { type: string }
        trans_date: { type: string }
        descriptor: { type: string }
        amount: { type: string }
        currency: { type: string }
        decline_reason: { type: string }
        digital_wallet: { type: string }
        pan_type: { type: string }
    SaleSyncRedirect:
      type: object
      description: 3DS redirect required. Redirect the cardholder, then await the callback.
      properties:
        action: { const: SALE }
        result: { const: REDIRECT }
        status: { type: string, enum: ['3DS', REDIRECT] }
        order_id: { type: string }
        trans_id: { type: string }
        trans_date: { type: string }
        descriptor: { type: string }
        amount: { type: string }
        currency: { type: string }
        redirect_url: { type: string }
        redirect_params:
          description: Object of 3DS params (key-value). May be an empty array or absent. Varies by acquirer.
          oneOf: [{ type: object, additionalProperties: true }, { type: array }, { type: 'null' }]
        redirect_method: { type: string, enum: [POST, GET] }
        digital_wallet: { type: string }
        pan_type: { type: string }
    SaleSyncUndefined:
      type: object
      description: Outcome not yet known; the callback is authoritative.
      properties:
        action: { const: SALE }
        result: { const: UNDEFINED }
        status: { type: string, enum: [PENDING, PREPARE], description: PENDING only when `auth=Y`. }
        order_id: { type: string }
        trans_id: { type: string }
        trans_date: { type: string }
        descriptor: { type: string }
        amount: { type: string }
        currency: { type: string }
        digital_wallet: { type: string }
        pan_type: { type: string }
    AcceptedResponse:
      type: object
      description: Synchronous acknowledgement for CAPTURE, CREDITVOID, VOID, and RETRY.
      properties:
        result: { const: ACCEPTED }
        order_id: { type: string }
        trans_id: { type: string }
    Credit2CardSyncResponse:
      type: object
      description: |
        CREDIT2CARD synchronous response - reduced shape, does not include amount or currency.
        SUCCESS carries `descriptor`; DECLINED carries `decline_reason`; UNDEFINED (status
        PREPARE) carries `descriptor` if available.
      properties:
        action: { const: CREDIT2CARD }
        result: { type: string, enum: [SUCCESS, DECLINED, UNDEFINED] }
        status: { type: string, enum: [SETTLED, DECLINED, PREPARE] }
        order_id: { type: string }
        trans_id: { type: string }
        descriptor: { type: string }
        decline_reason: { type: string }
    TransStatusResponse:
      type: object
      description: GET_TRANS_STATUS / GET_TRANS_STATUS_BY_ORDER response. For orders processed
        with cascading, GET_TRANS_STATUS_BY_ORDER returns the latest attempt.
      properties:
        action: { type: string }
        result: { type: string }
        status:
          type: string
          enum: ['3DS', REDIRECT, PENDING, PREPARE, DECLINED, SETTLED, REVERSAL, REFUND, VOID, CHARGEBACK]
        order_id: { type: string }
        trans_id: { type: string }
        decline_reason: { type: string }
        recurring_token: { type: string }
        schedule_id: { type: string }
        digital_wallet: { type: string }
        arn: { type: string, description: Acquirer Reference Number, if configured. }
    TransDetailsResponse:
      type: object
      description: GET_TRANS_DETAILS response.
      properties:
        action: { const: GET_TRANS_DETAILS }
        result: { type: string }
        status: { type: string }
        order_id: { type: string }
        trans_id: { type: string }
        name: { type: string, description: Payer name. }
        mail: { type: string, description: Payer email. }
        ip: { type: string }
        amount: { type: string }
        currency: { type: string }
        card: { type: string, description: Masked PAN. }
        decline_reason: { type: string }
        recurring_token: { type: string }
        schedule_id: { type: string }
        pan_type: { type: string }
        digital_wallet: { type: string }
        arn: { type: string, description: If configured. }
        transactions:
          type: array
          description: Operation history for the payment.
          items:
            type: object
            properties:
              date: { type: string }
              type: { type: string }
              status: { type: string }
              amount: { type: string }
              description: { type: string }
    ScheduleResponse:
      type: object
      description: Response shape for schedule operations (CREATE/PAUSE/RUN/DELETE/INFO/DESCHEDULE).
      properties:
        result: { type: string, enum: [SUCCESS, ACCEPTED, ERROR] }
        schedule_id: { type: string }
    ErrorResponse:
      type: object
      description: Synchronous error. See the error code table in the guide for the full list.
      properties:
        result: { const: ERROR }
        error_code: { type: string, description: e.g. 100000 Previous payment not completed. }
        error_message: { type: string }

    # ---------- callbacks ----------
    SaleCallbackSuccess:
      allOf:
        - $ref: '#/components/schemas/ExtendedCallbackData'
        - type: object
          properties:
            action: { type: string, enum: [SALE, RECURRING_SALE] }
            result: { const: SUCCESS }
            status: { type: string, enum: [PENDING, PREPARE, SETTLED] }
            order_id: { type: string }
            trans_id: { type: string }
            trans_date: { type: string }
            descriptor: { type: string }
            amount: { type: string }
            currency: { type: string }
            card: { type: string, description: 'Masked PAN, e.g. 411111****1111. For wallets: decrypted token PAN.' }
            card_expiration_date: { type: string }
            recurring_token: { type: string, description: If `recurring_init=Y` was sent. }
            schedule_id: { type: string, description: If a schedule was used. }
            card_token: { type: string, description: If `req_token=Y` was sent. }
            exchange_rate: { type: string, description: FX rate if currency conversion applied. }
            exchange_rate_base: { type: string, description: Base rate if double conversion. }
            exchange_currency: { type: string, description: Original currency. }
            exchange_amount: { type: string, description: Original amount. }
            custom_data: { type: object, additionalProperties: true, description: Echoed from request. }
            digital_wallet: { type: string, enum: [googlepay, applepay] }
            pan_type: { type: string, enum: [DPAN, FPAN] }
            hash: { type: string, description: Validate with Formula 2. }
    SaleCallbackDeclined:
      type: object
      description: Does NOT include card, card_expiration_date, descriptor, amount, currency,
        card_token, or recurring_token.
      properties:
        action: { type: string, enum: [SALE, RECURRING_SALE] }
        result: { const: DECLINED }
        status: { const: DECLINED }
        order_id: { type: string }
        trans_id: { type: string }
        trans_date: { type: string }
        decline_reason: { type: string }
        custom_data: { type: object, additionalProperties: true }
        digital_wallet: { type: string }
        pan_type: { type: string }
        hash: { type: string }
    SaleCallbackRedirect:
      type: object
      description: WAITING event - 3DS verification pending. Does NOT include card or
        card_expiration_date.
      properties:
        action: { const: SALE }
        result: { const: REDIRECT }
        status: { type: string, enum: ['3DS', REDIRECT] }
        order_id: { type: string }
        trans_id: { type: string }
        trans_date: { type: string }
        descriptor: { type: string }
        amount: { type: string }
        currency: { type: string }
        redirect_url: { type: string }
        redirect_params: { oneOf: [{ type: object, additionalProperties: true }, { type: array }, { type: 'null' }] }
        redirect_method: { type: string, enum: [POST, GET] }
        custom_data: { type: object, additionalProperties: true }
        digital_wallet: { type: string }
        pan_type: { type: string }
        hash: { type: string }
    SaleCallbackUndefined:
      type: object
      description: Does NOT include card or card_expiration_date.
      properties:
        action: { type: string, enum: [SALE, RECURRING_SALE] }
        result: { const: UNDEFINED }
        status: { type: string, enum: [PENDING, PREPARE, SETTLED] }
        order_id: { type: string }
        trans_id: { type: string }
        trans_date: { type: string }
        descriptor: { type: string }
        amount: { type: string }
        currency: { type: string }
        custom_data: { type: object, additionalProperties: true }
        digital_wallet: { type: string }
        pan_type: { type: string }
        hash: { type: string }
    CaptureCallbackSuccess:
      allOf:
        - $ref: '#/components/schemas/ExtendedCallbackData'
        - type: object
          properties:
            action: { const: CAPTURE }
            result: { const: SUCCESS }
            status: { const: SETTLED }
            order_id: { type: string }
            trans_id: { type: string }
            amount: { type: string }
            trans_date: { type: string }
            descriptor: { type: string }
            currency: { type: string }
            hash: { type: string, description: Validate with Formula 2. }
    CaptureCallbackDeclined:
      type: object
      properties:
        action: { const: CAPTURE }
        result: { const: DECLINED }
        status: { const: PENDING }
        order_id: { type: string }
        trans_id: { type: string }
        decline_reason: { type: string }
        hash: { type: string }
    CaptureCallbackUndefined:
      type: object
      properties:
        action: { const: CAPTURE }
        result: { const: UNDEFINED }
        status: { const: PENDING }
        order_id: { type: string }
        trans_id: { type: string }
        trans_date: { type: string }
        descriptor: { type: string }
        amount: { type: string }
        currency: { type: string }
        hash: { type: string }
    CreditvoidCallbackSuccess:
      allOf:
        - $ref: '#/components/schemas/ExtendedCallbackData'
        - type: object
          properties:
            action: { const: CREDITVOID }
            result: { const: SUCCESS }
            status:
              type: string
              enum: [REFUND, REVERSAL, SETTLED]
              description: REFUND/REVERSAL for full; SETTLED remains for partial refund.
            order_id: { type: string }
            trans_id: { type: string }
            creditvoid_date: { type: string }
            amount: { type: string }
            hash: { type: string, description: Validate with Formula 2. }
    CreditvoidCallbackDeclined:
      type: object
      properties:
        action: { const: CREDITVOID }
        result: { const: DECLINED }
        order_id: { type: string }
        trans_id: { type: string }
        decline_reason: { type: string }
        hash: { type: string }
    CreditvoidCallbackUndefined:
      type: object
      properties:
        action: { const: CREDITVOID }
        result: { const: UNDEFINED }
        status: { const: SETTLED }
        order_id: { type: string }
        trans_id: { type: string }
        creditvoid_date: { type: string }
        amount: { type: string }
        hash: { type: string }
    VoidCallbackSuccess:
      allOf:
        - $ref: '#/components/schemas/ExtendedCallbackData'
        - type: object
          description: Does not include amount or currency.
          properties:
            action: { const: VOID }
            result: { const: SUCCESS }
            status: { const: VOID }
            order_id: { type: string }
            trans_id: { type: string }
            trans_date: { type: string }
            hash: { type: string, description: Void signature - definition pending vendor confirmation. }
    VoidCallbackDeclined:
      type: object
      properties:
        action: { const: VOID }
        result: { const: DECLINED }
        status: { const: SETTLED }
        order_id: { type: string }
        trans_id: { type: string }
        trans_date: { type: string }
        decline_reason: { type: string }
        hash: { type: string }
    VoidCallbackUndefined:
      type: object
      properties:
        action: { const: VOID }
        result: { const: UNDEFINED }
        status: { type: string, enum: [PENDING, SETTLED] }
        order_id: { type: string }
        trans_id: { type: string }
        trans_date: { type: string }
        hash: { type: string }
    Credit2CardCallbackSuccess:
      allOf:
        - $ref: '#/components/schemas/ExtendedCallbackData'
        - type: object
          properties:
            action: { const: CREDIT2CARD }
            result: { const: SUCCESS }
            status: { const: SETTLED }
            order_id: { type: string }
            trans_id: { type: string }
            trans_date: { type: string }
            hash: { type: string, description: Validate with Formula 6. }
    Credit2CardCallbackDeclined:
      type: object
      properties:
        action: { const: CREDIT2CARD }
        result: { const: DECLINED }
        status: { const: DECLINED }
        order_id: { type: string }
        trans_id: { type: string }
        trans_date: { type: string }
        decline_reason: { type: string }
        hash: { type: string }
    Credit2CardCallbackUndefined:
      type: object
      properties:
        action: { const: CREDIT2CARD }
        result: { const: UNDEFINED }
        status: { const: PREPARE }
        order_id: { type: string }
        trans_id: { type: string }
        trans_date: { type: string }
        hash: { type: string }
    RetryCallbackSuccess:
      type: object
      properties:
        action: { const: RETRY }
        result: { const: SUCCESS }
        status: { const: SETTLED }
        order_id: { type: string }
        trans_id: { type: string }
        amount: { type: string }
        currency: { type: string }
        hash: { type: string, description: Validate with Formula 2. }
    RetryCallbackDeclined:
      type: object
      properties:
        action: { const: RETRY }
        result: { const: DECLINED }
        status: { const: DECLINED }
        order_id: { type: string }
        trans_id: { type: string }
        amount: { type: string }
        currency: { type: string }
        decline_reason: { type: string }
        hash: { type: string }
    ChargebackNotification:
      allOf:
        - $ref: '#/components/schemas/ExtendedCallbackData'
        - type: object
          properties:
            action: { const: CHARGEBACK }
            result: { type: string }
            status: { const: CHARGEBACK }
            order_id: { type: string }
            trans_id: { type: string }
            amount: { type: string }
            chargeback_date: { type: string }
            bank_date: { type: string }
            reason_code: { type: string }
            hash: { type: string, description: Validate with Formula 2. }
