Orsun Pay Webhooks API

Signed merchant event deliveries

GitHub OpenAPI

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/orsunpay-com:orsunpay-com-webhooks-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

orsunpay-com-webhooks-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  contact:
    name: OrsunPay
  description: Server-to-server merchant payments. Money is always a decimal string in major units.
  title: OrsunPay Merchant Webhooks API
  version: '1.0'
servers: []
tags:
- description: Signed merchant event deliveries
  name: Webhooks
paths: {}
webhooks:
  refundFailed:
    post:
      description: Terminal refund event sent to the original sale callbackUrl, falling back to the merchant default webhook URL. Verify HMAC-SHA256 over the exact raw body before parsing, using the merchant webhook secret (ADR-010). Reject signature timestamps beyond 300 seconds; compare in constant time. Deliveries are at least once and can arrive out of order. Deduplicate by the signed body id. Secret rotation takes effect immediately (no dual signing); failed deliveries retry for approximately 31 hours. API keys are not sent with webhooks. The refund and transaction snapshot stays byte-identical across retries/redrives; retain the maximum cumulative refundedAmount using decimal arithmetic.
      operationId: receiveRefundFailed
      parameters:
      - description: t=<Unix seconds>,v1=<hex HMAC-SHA256(timestamp + "." + exact raw body)>; never log this header
        in: header
        name: OrsunPay-Signature
        required: true
        schema:
          pattern: ^t=[0-9]+,v1=[a-f0-9]{64}$
          type: string
      - description: Convenience copy of body id (evt_…); deduplicate only after verifying the signed body
        in: header
        name: OrsunPay-Event-Id
        required: true
        schema:
          pattern: ^evt_[0-7][0-9a-hjkmnp-tv-z]{25}$
          type: string
      - description: Convenience copy of body type
        in: header
        name: OrsunPay-Event-Type
        required: true
        schema:
          example: refund.failed
          type: string
      requestBody:
        content:
          application/json:
            example:
              api_version: '2026-10-31'
              created: '2026-10-10T10:05:00.000Z'
              created_at: '2026-10-10T10:05:00.000Z'
              data:
                refund:
                  amount: '5.00'
                  currency: EUR
                  errorCode: REFUND_DECLINED
                  id: rf_example
                  provider: stripe
                  providerRefundId: re_example
                  reason: requested_by_customer
                  status: FAILED
                  transactionId: tr_example
                transaction:
                  amount: '12.30'
                  id: tr_example
                  livemode: true
                  orderId: order_example_001
                  refundState: none
                  refundedAmount: '0.00'
              id: evt_0j7s2pft4v8b9t8nj2cra1eg01
              livemode: true
              type: refund.failed
            schema:
              $ref: '#/components/schemas/RefundWebhookEvent'
        required: true
      responses:
        2XX:
          description: Any 2xx acknowledges delivery. Response body is ignored but must be empty or at most 64 KiB (MERCHANT_WEBHOOK_MAX_RESPONSE_BYTES); a larger body fails the delivery attempt. Prefer HTTP 204 No Content.
      security: []
      summary: Refund failed event
      tags:
      - Webhooks
  refundSucceeded:
    post:
      description: Terminal refund event sent to the original sale callbackUrl, falling back to the merchant default webhook URL. Verify HMAC-SHA256 over the exact raw body before parsing, using the merchant webhook secret (ADR-010). Reject signature timestamps beyond 300 seconds; compare in constant time. Deliveries are at least once and can arrive out of order. Deduplicate by the signed body id. Secret rotation takes effect immediately (no dual signing); failed deliveries retry for approximately 31 hours. API keys are not sent with webhooks. The refund and transaction snapshot stays byte-identical across retries/redrives; retain the maximum cumulative refundedAmount using decimal arithmetic.
      operationId: receiveRefundSucceeded
      parameters:
      - description: t=<Unix seconds>,v1=<hex HMAC-SHA256(timestamp + "." + exact raw body)>; never log this header
        in: header
        name: OrsunPay-Signature
        required: true
        schema:
          pattern: ^t=[0-9]+,v1=[a-f0-9]{64}$
          type: string
      - description: Convenience copy of body id (evt_…); deduplicate only after verifying the signed body
        in: header
        name: OrsunPay-Event-Id
        required: true
        schema:
          pattern: ^evt_[0-7][0-9a-hjkmnp-tv-z]{25}$
          type: string
      - description: Convenience copy of body type
        in: header
        name: OrsunPay-Event-Type
        required: true
        schema:
          example: refund.succeeded
          type: string
      requestBody:
        content:
          application/json:
            example:
              api_version: '2026-10-31'
              created: '2026-10-10T10:05:00.000Z'
              created_at: '2026-10-10T10:05:00.000Z'
              data:
                refund:
                  amount: '5.00'
                  currency: EUR
                  errorCode: null
                  id: rf_example
                  provider: stripe
                  providerRefundId: re_example
                  reason: requested_by_customer
                  status: SUCCEEDED
                  transactionId: tr_example
                transaction:
                  amount: '12.30'
                  id: tr_example
                  livemode: true
                  orderId: order_example_001
                  refundState: partial
                  refundedAmount: '5.00'
              id: evt_0j7s2pft4v8b9t8nj2cra1eg01
              livemode: true
              type: refund.succeeded
            schema:
              $ref: '#/components/schemas/RefundWebhookEvent'
        required: true
      responses:
        2XX:
          description: Any 2xx acknowledges delivery. Response body is ignored but must be empty or at most 64 KiB (MERCHANT_WEBHOOK_MAX_RESPONSE_BYTES); a larger body fails the delivery attempt. Prefer HTTP 204 No Content.
      security: []
      summary: Refund succeeded event
      tags:
      - Webhooks
  transactionUpdated:
    post:
      description: OrsunPay sends this POST to the transaction callbackUrl after a status update. Verify HMAC-SHA256 over the exact raw body before parsing, using the merchant webhook secret (ADR-010). Reject signature timestamps beyond 300 seconds; compare in constant time. Deliveries are at least once and can arrive out of order. Deduplicate by the signed body id. Secret rotation takes effect immediately (no dual signing); failed deliveries retry for approximately 31 hours. API keys are not sent with webhooks.
      operationId: receiveTransactionUpdated
      parameters:
      - description: t=<Unix seconds>,v1=<hex HMAC-SHA256(timestamp + "." + exact raw body)>; never log this header
        in: header
        name: OrsunPay-Signature
        required: true
        schema:
          pattern: ^t=[0-9]+,v1=[a-f0-9]{64}$
          type: string
      - description: Convenience copy of body id (evt_…); deduplicate only after verifying the signed body
        in: header
        name: OrsunPay-Event-Id
        required: true
        schema:
          pattern: ^evt_[0-7][0-9a-hjkmnp-tv-z]{25}$
          type: string
      - description: Convenience copy of body type
        in: header
        name: OrsunPay-Event-Type
        required: true
        schema:
          example: transaction.updated
          type: string
      requestBody:
        content:
          application/json:
            example:
              api_version: '2026-10-31'
              created_at: '2026-10-10T10:00:00.000Z'
              data:
                paymentData: {}
                transaction:
                  action: SALE
                  amount: '12.30'
                  createdAt: '2026-10-10T09:59:00.000Z'
                  currency: EUR
                  id: tr_example
                  livemode: true
                  orderId: order_example_001
                  status: SUCCESS
              id: evt_0j7s2pft4v8b9t8nj2cra1eg00
              livemode: true
              type: transaction.updated
            schema:
              $ref: '#/components/schemas/WebhookEvent'
        required: true
      responses:
        2XX:
          description: Any 2xx acknowledges delivery. Response body is ignored but must be empty or at most 64 KiB (MERCHANT_WEBHOOK_MAX_RESPONSE_BYTES); a larger body fails the delivery attempt. Prefer HTTP 204 No Content.
      security: []
      summary: Transaction status event
      tags:
      - Webhooks
