openapi: "3.1.0"
jsonSchemaDialect: "https://json-schema.org/draft/2020-12/schema"
info:
  title: "PayStar Merchant API"
  version: "2026-08-25.9"
  description: "Public integration baseline for PayStar merchant balances, deposits, payouts, and status operations. Available capabilities, credentials, limits, currencies, and routes are confirmed during merchant onboarding."
  contact:
    name: "PayStar integration manager"
servers:
  -
    url: "https://secure.paystar.uk"
    description: "Core API host for deposits, balances, payouts, and status operations"
tags:
  -
    name: "Balance"
    description: "Merchant and pipeline balance."
  -
    name: "Deposits"
    description: "H2H P2P, H2C, and tokenized deposit creation."
  -
    name: "Deposit status"
    description: "Deposit lookup by PayStar or merchant identifier."
  -
    name: "Payouts"
    description: "H2H payout creation."
  -
    name: "Payout status"
    description: "Payout lookup by PayStar or merchant identifier."
paths:
  "/api/v1/balance/merchant":
    get:
      operationId: "getMerchantBalance"
      summary: "Get merchant and pipeline balance"
      tags:
        - "Balance"
      servers:
        -
          url: "https://secure.paystar.uk"
      security:
        -
          bearerAuth:
            []
      parameters:
        -
          name: "currency"
          in: "query"
          required: true
          description: "Three-letter currency value. Syntax validation is mask-based, not a static currency-directory lookup."
          schema:
            "$ref": "#/components/schemas/CurrencyCode"
          example: "RUB"
      responses:
        "200":
          description: "Balance data."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/Balance"
        "400":
          description: "Missing or malformed currency."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/BusinessError"
        "401":
          description: "Missing or invalid Bearer token."
        "403":
          description: "The key is valid but cannot access balance."
  "/api/v1/integration/deposit-order/":
    post:
      operationId: "createDeposit"
      summary: "Create a deposit"
      description: "The host selects H2H, H2C, or tokenized behavior. The P2P H2H flow requires all three redirect URLs. Required additionalFields are configured per merchant flow."
      tags:
        - "Deposits"
      servers:
        -
          url: "https://secure.paystar.uk"
          description: "Core API host; this operation creates a direct H2H deposit, including the P2P flow"
        -
          url: "https://init.paystar.uk"
          description: "Hosted card collection that keeps card entry outside the merchant page and can reduce PCI DSS scope"
        -
          url: "https://token.paystar.uk"
          description: "Deposit using a token assigned to an approved merchant tokenized flow"
      security:
        -
          bearerAuth:
            []
      x-paystar-flow-variants:
        -
          id: "deposit-p2p-h2h"
          server: "https://secure.paystar.uk"
          requestSchema: "#/components/schemas/P2PDepositRequest"
        -
          id: "deposit-h2c"
          server: "https://init.paystar.uk"
          requestSchema: "#/components/schemas/H2CDepositRequest"
          description: "Hosted card collection that keeps card entry outside the merchant page and can reduce PCI DSS scope."
        -
          id: "deposit-tokenized-h2h"
          server: "https://token.paystar.uk"
          requestSchema: "#/components/schemas/TokenDepositRequest"
      requestBody:
        required: true
        content:
          "application/json":
            schema:
              anyOf:
                -
                  "$ref": "#/components/schemas/P2PDepositRequest"
                -
                  "$ref": "#/components/schemas/H2CDepositRequest"
                -
                  "$ref": "#/components/schemas/TokenDepositRequest"
            examples:
              p2p:
                "$ref": "#/components/examples/P2PDepositRequest"
              h2c:
                "$ref": "#/components/examples/H2CDepositRequest"
              tokenized:
                "$ref": "#/components/examples/TokenDepositRequest"
      responses:
        "200":
          description: "Deposit accepted."
          content:
            "application/json":
              schema:
                anyOf:
                  -
                    "$ref": "#/components/schemas/P2PDepositCreateResponse"
                  -
                    "$ref": "#/components/schemas/H2CDepositCreateResponse"
                  -
                    "$ref": "#/components/schemas/TokenDepositCreateResponse"
        "400":
          description: "Request validation failed, including malformed non-alpha-3 currency."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/BusinessError"
        "401":
          description: "Missing or invalid deposit Bearer token."
        "403":
          description: "The key is valid but cannot use this deposit capability."
        "415":
          description: "Unsupported media type. Framework-level error raised before PayStar business processing."
          content:
            "application/problem+json":
              schema:
                "$ref": "#/components/schemas/ProblemDetails415"
        "423":
          description: "No active route for a syntactically valid request, currency, or configured limits."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/BusinessError"
        "500":
          description: "Internal server error."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/BusinessError"
      x-paystar-retry-rule: "After timeout, broken connection, missing response, or HTTP 5xx, query status using the same externalTransactionId before any retry or cascade."
  "/api/v1/integration/deposit-order/{externalId}/status":
    get:
      operationId: "getDepositStatusByPayStarId"
      summary: "Get deposit status by PayStar ID"
      tags:
        - "Deposit status"
      servers:
        -
          url: "https://secure.paystar.uk"
      security:
        -
          bearerAuth:
            []
      x-paystar-key-capability: "deposit"
      parameters:
        -
          name: "externalId"
          in: "path"
          required: true
          description: "PayStar order identifier returned by create."
          schema:
            type: "string"
            minLength: 1
      responses:
        "200":
          description: "Current order state."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/DepositStatusResponse"
        "401":
          description: "Missing or invalid Bearer token."
        "403":
          description: "The key is valid but cannot access this resource."
        "404":
          description: "Order not found."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/BusinessError"
        "500":
          description: "Internal server error."
  "/api/v1/integration/deposit-order/{externalTransactionId}/status-by-external-transaction-id":
    get:
      operationId: "getDepositStatusByMerchantId"
      summary: "Get deposit status by merchant ID"
      tags:
        - "Deposit status"
      servers:
        -
          url: "https://secure.paystar.uk"
      security:
        -
          bearerAuth:
            []
      x-paystar-key-capability: "deposit"
      parameters:
        -
          name: "externalTransactionId"
          in: "path"
          required: true
          description: "Merchant-generated external transaction identifier."
          schema:
            type: "string"
            minLength: 1
      responses:
        "200":
          description: "Current order state."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/DepositStatusResponse"
        "401":
          description: "Missing or invalid Bearer token."
        "403":
          description: "The key is valid but cannot access this resource."
        "404":
          description: "Order not found."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/BusinessError"
        "500":
          description: "Internal server error."
  "/api/v1/integration/withdrawal-order/":
    post:
      operationId: "createPayout"
      summary: "Create an H2H payout"
      tags:
        - "Payouts"
      servers:
        -
          url: "https://secure.paystar.uk"
      security:
        -
          bearerAuth:
            []
      requestBody:
        required: true
        content:
          "application/json":
            schema:
              "$ref": "#/components/schemas/PayoutRequest"
            examples:
              card:
                "$ref": "#/components/examples/CardPayoutRequest"
      responses:
        "200":
          description: "Payout accepted."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/PayoutCreateResponse"
        "400":
          description: "Request validation failed, including malformed non-alpha-3 currency."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/BusinessError"
        "401":
          description: "Missing or invalid payout Bearer token."
        "403":
          description: "The key is valid but cannot use this payout capability."
        "415":
          description: "Unsupported media type. Framework-level error raised before PayStar business processing."
          content:
            "application/problem+json":
              schema:
                "$ref": "#/components/schemas/ProblemDetails415"
        "422":
          description: "Request cannot be processed for the configured merchant profile."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/BusinessError"
        "423":
          description: "No active route for a syntactically valid request, currency, or configured limits."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/BusinessError"
        "500":
          description: "Internal server error."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/BusinessError"
      x-paystar-retry-rule: "After timeout, broken connection, missing response, or HTTP 5xx, query status using the same externalTransactionId before retrying."
  "/api/v1/integration/withdrawal-order/{externalId}/status":
    get:
      operationId: "getPayoutStatusByPayStarId"
      summary: "Get payout status by PayStar ID"
      tags:
        - "Payout status"
      servers:
        -
          url: "https://secure.paystar.uk"
      security:
        -
          bearerAuth:
            []
      x-paystar-key-capability: "payout"
      parameters:
        -
          name: "externalId"
          in: "path"
          required: true
          description: "PayStar order identifier returned by create."
          schema:
            type: "string"
            minLength: 1
      responses:
        "200":
          description: "Current order state."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/PayoutStatusResponse"
        "401":
          description: "Missing or invalid Bearer token."
        "403":
          description: "The key is valid but cannot access this resource."
        "404":
          description: "Order not found."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/BusinessError"
        "500":
          description: "Internal server error."
  "/api/v1/integration/withdrawal-order/{externalTransactionId}/status-by-external-transaction-id":
    get:
      operationId: "getPayoutStatusByMerchantId"
      summary: "Get payout status by merchant ID"
      tags:
        - "Payout status"
      servers:
        -
          url: "https://secure.paystar.uk"
      security:
        -
          bearerAuth:
            []
      x-paystar-key-capability: "payout"
      parameters:
        -
          name: "externalTransactionId"
          in: "path"
          required: true
          description: "Merchant-generated external transaction identifier."
          schema:
            type: "string"
            minLength: 1
      responses:
        "200":
          description: "Current order state."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/PayoutStatusResponse"
        "401":
          description: "Missing or invalid Bearer token."
        "403":
          description: "The key is valid but cannot access this resource."
        "404":
          description: "Order not found."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/BusinessError"
        "500":
          description: "Internal server error."