components:
  schemas:
    RefundWebhookEvent:
      description: Immutable refund terminal event. Amounts use currency precision; retain the maximum refundedAmount when events arrive out of order.
      properties:
        api_version:
          example: '2026-10-31'
          pattern: ^[0-9]{4}-[0-9]{2}-[0-9]{2}$
          type: string
        created:
          description: Alias of created_at, preserved across retries.
          format: date-time
          type: string
        created_at:
          format: date-time
          type: string
        data:
          properties:
            refund:
              properties:
                amount:
                  pattern: ^(0|[1-9]\d{0,19})(\.\d{1,18})?$
                  type: string
                currency:
                  type: string
                errorCode:
                  oneOf:
                  - type: string
                  - type: 'null'
                id:
                  type: string
                provider:
                  type: string
                providerRefundId:
                  oneOf:
                  - type: string
                  - type: 'null'
                reason:
                  enum:
                  - requested_by_customer
                  - duplicate
                  - fraudulent
                  - other
                  type: string
                status:
                  enum:
                  - SUCCEEDED
                  - FAILED
                  type: string
                transactionId:
                  type: string
              required:
              - id
              - transactionId
              - amount
              - currency
              - status
              - reason
              - provider
              - providerRefundId
              - errorCode
              type: object
            transaction:
              properties:
                amount:
                  pattern: ^(0|[1-9]\d{0,19})(\.\d{1,18})?$
                  type: string
                id:
                  type: string
                livemode:
                  type: boolean
                orderId:
                  type: string
                refundState:
                  enum:
                  - none
                  - partial
                  - full
                  type: string
                refundedAmount:
                  pattern: ^(0|[1-9]\d{0,19})(\.\d{1,18})?$
                  type: string
              required:
              - id
              - orderId
              - amount
              - refundedAmount
              - refundState
              - livemode
              type: object
          required:
          - refund
          - transaction
          type: object
        id:
          pattern: ^evt_[0-7][0-9a-hjkmnp-tv-z]{25}$
          type: string
        livemode:
          description: Mode of the transaction snapshot; false for sandbox.
          type: boolean
        type:
          enum:
          - refund.succeeded
          - refund.failed
          type: string
      required:
      - id
      - type
      - api_version
      - created_at
      - created
      - data
      - livemode
      type: object
    TransactionDto:
      properties:
        action:
          description: Transaction action type
          enum:
          - SALE
          - PAYOUT
          - AUTHORIZE
          - REFUND
          - CHARGEBACK
          example: SALE
          type: string
        amount:
          description: Transaction amount in `currency`. Decimal string in major units, padded to the currency exponent ("10.00" EUR, "5000" JPY). Parse with a decimal library, never with parseFloat.
          example: '10.00'
          pattern: ^(0|[1-9]\d{0,19})(\.\d{1,18})?$
          type: string
        createdAt:
          description: Transaction creation timestamp
          example: '2023-12-25T10:00:00.000Z'
          format: date-time
          type: string
        currency:
          description: Transaction currency
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRU
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SLL
          - SOS
          - SRD
          - SSP
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYU
          - UZS
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XAG
          - XAU
          - XCD
          - XDR
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMW
          - ZWL
          example: USD
          type: string
        currencyRate:
          anyOf:
          - description: Effective DCC rate as a plain decimal string; null without DCC.
            example: '0.9573935814433348'
            type: string
          - type: 'null'
        errorCode:
          anyOf:
          - description: 'Payment error/outcome reason. LIVEMODE_MISMATCH means the transaction was DECLINED before PSP dispatch; creation still returns HTTP 201 with status: true. PSP_OUTCOME_UNKNOWN means reconcile or poll; do not create another order. PSP_INPUT_INVALID identifies local legacy-submit serialization/codec failures; PSP_REQUEST_REJECTED identifies a definitive upstream rejection.'
            example: PSP_OUTCOME_UNKNOWN
            type: string
          - type: 'null'
        feeAmount:
          anyOf:
          - description: 'Configured fee: money in `processingCurrency` for FIXED fees, a percent ("10" = 10 %) for PERCENTAGE fees. Decimal string.'
            example: '10'
            pattern: ^(0|[1-9]\d{0,19})(\.\d{1,18})?$
            type: string
          - type: 'null'
        id:
          description: Transaction ID
          example: tr_xv0p2q5scocndpejk0nud75q
          type: string
        livemode:
          description: True for live payments; false for sandbox payments. Derived from the authenticated API key.
          example: true
          type: boolean
        orderId:
          description: Order ID from merchant system
          example: transaction_123
          type: string
        processingAmount:
          anyOf:
          - description: Amount in `processingCurrency`. Decimal string in major units, padded to the currency exponent ("10.00" EUR, "5000" JPY). Parse with a decimal library, never with parseFloat.
            example: '9.57'
            pattern: ^(0|[1-9]\d{0,19})(\.\d{1,18})?$
            type: string
          - type: 'null'
        processingAmountWithFee:
          anyOf:
          - description: Processing amount including a TOP fee, in `processingCurrency`. Decimal string in major units, padded to the currency exponent ("10.00" EUR, "5000" JPY). Parse with a decimal library, never with parseFloat.
            example: '10.53'
            pattern: ^(0|[1-9]\d{0,19})(\.\d{1,18})?$
            type: string
          - type: 'null'
        processingCurrency:
          description: Currency the PSP is charged in (differs from `currency` with DCC)
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRU
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SLL
          - SOS
          - SRD
          - SSP
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYU
          - UZS
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XAG
          - XAU
          - XCD
          - XDR
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMW
          - ZWL
          example: EUR
          type: string
        processingFeeAmount:
          anyOf:
          - description: Fee charged, in `processingCurrency`. Decimal string in major units, padded to the currency exponent ("10.00" EUR, "5000" JPY). Parse with a decimal library, never with parseFloat.
            example: '0.96'
            pattern: ^(0|[1-9]\d{0,19})(\.\d{1,18})?$
            type: string
          - type: 'null'
        status:
          description: Transaction status
          enum:
          - CREATED
          - WAIT_APPROVE
          - PROCESSING
          - CANCELED
          - DECLINED
          - SUCCESS
          - EXPIRED
          example: PROCESSING
          type: string
      required:
      - livemode
      - id
      - orderId
      - status
      - action
      - amount
      - currency
      - createdAt
      type: object
    WebhookEvent:
      description: Signed merchant event envelope (ADR-005/010). Event id and created_at remain unchanged on retries. Additional fields and event types may be added.
      properties:
        api_version:
          description: 'Payload version, fixed for the event (retries and re-drives keep it). Current: 2026-10-31. See the webhook event catalogue.'
          example: '2026-10-31'
          pattern: ^[0-9]{4}-[0-9]{2}-[0-9]{2}$
          type: string
        created_at:
          description: UTC time when the event was recorded, not delivery time
          format: date-time
          type: string
        data:
          properties:
            paymentData:
              description: Opaque JSON provider data. Shape varies by provider and event; may contain personal data. Do not log it.
            transaction:
              $ref: '#/components/schemas/TransactionDto'
          required:
          - transaction
          - paymentData
          type: object
        id:
          description: Stable event identifier (TypeID with prefix evt_); identical on every retry and re-drive. Use the signed body id for deduplication
          example: evt_0j7s2pft4v8b9t8nj2cra1eg00
          pattern: ^evt_[0-7][0-9a-hjkmnp-tv-z]{25}$
          type: string
        livemode:
          description: Mode of the transaction snapshot; false for sandbox.
          type: boolean
        type:
          description: Payment status event type; refund events use RefundWebhookEvent
          example: transaction.updated
          type: string
      required:
      - id
      - type
      - api_version
      - created_at
      - data
      - livemode
      type: object
  securitySchemes:
    X-API-Key:
      in: header
      name: x-api-key
      type: apiKey
    bearer:
      bearerFormat: Opaque cashier player grant
      scheme: bearer
      type: http