components:
  securitySchemes:
    bearerAuth:
      type: "http"
      scheme: "bearer"
      bearerFormat: "JWT"
      description: "Use the PayStar key assigned to this specific pipeline. Every pipeline has a distinct key, including multiple deposit pipelines. Deposit and payout pipelines never share a key."
  schemas:
    CurrencyCode:
      type: "string"
      minLength: 3
      maxLength: 3
      pattern: "^[A-Za-z]{3}$"
      example: "RUB"
      description: "Alpha-3 syntax is validated by shape, not by a static currency directory. RU is malformed and normatively returns 400. ZZZ passes syntax and may return routing 423."
      x-paystar-owner-confirmed: true
    Amount:
      type: "number"
      exclusiveMinimum: 0
      example: 100
      description: "Amount in major currency units. JSON number is normative; quoted numeric strings remain backward-compatible. Normal requests and displayed examples use two decimal places. Flow-specific min/max are routing configuration."
      x-paystar-normal-decimal-places: 2
      x-paystar-display-format: "0.00"
      x-paystar-string-compatibility: true
    ExternalTransactionId:
      type: "string"
      minLength: 1
      description: "Unique merchant-generated identifier used for status lookup and safe retry resolution."
    AdditionalFieldValue:
      description: "Flow-specific scalar. Presence and non-null value are normative; formats and ranges belong to the selected flow schema."
      oneOf:
        -
          type: "string"
        -
          type: "number"
        -
          type: "boolean"
    AdditionalField:
      type: "object"
      required:
        - "key"
        - "value"
      properties:
        key:
          type: "string"
          minLength: 1
          description: "Canonical documented casing is lowerCamelCase."
        value:
          "$ref": "#/components/schemas/AdditionalFieldValue"
    BaseDepositRequest:
      type: "object"
      required:
        - "amount"
        - "currency"
        - "externalTransactionId"
      properties:
        amount:
          allOf:
            -
              "$ref": "#/components/schemas/Amount"
          x-paystar-p2p-rounding:
            mode: "half-up"
            decimalPlaces: 2
            examples:
              "100.124": 100.12
              "100.125": 100.13
              "100.126": 100.13
        currency:
          "$ref": "#/components/schemas/CurrencyCode"
        externalTransactionId:
          "$ref": "#/components/schemas/ExternalTransactionId"
        callbackUrl:
          type: "string"
          format: "uri"
          description: "Optional callback URL."
        processingRedirectUrl:
          type: "string"
          format: "uri"
        failedRedirectUrl:
          type: "string"
          format: "uri"
        successRedirectUrl:
          type: "string"
          format: "uri"
        additionalFields:
          type: "array"
          items:
            "$ref": "#/components/schemas/AdditionalField"
    P2PDepositRequest:
      title: "P2P H2H deposit request"
      allOf:
        -
          "$ref": "#/components/schemas/BaseDepositRequest"
        -
          type: "object"
          required:
            - "processingRedirectUrl"
            - "failedRedirectUrl"
            - "successRedirectUrl"
    H2CDepositRequest:
      title: "H2C hosted-form deposit request"
      allOf:
        -
          "$ref": "#/components/schemas/BaseDepositRequest"
      x-paystar-pci-rule: "Merchant must not collect card data."
    TokenDepositRequest:
      title: "Tokenized H2H deposit request"
      allOf:
        -
          "$ref": "#/components/schemas/BaseDepositRequest"
        -
          type: "object"
          required:
            - "additionalFields"
          properties:
            additionalFields:
              type: "array"
              minContains: 1
              contains:
                type: "object"
                required:
                  - "key"
                  - "value"
                properties:
                  key:
                    const: "cardStorageToken"
              items:
                "$ref": "#/components/schemas/AdditionalField"
    PayoutRequest:
      type: "object"
      required:
        - "amount"
        - "currency"
        - "externalTransactionId"
      properties:
        amount:
          "$ref": "#/components/schemas/Amount"
        currency:
          "$ref": "#/components/schemas/CurrencyCode"
        externalTransactionId:
          "$ref": "#/components/schemas/ExternalTransactionId"
        callbackUrl:
          type: "string"
          format: "uri"
        additionalFields:
          type: "array"
          items:
            "$ref": "#/components/schemas/AdditionalField"
          description: "Required key set is merchant- and flow-configured. Confirm it with the PayStar manager."
          x-paystar-requiredness: "flow-specific"
      description: "Deposit redirect fields are not payout request fields and must not be added to canonical payout examples."
    P2PPaymentDetails:
      type: "object"
      properties:
        card:
          type:
            - "string"
            - "null"
          description: "Sensitive payment detail; redact in stored evidence."
        fio:
          type:
            - "string"
            - "null"
        bank:
          type:
            - "string"
            - "null"
        formUrl:
          type:
            - "string"
            - "null"
          format: "uri"
          description: "Sensitive one-time query tokens must be redacted."
    P2PDepositCreateResponse:
      type: "object"
      required:
        - "externalId"
        - "orderStatus"
      properties:
        externalId:
          type: "string"
        orderStatus:
          type: "string"
          enum:
            - "Processing"
        paymentDetails:
          "$ref": "#/components/schemas/P2PPaymentDetails"
    H2CDepositCreateResponse:
      type: "object"
      required:
        - "externalId"
        - "orderStatus"
        - "formUrl"
      properties:
        externalId:
          type: "string"
        orderStatus:
          type: "string"
          enum:
            - "Init"
        formUrl:
          type: "string"
          format: "uri"
    TokenDepositCreateResponse:
      type: "object"
      required:
        - "externalId"
        - "orderStatus"
      properties:
        externalId:
          type: "string"
        orderStatus:
          type: "string"
          enum:
            - "Processing"
        paymentDetails:
          type: "object"
          properties:
            formUrl:
              type:
                - "string"
                - "null"
              format: "uri"
    PayoutCreateResponse:
      type: "object"
      required:
        - "externalId"
        - "orderStatus"
      properties:
        externalId:
          type: "string"
        orderStatus:
          type: "string"
          enum:
            - "Created"
    OrderHistoryItem:
      type: "object"
      properties:
        time:
          type: "string"
          format: "date-time"
        action:
          type:
            - "string"
            - "null"
          description: "Payment History action code."
        newCode:
          type:
            - "string"
            - "null"
          description: "Additional Payment History code returned by the current API."
    ExternalParams:
      type: "object"
      properties:
        cardToken:
          type:
            - "string"
            - "null"
          writeOnly: false
          description: "Sensitive; access and logging must be restricted."
        cardStorageToken:
          type:
            - "string"
            - "null"
          writeOnly: false
          description: "Sensitive; access and logging must be restricted."
        cardHolder:
          type:
            - "string"
            - "null"
        cardNumber:
          type:
            - "string"
            - "null"
          description: "Must be masked when returned."
      additionalProperties: true
      description: "Flow-dependent object; it may be absent or contain null fields."
    DepositStatusResponse:
      type: "object"
      required:
        - "externalId"
        - "orderStatus"
      properties:
        externalId:
          type: "string"
        orderStatus:
          type: "string"
          enum:
            - "Init"
            - "Created"
            - "Processing"
            - "Success"
            - "Failed"
        amount:
          "$ref": "#/components/schemas/Amount"
        externalParams:
          "$ref": "#/components/schemas/ExternalParams"
        orderHistory:
          type: "array"
          items:
            "$ref": "#/components/schemas/OrderHistoryItem"
          description: "Not guaranteed to be populated and may be delivered after the current status changes."
    PayoutStatusResponse:
      type: "object"
      required:
        - "externalId"
        - "orderStatus"
      properties:
        externalId:
          type: "string"
        orderStatus:
          type: "string"
          enum:
            - "Created"
            - "Processing"
            - "Success"
            - "Failed"
        amount:
          "$ref": "#/components/schemas/Amount"
        externalParams:
          "$ref": "#/components/schemas/ExternalParams"
        orderHistory:
          type: "array"
          items:
            "$ref": "#/components/schemas/OrderHistoryItem"
          description: "Not guaranteed to be populated and may be delayed."
    Balance:
      type: "object"
      required:
        - "currency"
        - "merchantBalance"
        - "merchantOverdraft"
        - "pipelineBalance"
        - "pipelineAvailableBalance"
        - "pipelineProcessingOrdersDeposit"
        - "pipelineProcessingOrdersWithdrawals"
      properties:
        currency:
          type: "string"
        merchantBalance:
          type: "number"
        merchantOverdraft:
          type: "number"
        pipelineBalance:
          type: "number"
        pipelineAvailableBalance:
          type: "number"
        pipelineProcessingOrdersDeposit:
          type: "number"
        pipelineProcessingOrdersWithdrawals:
          type: "number"
    BusinessError:
      type: "object"
      required:
        - "label"
        - "message"
      properties:
        label:
          type: "string"
          examples:
            - "VALIDATION_ERROR"
            - "REQUEST_VALIDATION_ERROR"
            - "TEMPORARY_ERROR"
            - "NOT_FOUND"
            - "INTERNAL_SERVER_ERROR"
        message:
          type: "string"
          description: "Do not branch on exact message text."
        statusDescrption:
          type:
            - "string"
            - "null"
          description: "Current compatible wire spelling, including the typo."
        externalTransactionId:
          type:
            - "string"
            - "null"
        code:
          type:
            - "string"
            - "null"
          description: "Application code; the complete stable catalog is not yet documented."
    ProblemDetails415:
      type: "object"
      required:
        - "type"
        - "title"
        - "status"
      properties:
        type:
          type: "string"
          format: "uri"
        title:
          type: "string"
          example: "Unsupported Media Type"
        status:
          type: "integer"
          const: 415
        traceId:
          type: "string"
  examples:
    P2PDepositRequest:
      summary: "P2P H2H request"
      value:
        amount: 100.00
        currency: "RUB"
        externalTransactionId: "merchant-deposit-123"
        callbackUrl: "https://merchant.example/paystar/callback"
        processingRedirectUrl: "https://merchant.example/payment/processing"
        failedRedirectUrl: "https://merchant.example/payment/failed"
        successRedirectUrl: "https://merchant.example/payment/success"
        additionalFields:
          []
    H2CDepositRequest:
      summary: "H2C hosted-form request"
      value:
        amount: 100.00
        currency: "RUB"
        externalTransactionId: "merchant-h2c-123"
        callbackUrl: "https://merchant.example/paystar/callback"
        additionalFields:
          []
    TokenDepositRequest:
      summary: "Tokenized H2H request"
      value:
        amount: 100.00
        currency: "RUB"
        externalTransactionId: "merchant-token-deposit-123"
        callbackUrl: "https://merchant.example/paystar/callback"
        additionalFields:
          -
            key: "cardStorageToken"
            value: "{{cardStorageToken}}"
    CardPayoutRequest:
      summary: "Typical card payout; confirm exact required fields with the PayStar manager"
      value:
        amount: 1000.00
        currency: "RUB"
        externalTransactionId: "merchant-payout-123"
        callbackUrl: "https://merchant.example/paystar/callback"
        additionalFields:
          -
            key: "payeerIdentifier"
            value: "merchant-customer-123"
          -
            key: "bankName"
            value: "Example Bank"
          -
            key: "cardHolder"
            value: "TEST CARDHOLDER"
          -
            key: "cardNumber"
            value: "{{testCardNumber}}"
x-paystar-contract-version: "2026-08-25.9"
x-paystar-published-date: "2026-08-25"
