openapi: 3.1.0
info:
  title: Kashier API
  version: v3
  license:
    name: Proprietary — © Kashier. All rights reserved.
    identifier: LicenseRef-Kashier-Proprietary
  description: |
    REST API for Kashier, the Egyptian payment gateway.

    Kashier exposes two environments:

    - **Test** — endpoints on `test-api.kashier.io` / `test-fep.kashier.io`. No real money moves;
      use it while you are still in the development phase.
    - **Live** — endpoints on `api.kashier.io` / `fep.kashier.io`, for production traffic.

    The `Authorization` header carries your merchant **secret key** (raw value, not a Bearer token),
    and the `api-key` header carries the API key from the merchant dashboard (Integrations section).
    Both keys differ between the test and live environments, so make sure to use the correct one for each.

    Some operations (refund, void, capture, pay with token, tokens, payout transfer creation) are served
    from the `fep.kashier.io` / `test-fep.kashier.io` hosts; those paths declare their own `servers` blocks.

    This specification lists only the TEST servers so the docs playground can never touch production.
    When you go live, swap the base URL to the live host (drop the `test-` prefix): `https://api.kashier.io`
    (or `https://fep.kashier.io` for fep-served operations) and switch to your live keys.
servers:
  - url: https://test-api.kashier.io
    description: Test — no real money moves
security:
  - secretKey: []
tags:
  - name: Payment sessions
    description: Create and inspect payment sessions. Payment Sessions make transactions more secure and efficient — with a simple API call you can create payments without exposing sensitive data in query strings, and session history tracking lets you monitor every action in real time.
  - name: Transactions
    description: Retrieve transaction data and export transaction batch data so merchants can monitor their transactions efficiently.
  - name: Order operations
    description: "Refund, void, capture and reversal against an existing order. Refunds repay customers in part or fully from your available Kashier balance; capture and void complete or cancel authorized amounts. Each operation is reachable two ways, and they are the same operation, not two implementations: as `PUT /v3/orders/{orderId}` on the checkout host (`test-fep.kashier.io`) with the operation named in `apiOperation`, or as its own path on the dashboard host (`test-api.kashier.io`). The checkout host applies no authentication of its own — it rewrites the path from `apiOperation` and forwards your request, credential included, to the dashboard route, which is the single point where auth and permissions are enforced. Either way, authenticate with your merchant secret key in the `Authorization` header; refund and void additionally need the refund permission on the key's role."
  - name: Tokens
    description: "Card tokenization — pay with a saved card token, retrieve a customer's saved card tokens, and delete a token. Tokenization is exposed on both hosts, and which one you use decides how you authenticate. The checkout host (`test-fep.kashier.io`) carries the customer-facing calls — pay with token, create, read and delete a token — validated with a `Kashier-Hash` (HMAC SHA256) header and no secret key. The dashboard host (`test-api.kashier.io`) carries the account-wide management reads under `/v3/payment/tokenization`, authenticated with your merchant secret key in `Authorization` and no hash. Card numbers are always masked; there is no endpoint that returns a full PAN."
  - name: Installments
    description: Retrieve installment-enabled banks and their installment plans.
  - name: Payouts
    description: Payout bank and wallet transfer APIs — check account balance, list transfers, inquire about fees, and create single or bulk transfers to pay vendors, suppliers, employees, or customers.
  - name: Customers
    description: Store, update, and retrieve customer profiles, so payments and payment links can be linked back to the person who paid. Customers can be created one at a time, bulk-imported from an Excel sheet, and exported asynchronously.
  - name: Invoices
    description: Invoices (payment requests) — create a payable invoice or payment link, share it with a customer by email or SMS, track whether it has been paid, and export or bulk-import invoices. Served from the api.kashier.io / test-api.kashier.io hosts and authenticated with your merchant secret key in the Authorization header.
  - name: Payment links
    description: Create, share, update, and export payment links — shareable pages your customers open and pay on, with no integration required. Links can be created one at a time, created and shared in a single call, or bulk-imported from an Excel sheet.
  - name: Payment pages
    description: "Payment pages — merchant-built, shareable pages that collect a payment without any integration work: either a regular page that asks for one amount, or a product page that lists a catalogue the customer picks from. Served from the api.kashier.io / test-api.kashier.io hosts and authenticated with your merchant secret key in the Authorization header, except for the two /public reads that the page itself uses."
  - name: Balance and accounts
    description: Read your Kashier balance accounts — the ledger Kashier keeps for you. Every account carries a total and an available balance, the payout method money leaves by, and a stream of balance records (one per settlement, payout, refund, or adjustment that moved the balance). Use these reads to build a statement, reconcile a payout back to the records it paid, and check what is currently on hold.
  - name: Settlement reporting
    description: Read how your captured sales are grouped into settlement windows and batches, and what fees were taken on the way. A window groups the transactions ready for settlement on a given date; each window closes into one or more batches, and each batch carries the selling fees, VAT, and net settlement amount you reconcile against. Settlement windows are produced by the live settlement pipeline only — test mode never creates windows or batches.
  - name: Bulk batches
    description: "Batches group many invoices (payment requests) into one job so a merchant can bill a whole list of customers at once: create a batch, fill it by importing an Excel sheet, correct any row that came in wrong, then share the batch and Kashier sends every customer their own payment link. Served from the api.kashier.io / test-api.kashier.io hosts and authenticated with your merchant secret key in the Authorization header. These are the bulk-billing batches — for grouped payouts to vendors and employees see the Payouts endpoints under /v2/transfers/batch."
  - name: Checkout reference data
    description: "Read-only lookups a custom checkout needs before it can render: which payment methods your merchant account is entitled to, which banks offer installments on it, and the plans and fees behind each bank. These endpoints are public — they take no Authorization header, because a browser-side checkout calls them before any payment exists. Served from the api.kashier.io / test-api.kashier.io hosts."
  - name: Constants
    description: Static Kashier reference lists — Egyptian banks, cities, countries, industries, and the payment method definitions behind the gateway. Public and unauthenticated; safe to cache, since the values change rarely.
  - name: Fees and discounts
    description: "Calculators that tell you what a payment will actually cost before it is made: how much processing fee a customer-borne pricing model adds on top of an amount, and whether a bank discount campaign applies to the card the customer is about to pay with. Use them to show the real total on your checkout rather than surprising the customer at the end. The two card-level and merchant-level lookups are public so a checkout page can call them directly; the rest are authenticated with your merchant secret key in the Authorization header."
  - name: Instant settlement
    description: "Get your not-yet-settled sales paid out early instead of waiting for their normal settlement date, in exchange for a fee. The usual flow is: list your eligible transactions, optionally ask for amount suggestions or a fee inquiry, then create a request. A request starts as `PENDING`, becomes `PROCESSING` once the early-payout amount is deducted from your balance, and `TRANSFERRED` once the money reaches your payout method; a request that will not be processed becomes `DECLINED`. Instant settlement must be enabled on your account — contact your account manager or customer success to switch on the `instant_settlement_request` feature flag, agree your fee and caps, and have the `instant_settlements.all.view_instant_settlement` and `create_instant_settlement` permissions granted to your user's role."
  - name: POS terminals
    description: "Card-present POS integration: drive a Kashier-managed terminal from your backend by relaying a sale or details message to it, generate a POS payment QR, and read the terminal's transactions, reports, branches and settlement acknowledgements. Served from the api.kashier.io / test-api.kashier.io hosts and authenticated with your merchant secret key in the Authorization header. Every terminal route is scoped to the terminals that belong to your merchant account — a terminal that belongs to another merchant is rejected with 401."
  - name: Terminals
    description: Read the POS terminals registered on your merchant account, their branches, and an Excel export of the terminal list. Terminal provisioning (adding, editing, or removing hardware) is performed by Kashier, not through the merchant API.
  - name: Products
    description: A merchant's product catalogue — the items a product payment page or a payment link line item is built from. Products can be created one at a time from an ERP, listed and filtered, priced per currency, given an image, grouped into categories, and exported to a sheet. Served from the api.kashier.io / test-api.kashier.io hosts and authenticated with your merchant secret key in the Authorization header.
  - name: Categories
    description: Product categories — the grouping layer above products. Categories organise a catalogue so a product payment page can present its items in sections, and they can be assigned to products in bulk. The two public reads are the ones a payment page itself calls while a customer is browsing.
  - name: Webhooks
    description: "The webhook management module (`/v2/webhooks`). Create as many named webhooks as you need, each scoped to a mode (test or live) and to the events it should receive, so Kashier notifies you automatically without a webhook URL on every request. The module also covers the catalog of subscribable events, delivery-record lookup, resending a failed delivery, and sending a test event."
  - name: Credentials and access
    description: "The two credentials Kashier issues you and the IP allow-list that gates them. A **Secret Key** goes in the `Authorization` header and authenticates every Dashboard API call; a **Payment API Key** never travels as a credential at all — it is the shared secret you compute the `Kashier-Hash` order hash with and verify redirect and webhook signatures against. Each account has a separate pair per environment, and the two environments' keys are never interchangeable. The IP allow-list endpoints matter more than their size suggests: every secret-key call is checked against the list, an address that is not on it is refused with `403 Unauthorized IP address` that reads like an auth failure, and an *empty* list allows everything — so the restriction is invisible until someone adds the first entry, which is exactly why it catches integrations out."
paths:
  /v3/payment/sessions:
    post:
      operationId: createPaymentSession
      tags:
        - Payment sessions
      summary: Create payment session
      description: Creates a payment session. The response contains a sessionUrl that is used to redirect the customer to the payment page — you can use it as the src attribute in a link or iframe.
      security:
        - secretKey: []
          apiKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreatePaymentSessionRequest"
            examples:
              createSession:
                summary: Create a one-time card/wallet session
                value:
                  expireAt: 2030-01-01 00:00:00+00:00
                  maxFailureAttempts: 3
                  paymentType: credit
                  amount: "100.00"
                  currency: EGP
                  order: 8f64saf6sa4
                  merchantRedirect: https://your-website.com/redirect
                  display: en
                  type: one-time
                  allowedMethods: card,wallet
                  redirectMethod: null
                  iframeBackgroundColor: "#FFFFFF"
                  metaData:
                    customKey: customValue
                    displayNotes:
                      key: value
                  merchantId: YOUR_MID
                  failureRedirect: false
                  brandColor: "#FF5733"
                  defaultMethod: card
                  description: Payment for order ORD123456
                  manualCapture: false
                  customer:
                    email: john@example.com
                    reference: "894321"
                  saveCard: optional
                  retrieveSavedCard: true
                  interactionSource: ECOMMERCE
                  enable3DS: true
                  serverWebhook: https://your_webhook_url
                  notes: Special handling required
      responses:
        "200":
          description: Payment session created. `sessionUrl` redirects the customer to the payment page.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentSession"
              examples:
                created:
                  value:
                    status: CREATED
                    failureAttempts: 0
                    capturedAmount: 0
                    refundedAmount: 0
                    _id: 67adc07584f10c00121f6739
                    merchantId: MID-XXXX-XXXX
                    expireAt: 2025-01-28 17:27:32.359000+00:00
                    maxFailureAttempts: 3
                    paymentParams:
                      display: en
                      paymentType: credit
                      amount: "100.00"
                      currency: EGP
                      order: as8f64a5
                      merchantRedirect: https://your-website.com/redirect
                      type: one-time
                      allowedMethods: card,wallet
                      redirectMethod: null
                      iframeBackgroundColor: "#FFFFFF"
                      metaData:
                        customKey: customValue
                        displayNotes:
                          key: value
                      failureRedirect: false
                      brandColor: "#FF5733"
                      defaultMethod: card
                      description: Payment for order ORD123456
                      manualCapture: false
                      customer:
                        email: john@example.com
                        reference: "894321"
                      saveCard: optional
                      retrieveSavedCard: true
                      interactionSource: ECOMMERCE
                      enable3DS: true
                      serverWebhook: https://your_webhook_url
                      notes: Special handling required
                      hash: 3a657fb8e653c024a4abdd31b084082c8bbd4d9438f98451ca42a4abeb49766d
                      storeName: Demo
                      store: Demo
                    apiKey: "{{merchant_api_key}}"
                    history:
                      - status: CREATED
                        date: 2025-02-13 09:50:45.360000+00:00
                    webhookNotifications: []
                    createdAt: 2025-02-13 09:50:45.363000+00:00
                    updatedAt: 2025-02-13 09:50:45.363000+00:00
                    __v: 0
                    sessionUrl: https://payments.kashier.io/session/67adc07584f10c00121f6739?mode=test
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
    get:
      operationId: listPaymentSessions
      tags:
        - Payment sessions
      summary: List payment sessions
      description: |
        Lists the payment sessions on your merchant account — the sessions you created, in
        whatever state they reached. Use it to sweep up sessions your own records lost track
        of; to poll one particular session, use Get payment session by id instead, which is
        cheaper and needs no credential.

        Requires the transaction-view permission on your user's role.

        > Kashier has not published the query parameters or the exact pagination envelope for
        > this endpoint, so neither is described here. Send the call and read what comes back;
        > the "Try it" panel below will show you the real shape for your account.
      security:
        - secretKey: []
      responses:
        "200":
          description: The merchant's payment sessions. Each entry is a session document of the same kind Create payment session returns.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                description: A paginated collection of session documents. The envelope is not documented by Kashier — inspect the live response rather than assuming a field layout.
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/sessions/{sessionId}:
    get:
      operationId: getPaymentSessionById
      tags:
        - Payment sessions
      summary: Get payment session by id
      description: |
        Returns the session document for one session — its current `status`, the payment
        parameters it was created with, and its `history` of state changes.

        **This endpoint takes no credential.** It is the read the hosted checkout page itself
        performs, which is why it is unauthenticated, and why it is also the cheapest way for
        your backend to poll a session while the customer is paying. It exposes nothing beyond
        what the customer already sees on the payment page — but treat the `sessionId` itself
        as the capability it is, and do not publish one anywhere you would not publish the
        payment link.

        Poll this until `status` reaches a final state (`PAID`, `AUTHORIZED`, `FAILED`,
        `EXPIRED`, `ABANDONED`, `REJECTED`, `VOIDED`, `REVERSED`, `REFUNDED`), or — better —
        let the webhook tell you and use this to confirm.
      security: []
      parameters:
        - name: sessionId
          in: path
          required: true
          description: The session's `_id`, returned as `_id` by Create payment session and embedded in the `sessionUrl`.
          schema:
            type: string
      responses:
        "200":
          description: The payment session.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentSession"
        "400":
          $ref: "#/components/responses/BadRequest"
        "404":
          description: No session with that id exists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorEnvelope"
              examples:
                notFound:
                  value:
                    error:
                      cause: resource not found
                    messages:
                      en: Payment session not found
                      ar: Payment session not found
                    status: FAILURE
        "500":
          $ref: "#/components/responses/ServerError"
    patch:
      operationId: abandonPaymentSession
      tags:
        - Payment sessions
      summary: Abandon a payment session
      description: |
        Marks a session as `ABANDONED` — the customer closed the checkout, or you decided the
        session is no longer wanted. Abandoning is the clean way to end a session you will not
        use, rather than leaving it to expire on its own at `expireAt`.

        Like the read above, this call takes **no credential** — the hosted checkout page calls
        it directly when the customer walks away. It needs no request body.

        Abandoning does not move money and cannot undo a payment: a session that has already
        reached a final state stays where it is. To reverse money that has already moved, use
        the refund, void or capture-release operations instead.
      security: []
      parameters:
        - name: sessionId
          in: path
          required: true
          description: The session's `_id`.
          schema:
            type: string
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
              description: No fields are required. Send an empty object.
            examples:
              abandon:
                value: {}
      responses:
        "200":
          description: The session was abandoned. The body is the updated session document, with `status` now `ABANDONED`.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                description: The updated session document. Kashier has not published the exact projection returned here, so read `status` and treat the rest as informational.
        "400":
          $ref: "#/components/responses/BadRequest"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/sessions/{sessionId}/payment:
    get:
      operationId: getPaymentSession
      tags:
        - Payment sessions
      summary: Get payment session
      description: Retrieves the current state (and history) of a payment session.
      security:
        - secretKey: []
      parameters:
        - name: sessionId
          in: path
          required: true
          description: The payment session identifier returned when the session was created.
          schema:
            type: string
      responses:
        "200":
          description: The payment session details, including its status, amounts, customer info, and a history of status changes and actions taken on the session.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    $ref: "#/components/schemas/PaymentSessionDetails"
              examples:
                pending:
                  value:
                    message: success
                    data:
                      sessionId: 67ada35e9d5266001295b153
                      status: PENDING
                      createdAt: 2025-02-13 07:46:38.018000+00:00
                      updatedAt: 2025-02-13 09:57:23.780000+00:00
                      merchantId: MID-XXXX-XXXX
                      merchantOrderId: testOrder123
                      amount: "100.00"
                      currency: EGP
                      method: card
                      orderId: NA
                      paymentChannel: ONLINE
                      rfsDate: NA
                      lastTransactionType: NA
                      issuerAuthorizationCode: NA
                      metaData:
                        customKey: customValue
                        displayNotes:
                          key: value
                      customer:
                        email: john@example.com
                        reference: "894321"
                      history:
                        - status: OPENED
                          date: 2025-02-13 09:57:23.783000+00:00
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/aggregator/transactions:
    get:
      operationId: listTransactions
      tags:
        - Transactions
      summary: Get all transactions
      description: Retrieves a list of transaction records based on multiple optional filter parameters, such as currency, amount, status, channel, etc. The data can be paginated, sorted, and searched.
      security:
        - secretKey: []
      parameters:
        - name: currency
          in: query
          description: ISO 4217 currency code (e.g., EGP, USD).
          schema:
            type: string
        - name: sortBy
          in: query
          description: Field name to sort by (e.g., amount, date, etc.). Leave empty for default.
          schema:
            type: string
        - name: sortType
          in: query
          description: "Sorting direction: 1 = ascending, -1 = descending."
          schema:
            type: integer
            enum:
              - 1
              - -1
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: page
          in: query
          description: Page number
          schema:
            type: integer
        - name: status
          in: query
          description: Filter by transaction status [approved, rejected, unknown]
          schema:
            type: string
            enum:
              - approved
              - rejected
              - unknown
        - name: search
          in: query
          description: keyword for trxId or merchant orderId to filter with
          schema:
            type: string
        - name: amountFrom
          in: query
          description: Minimum transaction amount.
          schema:
            type: string
        - name: amountTo
          in: query
          description: Maximum transaction amount.
          schema:
            type: string
        - name: channel
          in: query
          description: Payment channel [online, pos]
          schema:
            type: string
            enum:
              - online
              - pos
        - name: type
          in: query
          description: Transaction type [payment, refund]
          schema:
            type: string
            enum:
              - payment
              - refund
        - name: method
          in: query
          description: Payment method [card, wallet, valu, octo, souhoola]
          schema:
            type: string
            enum:
              - card
              - wallet
              - valu
              - octo
              - souhoola
      responses:
        "200":
          description: The payment transactions, with pagination info.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: array
                    items:
                      $ref: "#/components/schemas/TransactionRecord"
                  pagination:
                    $ref: "#/components/schemas/Pagination"
                  message:
                    type: string
              examples:
                transactions:
                  summary: A single approved card payment (abridged from the docs example)
                  value:
                    body:
                      - _id: 688f2b051d65c20012aa314a
                        isPOSPortalRefund: false
                        createdAt: 2025-08-03 09:25:25.557000+00:00
                        merchantId: MID-24358-575
                        storeName: TEST-Demo
                        orderReference: TEST-ORD-193402001
                        merchantOrderId: "71754213106"
                        totalAuthorizedAmount: "105"
                        method: card
                        sourceOfFunds:
                          cardInfo:
                            maskedCard: 512345******2346
                            cardBrand: Mastercard
                            cardHolderName: John Doe
                            cardDataToken: 3cd66a8b-b5e2-44c2-a753-d3ad069ff2dd
                            agreement: null
                        paymentAgreement: regular
                        provider: mpgs
                        status: Approved
                        transactionId: TX-243585751279
                        targetedTransaction: TX-243585751277
                        targetedTransactionOperation: 3dsecure_verify
                        id: 00916dc7-7a3a-4875-af44-118bc678378b
                        channel: online | e-commerce
                        type: PAYMENT
                        currency: EGP
                        lastStatus: CAPTURED
                        isVoided: false
                        isCancelled: false
                        dateToFilter: 2025-08-03 09:25:24.335000+00:00
                        date: 2025-08-03 09:25:24.335000+00:00
                        responseDate: 2025-08-03 09:25:25.459000+00:00
                        settlementDate: 2025-08-03 09:25:25.459000+00:00
                        bankValueDate: 2025-08-03 09:25:25.459000+00:00
                        bankSettlementDate: 2025-08-03 09:25:25.459000+00:00
                        formattedDate: 2025-08-03
                        dateTime: "44724"
                        lastModifiedDate: 2025-08-03 09:25:25.494000+00:00
                        issuer: card
                        issuerAuthorizationCode: "119058"
                        transactionResponseCode: "00"
                        transactionResponseMessage:
                          en: Approved
                          ar: تمت الموافقة
                        pcc:
                          operations: []
                          financial_institution: qnb
                        transactions: []
                    message: The payment transactions has been retreived successfully
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/aggregator/transactions/{transactionId}:
    get:
      operationId: getTransactionDetails
      tags:
        - Transactions
      summary: Get transaction details
      description: Retrieves detailed information about a single transaction using its unique reference ID.
      security:
        - secretKey: []
      parameters:
        - name: transactionId
          in: path
          required: true
          description: The transaction reference ID (e.g., `TX-243585751279`).
          schema:
            type: string
      responses:
        "200":
          description: The payment transaction details.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: object
                    additionalProperties: true
                  message:
                    type: string
              examples:
                transaction:
                  summary: Approved card payment (abridged from the docs example)
                  value:
                    body:
                      transactionId: TX-243585751279
                      method: card
                      provider: mpgs
                      pcc:
                        financial_institution: qnb
                      currency: EGP
                      paymentChannel: online | e-commerce
                      status: SUCCESS
                      paymentStatus: SUCCESS
                      date: 2025-08-03 09:25:24.335000+00:00
                      trxType: payment
                      merchantOrderId: 71754213106
                      metaData:
                        kashier payment UI version: V3
                        referral url: http://localhost/
                        termsAndConditions:
                          ip: 41.35.216.58
                        merchantWebhook: https://webhook.site/b607673d-c9a6-493c-908b-91498acf3014
                      paymentOrigin: new_woo_demo
                      transactionResponseCode: "00"
                      transactionResponseMessage:
                        en: Approved
                        ar: تمت الموافقة
                      isReversed: false
                      isVoided: false
                      order:
                        orderReference: TEST-ORD-193402001
                        feeTrxAmount: "0.00"
                        feeVatAmount: "0.00"
                        accountType: PF
                        orderId: 00916dc7-7a3a-4875-af44-118bc678378b
                      sourceOfFunds:
                        maskedCard: 512345******2346
                        cardBrand: Mastercard
                        cardHolderName: John Doe
                        cardDataToken: 3cd66a8b-b5e2-44c2-a753-d3ad069ff2dd
                        expiryYear: "26"
                        expiryMonth: "05"
                        storedOnFile: NOT_STORED
                        save: false
                        agreement: null
                      transactions:
                        - status: SUCCESS
                          currency: EGP
                          operation: pay
                          transactionId: TX-243585751279
                          date: 2025-08-03 09:25:24.335000+00:00
                    message: The payment transaction has been retreived successfully
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/orders:
    get:
      operationId: searchOrders
      tags:
        - Transactions
      summary: Look up an order and its transactions
      description: |
        The endpoint to call after a payment when you need to know what actually happened.
        It returns the whole **order** — every transaction attempted against it, each one's
        response code, and Kashier's own reconciliation verdict — so you can settle the
        question "was this paid?" from Kashier's records rather than from a webhook you may
        have missed.

        **Read the order status, not the HTTP status.** A declined payment is still an
        HTTP 200 here, and inside `transactions[]` a declined attempt is still a stored
        transaction. Branch on the order-level `status` (`CAPTURED` is the paid state) and,
        per transaction, on `status` together with `transactionResponseCode`.

        **`search` is required**, and it is a partial, case-insensitive match on your own
        `merchantOrderId` — not on Kashier's order id. Calling without it returns a 400.
        (Kashier's older published docs name this parameter `merchantOrderId`; the parameter
        the API actually accepts is `search`.)

        A merchant's calls are always scoped to their own MID, which is taken from the
        credential — you cannot read another merchant's orders by passing a different
        `merchantId`.
      security:
        - secretKey: []
      parameters:
        - name: search
          in: query
          required: true
          description: Partial, case-insensitive match on your `merchantOrderId`. Must be a non-empty string of 1–100 characters; the call is rejected with a 400 without it.
          schema:
            type: string
            minLength: 1
            maxLength: 100
          example: ORDER-12345
        - name: status
          in: query
          required: false
          description: Filter by the order-level status. The value is upper-cased before matching, so `captured` and `CAPTURED` are equivalent. This is the `OrderStatus` vocabulary — not the `Approved`/`Rejected` labels used by the transactions list.
          schema:
            $ref: "#/components/schemas/OrderStatus"
        - name: startDate
          in: query
          required: false
          description: Only return orders dated on or after this date. Must not be later than `endDate`, or the call is rejected with a 400.
          schema:
            type: string
          example: 2026-06-01
        - name: endDate
          in: query
          required: false
          description: Only return orders dated on or before this date.
          schema:
            type: string
          example: 2026-06-18
        - name: page
          in: query
          required: false
          description: Page number. Defaults to 1.
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          required: false
          description: Page size. Defaults to 20. Orders come back newest first.
          schema:
            type: integer
            default: 20
      responses:
        "200":
          description: The matching orders, newest first. An empty `data` array means no order matched the search — it does not mean the payment failed.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: SUCCESS
                  message:
                    type: string
                    example: Orders retrieved successfully
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/ReconciledOrder"
                  pagination:
                    $ref: "#/components/schemas/Pagination"
              examples:
                captured:
                  summary: A card order that was paid
                  value:
                    status: SUCCESS
                    message: Orders retrieved successfully
                    data:
                      - merchantOrderId: ORDER-12345
                        orderId: 00916dc7-7a3a-4875-af44-118bc678378b
                        status: CAPTURED
                        interChangeRate: ON_US
                        transactions:
                          - operation: 3dsecure_verify
                            status: SUCCESS
                            transactionResponseCode: AUTHENTICATION_IN_PROGRESS
                            transactionResponseMessage:
                              en: Authentication in progress
                              ar: المصادقة قيد التقدم
                            reconcilation: "NA"
                            merchantWebhookReconciliation: "NA"
                          - operation: pay
                            status: SUCCESS
                            transactionResponseCode: APPROVED
                            transactionResponseMessage:
                              en: Approved
                              ar: تمت الموافقة
                            reconcilation: OK
                            merchantWebhookReconciliation: OK
                            isSettled: true
                    pagination:
                      total: 1
                      page: 1
                      limit: 20
                      pages: 1
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/export:
    get:
      operationId: exportTransactionBatches
      tags:
        - Transactions
      summary: Export transaction batches
      description: Exports transaction data based on specific filters such as status and date range. It's typically used for reporting, reconciliation, and data analysis by aggregators or merchants. The export is delivered by email.
      security:
        - secretKey: []
      parameters:
        - name: status
          in: query
          description: "Filter transactions by status. Example: Approved"
          schema:
            type: string
        - name: startDate
          in: query
          description: "Start of the date range (ISO 8601 format). Example: 2024-10-27T00:00:00.000Z."
          schema:
            type: string
        - name: endDate
          in: query
          description: "End of the date range (ISO 8601 format). Example: 2024-11-27T23:59:59.999Z."
          schema:
            type: string
      responses:
        "200":
          description: Export accepted for processing — an email with the export is sent within a few minutes.
          content:
            application/json:
              schema:
                type: object
                properties:
                  messages:
                    $ref: "#/components/schemas/LocalizedMessage"
              examples:
                processing:
                  value:
                    messages:
                      en: We're processing your request. Expect to receive an email in just a few minutes
                      ar: جاري معالجة طلبك. توقع استلام بريد إلكتروني في غضون دقائق قليلة
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/orders/{orderId}:
    servers:
      - url: https://test-fep.kashier.io
        description: Test — no real money moves
    put:
      operationId: updateOrder
      tags:
        - Order operations
      summary: Refund, void, or capture an order
      description: |
        Performs an operation against an existing order, selected by the apiOperation field
        in the body:

        - **REFUND** — repay your customer in part or fully. For partial refunds pass an
          amount in transaction. The refund amount must not exceed the amount of the
          original transaction. Refunds use your available Kashier balance (pending balance
          excluded). Refund statuses: SUCCESS (processed by the processor), FAILURE
          (cannot be processed; your account is credited with the refund amount), PENDING
          (initiated, waiting for the processor).
        - **VOID** — cancel the order's transaction amount fully or partially. You can
          cancel a pay, refund, authorize, or capture transaction; pass the
          targetTransactionId returned in a previous response.
        - **CAPTURE** — capture a previously authorized amount fully or partially. You
          should capture the amount before 7 or 30 days depending on your configuration.
          The Authorization Capture feature must be enabled by contacting your account
          manager or customer success. Releasing an authorized amount back to the customer
          is done with the VOID operation.

        **Authentication.** Send your **secret key** in the `Authorization` header, as you
        do for the Dashboard API. This route is not the same as the pay call: creating an
        order (`POST /v3/orders`) is gated by a `Kashier-Hash` header and takes no secret
        key, while refund, void and capture are authenticated further down the chain by
        your secret key, and refund and void additionally require the refund permission on
        the key's role. Kashier has not published a `Kashier-Hash` string-to-sign for this
        route — the documented signed strings cover only the create/pay, tokenization,
        3DS-resume and session-create calls — so send `Authorization` and no hash. If your
        account rejects an update with `INVALID_HASH_CHECK`, that is an unconfirmed case to
        raise with Kashier support.
      security:
        - secretKey: []
      parameters:
        - name: orderId
          in: path
          required: true
          description: Kashier Order Id
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - $ref: "#/components/schemas/RefundRequest"
                - $ref: "#/components/schemas/VoidRequest"
                - $ref: "#/components/schemas/CaptureRequest"
            examples:
              refund:
                summary: Refund (partial or full)
                value:
                  apiOperation: REFUND
                  reason: any reason
                  transaction:
                    amount: 3
              void:
                summary: Void a transaction
                value:
                  apiOperation: VOID
                  transaction:
                    amount: 3
                    targetTransactionId: TX-1902526801
              capture:
                summary: Capture an authorized amount
                value:
                  apiOperation: CAPTURE
                  transaction:
                    amount: 3
      responses:
        "200":
          description: Operation result. `response.status` reflects the resulting order state (e.g. `PARTIALLY_REFUNDED` order status for refunds, `CANCELLED` for voids, `CAPTURED` for captures) and the top-level `status` is `SUCCESS` when the request was processed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrderOperationResult"
              examples:
                refund:
                  summary: Successful (partial) refund
                  value:
                    response:
                      status: SUCCESS
                      gatewayCode: APPROVED
                      gatewayMessage: Payment accepted
                      transactionResponseCode: "00"
                      transactionResponseMessage:
                        en: Approved
                        ar: تمت الموافقة
                      transactionId: TX-69827599
                      transactionDate: 2022-04-13 10:44:46.724000+00:00
                      settlementDate: 2022-04-13
                      amount: 10
                      currency: EGP
                      operation: refund
                      merchantIdentifier: TESTQNBINHOUSE03
                      payload:
                        authorizationResponse:
                          cardSecurityCodeError: M
                          commercialCard: "888"
                          commercialCardIndicator: "3"
                          financialNetworkCode: "777"
                          posData: "1025100006600"
                          posEntryMode: "812"
                          processingCode: "203000"
                          responseCode: "00"
                          stan: "199804"
                          transactionIdentifier: "123456789"
                        gatewayEntryPoint: WEB_SERVICES_API
                        merchant: ""
                        order:
                          amount: 14
                          chargeback:
                            amount: 0
                            currency: EGP
                          creationTime: 2022-04-13 10:39:31.655000+00:00
                          currency: EGP
                          id: 93c799ea-ae6c-485c-bf36-a385acbb8c13
                          lastUpdatedTime: 2022-04-13 10:44:46.764000+00:00
                          merchantAmount: 14
                          merchantCategoryCode: "8211"
                          merchantCurrency: EGP
                          reference: 6228c89970bbfb001898c9fc
                          status: PARTIALLY_REFUNDED
                          totalAuthorizedAmount: 14
                          totalCapturedAmount: 14
                          totalDisbursedAmount: 0
                          totalRefundedAmount: 10
                        response:
                          acquirerCode: "00"
                          cardSecurityCode:
                            acquirerCode: M
                            gatewayCode: MATCH
                          gatewayCode: APPROVED
                        result: SUCCESS
                        sourceOfFunds:
                          provided:
                            card:
                              brand: ""
                              expiry:
                                month: "6"
                                year: "22"
                              fundingMethod: CREDIT
                              number: 512345******2346
                              scheme: MASTERCARD
                              storedOnFile: NOT_STORED
                          type: CARD
                        timeOfLastUpdate: 2022-04-13 10:44:46.764000+00:00
                        timeOfRecord: 2022-04-13 10:44:46.724000+00:00
                        transaction:
                          acquirer:
                            batch: 20220413
                            date: "0413"
                            id: QNBAAIH_S2I
                            merchantId: 79447918
                            settlementDate: 2022-04-13
                            timeZone: "+0200"
                            transactionId: "123456789"
                          amount: 10
                          currency: EGP
                          id: TX-69827599
                          receipt: "210310200874"
                          source: INTERNET
                          stan: "200874"
                          terminal: "80000145"
                          type: REFUND
                        version: "62"
                      cardOrderId: 93c799ea-ae6c-485c-bf36-a385acbb8c13
                      creationDate: 2022-04-13 10:44:46.724000+00:00
                      orderReference: TEST-ORD-37089
                    messages:
                      en: Congratulations! Your refund was successful
                      ar: تهانينا! تمت معاملة استرداد الأموال بنجاح
                    status: SUCCESS
                void:
                  summary: Successful void
                  value:
                    response:
                      apiOperation: VOID
                      operation: void
                      currency: EGP
                      result: SUCCESS
                      status: CANCELLED
                      amount: 1
                      certainty: ESTIMATED
                      chargeback:
                        amount: 0
                        currency: EGP
                      creationTime: 2023-09-14 13:58:45.411000+00:00
                      id: c4e94e5d-456e-477b-9adf-e13500b03cde
                      lastUpdatedTime: 2023-09-14 13:59:42.373000+00:00
                      merchantAmount: 1
                      merchantCategoryCode: "8211"
                      merchantCurrency: EGP
                      reference: "1694699921"
                      totalAuthorizedAmount: 0
                      totalCapturedAmount: 0
                      totalDisbursedAmount: 0
                      totalRefundedAmount: 0
                      authentication: {}
                      paymentMethod:
                        type: card
                        card:
                          maskedCard: 512345******0008
                          cardBrand: Mastercard
                          agreement: null
                          cardHolderName: John Doe
                          expiryMonth: "25"
                          expiryYear: "06"
                          save: null
                          number: 512345******0008
                          nameOnCard: John Doe
                          expiry:
                            month: "25"
                            year: "06"
                          installments: {}
                      metaData:
                        amount: 1
                        currency: EGP
                        redirectMethod: post
                        id: 1694699921
                        auth: true
                        ip: 41.33.72.178
                        merchantWebhook: https://tester-integration.herokuapp.com/invoice-serverWebhook
                      merchantId: MID-2-670
                      order:
                        amount: 1
                        currency: EGP
                        callbackURL: https://tester-integration.herokuapp.com/merchant-redirect
                        systemOrderId: c4e94e5d-456e-477b-9adf-e13500b03cde
                      merchantRedirectUrl: https://tester-integration.herokuapp.com/merchant-redirect?
                      apiKeyId: 6243195989b6bfa3e0286e0e
                      method: card
                      creationDate: 2023-09-14 16:58:44.826000+00:00
                      orderId: c4e94e5d-456e-477b-9adf-e13500b03cde
                      merchantOrderId: "1694699921"
                      orderReference: TEST-ORD-193343485
                      paymentType: ext-internal-hidden-test
                      providerType: mpgs
                      fees:
                        transaction: 0
                        processing: 0
                      bank: qnb
                      interactionSource: ECOMMERCE
                      device: {}
                      transactionId: TX-2670193217984
                      transactionResponseCode: "00"
                      transactionResponseMessage:
                        en: Approved
                        ar: تمت الموافقة
                    status: SUCCESS
                    provider:
                      type: mpgs
                      version: "68"
                capture:
                  summary: Successful capture
                  value:
                    response:
                      apiOperation: CAPTURE
                      operation: capture
                      currency: EGP
                      result: SUCCESS
                      status: CAPTURED
                      amount: 1
                      certainty: ESTIMATED
                      chargeback: {}
                      creationTime: 2023-09-14 11:04:15.460000+00:00
                      id: a08d74e4-aab4-471f-bb73-1e02991b513b
                      lastUpdatedTime: 2023-09-14 11:16:51.876000+00:00
                      merchantAmount: 1
                      merchantCategoryCode: "8211"
                      merchantCurrency: EGP
                      reference: "1694689438"
                      totalAuthorizedAmount: 1
                      totalCapturedAmount: 1
                      totalDisbursedAmount: 0
                      totalRefundedAmount: 0
                      authentication: {}
                      paymentMethod:
                        type: card
                        card:
                          maskedCard: 512345******0008
                          cardBrand: Mastercard
                          agreement: null
                          cardHolderName: John Doe
                          expiryMonth: "25"
                          expiryYear: "06"
                          save: null
                          number: 512345******0008
                          nameOnCard: John Doe
                          expiry:
                            month: "25"
                            year: "06"
                          installments: {}
                      metaData: {}
                      merchantId: MID-2-670
                      order:
                        amount: 1
                        currency: EGP
                        callbackURL: https://tester-integration.herokuapp.com/merchant-redirect
                        systemOrderId: a08d74e4-aab4-471f-bb73-1e02991b513b
                      merchantRedirectUrl: https://tester-integration.herokuapp.com/merchant-redirect?paymentStatus=SUCCESS&,cardDataToken=c2ed8287-ae57-484a-a155-8f62f63c126f&maskedCard=512345******0008
                      apiKeyId: 6243195989b6bfa3e0286e0e
                      provider: mpgs
                      method: card
                      creationDate: 2023-09-14 14:04:14.832000+00:00
                      orderId: a08d74e4-aab4-471f-bb73-1e02991b513b
                      merchantOrderId: "1694689438"
                      orderReference: TEST-ORD-193343469
                      paymentType: ext-internal-hidden-test
                      providerType: mpgs
                      fees:
                        transaction: 0
                        processing: 0
                      bank: qnb
                      interactionSource: ECOMMERCE
                      transactionId: TX-2670193217974
                      transactionResponseCode: "00"
                      transactionResponseMessage:
                        en: Approved
                        ar: تمت الموافقة
                    transactionId: TX-2670193217974
                    messages:
                      en: Approved
                      ar: تمت الموافقة
                    status: SUCCESS
                    provider:
                      type: mpgs
                      version: "68"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/orders:
    servers:
      - url: https://test-fep.kashier.io
        description: Test — no real money moves
    post:
      operationId: payWithToken
      tags:
        - Tokens
      summary: Pay with token
      description: "Creates a new payment request using a saved card token. (The docs show the URL with a trailing slash: /v3/orders/.) The request is authenticated with a Kashier-Hash header (order hash generated with HMAC SHA256 from your backend). With interactionSource: ECOMMERCE and 3DS enabled, the response contains an authentication.redirectUrl you should redirect to for the 3DS page; the final transaction response after 3DS processing is received via webhook. With MOTO, the payment is processed directly."
      security: []
      parameters:
        - $ref: "#/components/parameters/KashierHash"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PayWithTokenRequest"
            examples:
              payWithToken:
                summary: Pay with a saved card token
                value:
                  apiOperation: PAY
                  paymentMethod:
                    type: CARD
                    card:
                      cardToken: "123456789123456789"
                      securityCode: ""
                      enable3DS: true
                  installments:
                    plandId: ""
                  origin:
                    id: ""
                  connectedAccount:
                    merchantId: ""
                  order:
                    reference: ""
                    amount: "1"
                    currency: EGP
                    description: ""
                  customer:
                    reference: ""
                  interactionSource: ECOMMERCE
                  reconciliation:
                    webhookUrl: ""
                    merchantRedirect: ""
                    redirect: true
                  metaData: {}
                  merchantId: ""
                  timestamp: ""
      responses:
        "200":
          description: Payment result. For MOTO (non-3DS) the payment is captured directly. For ECOMMERCE with 3DS, `response.status` is `AUTHENTICATION_INITIATED` and you must redirect the customer to `response.authentication.redirectUrl`; the final transaction response arrives on your webhook.
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: object
                    additionalProperties: true
                  messages:
                    $ref: "#/components/schemas/LocalizedMessage"
                  status:
                    type: string
                  showCaptcha:
                    type: boolean
              examples:
                motoNon3ds:
                  summary: MOTO NON-3DS — captured directly
                  value:
                    response:
                      apiOperation: PAY
                      operation: pay
                      currency: EGP
                      result: SUCCESS
                      status: CAPTURED
                      authenticationStatus: AUTHENTICATION_NOT_IN_EFFECT
                      amount: 100
                      creationTime: 2023-10-16 12:00:49.746000+00:00
                      lastUpdatedTime: 2023-10-16 12:00:50.137000+00:00
                      merchantCurrency: EGP
                      reference: "1697457648576"
                      totalAuthorizedAmount: 100
                      totalCapturedAmount: 100
                      totalDisbursedAmount: 0
                      totalRefundedAmount: 0
                      authentication: {}
                      paymentMethod:
                        type: CARD
                        card:
                          cardBrand: Mastercard
                          storedOnFile: TO_BE_STORED
                          number: 512345******2346
                          nameOnCard: Mohamed Khaled
                          expiry:
                            month: "12"
                            year: "25"
                          cardToken: 9d8332cb-6195-40ea-aed0-86c3aa60fbaa
                      metaData:
                        customerName: Noura Mosaad
                        merchantWebhook: http://40fb-156-210-144-77.ngrok.io/paymentWebhook
                        redirect: true
                      customer:
                        reference: "01163550555"
                      timestamp: 2022-12-15 13:54:01.606000+00:00
                      reconciliation:
                        webhookUrl: https://your-call-back-url.com
                        merchantRedirect: https://your-call-back-url.com?paymentStatus=SUCCESS&cardDataToken=9d8332cb-6195-40ea-aed0-86c3aa60fbaa&maskedCard=512345******2346&merchantOrderId=1697457648576&orderId=27a86389-83be-4107-b51d-33ad767078a2&cardBrand=Mastercard&orderReference=TEST-ORD-96353&transactionId=TX-2498912113&amount=100&currency=EGP&mode=test&signature=dde46b3a9b4fc05478f6a35dd62f82a2a3c0b6ace73997dfdcebda0abd7b8cc3
                        redirect: true
                      merchantId: MID-24-989
                      order:
                        amount: 100
                        currency: EGP
                        callbackURL: https://your-call-back-url.com
                        systemOrderId: 27a86389-83be-4107-b51d-33ad767078a2
                      merchantRedirectUrl: https://your-call-back-url.com?paymentStatus=SUCCESS&cardDataToken=9d8332cb-6195-40ea-aed0-86c3aa60fbaa&maskedCard=512345******2346&merchantOrderId=1697457648576&orderId=27a86389-83be-4107-b51d-33ad767078a2&cardBrand=Mastercard&orderReference=TEST-ORD-96353&transactionId=TX-2498912113&amount=100&currency=EGP&mode=test&signature=dde46b3a9b4fc05478f6a35dd62f82a2a3c0b6ace73997dfdcebda0abd7b8cc3
                      apiKeyId: 5d0003fc77c68a0018b05a6f
                      method: card
                      creationDate: 2023-10-16 15:00:48.946000+00:00
                      orderId: 27a86389-83be-4107-b51d-33ad767078a2
                      merchantOrderId: "1697457648576"
                      orderReference: TEST-ORD-96353
                      paymentType: ext-default
                      interactionSource: MOTO
                      transactionId: TX-2498912113
                      transactionResponseCode: "00"
                      transactionResponseMessage:
                        en: Approved
                        ar: تمت الموافقة
                    messages:
                      en: Approved
                      ar: تمت الموافقة
                    status: SUCCESS
                    showCaptcha: false
                ecommerce3ds:
                  summary: ECOMMERCE with 3DS — authentication initiated (redirectHtml/redirectUrl abridged)
                  value:
                    response:
                      apiOperation: PAY
                      operation: 3dsecure_verify
                      currency: EGP
                      result: SUCCESS
                      status: AUTHENTICATION_INITIATED
                      authenticationStatus: AUTHENTICATION_AVAILABLE
                      creationTime: 2023-10-16 11:53:51.094000+00:00
                      lastUpdatedTime: 2023-10-16 11:53:51.059000+00:00
                      totalAuthorizedAmount: 0
                      totalCapturedAmount: 0
                      totalRefundedAmount: 0
                      authentication:
                        channel: PAYER_BROWSER
                        purpose: PAYMENT_TRANSACTION
                        redirectHtml: <div id="initiate3dsSimpleRedirect" xmlns="http://www.w3.org/1999/html"> <iframe id="methodFrame" name="methodFrame" height="100" width="200"> </iframe> <form id="initiate3dsSimpleRedirectForm" method="POST" action="https://mtf.gateway.mastercard.com/acs/mastercard/v2/method" target="methodFrame"> <input type="hidden" name="threeDSMethodData" value="eyJ0aHJlZURTTWV0aG9kTm90aWZpY2F0aW9uVVJMIjoi..." /> </form> <script id="initiate-authentication-script"> var e=document.getElementById("initiate3dsSimpleRedirectForm"); if (e) { e.submit(); if (e.parentNode !== null) { e.parentNode.removeChild(e); } } </script> </div>
                        version: 3DS2
                        redirectUrl: https://checkout.staging.payformance.io/3dsRedirect/bdcab401-d3eb-4cb1-80a7-6bc59f595961?methodUrl=https://mtf.gateway.mastercard.com/acs/mastercard/v2/method&methodPostData=eyJ0aHJlZURTTWV0aG9kTm90aWZpY2F0aW9uVVJMIjoi...&mode=test
                      paymentMethod:
                        type: CARD
                        card:
                          cardBrand: Mastercard
                          storedOnFile: TO_BE_STORED
                          number: 512345******2346
                          nameOnCard: Mohamed Khaled
                          expiry:
                            month: "12"
                            year: "25"
                          cardToken: 9d8332cb-6195-40ea-aed0-86c3aa60fbaa
                      metaData:
                        customerName: Noura Mosaad
                        merchantWebhook: http://40fb-156-210-144-77.ngrok.io/paymentWebhook
                        redirect: true
                      customer:
                        reference: "01163550555"
                      timestamp: 2022-12-15 13:54:01.606000+00:00
                      reconciliation:
                        webhookUrl: https://your-call-back-url.com
                        merchantRedirect: https://your-call-back-url.com?&signature=
                        redirect: true
                      merchantId: MID-24-989
                      order:
                        amount: 100
                        currency: EGP
                        callbackURL: https://your-call-back-url.com
                        systemOrderId: bdcab401-d3eb-4cb1-80a7-6bc59f595961
                      description: order description
                      merchantRedirectUrl: https://your-call-back-url.com?&signature=
                      apiKeyId: 5d0003fc77c68a0018b05a6f
                      method: card
                      creationDate: 2023-10-16 14:53:50.593000+00:00
                      orderId: bdcab401-d3eb-4cb1-80a7-6bc59f595961
                      merchantOrderId: "1697457230044"
                      orderReference: TEST-ORD-96349
                      paymentType: ext-default
                      interactionSource: ECOMMERCE
                      transactionId: TX-2498912112
                      transactionResponseCode: AUTHENTICATION_IN_PROGRESS
                      transactionResponseMessage:
                        en: Authentication in progress
                        ar: المصادقة قيد التقدم
                    messages:
                      en: Authentication in progress
                      ar: المصادقة قيد التقدم
                    status: SUCCESS
                    showCaptcha: false
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/refund/{orderId}:
    put:
      operationId: refundOrder
      tags:
        - Order operations
      summary: Refund an order
      description: |
        Repays your customer, in part or in full, from your available Kashier balance.

        **This is the same operation as `PUT /v3/orders/{orderId}` with
        `apiOperation: REFUND`, one hop closer.** The checkout host (`test-fep.kashier.io`)
        applies no authentication of its own — it reads `apiOperation`, rewrites the path to
        this one, and forwards your request here unchanged, credential and all. So both routes
        end at the same enforcement point and behave identically; pick whichever fits your
        integration. If you already talk to the checkout host for payments, keep using
        `PUT /v3/orders/{orderId}` and let it route. If your refunds are issued from a
        back-office service that only knows the dashboard host, call this directly and skip
        the hop.

        Send your **secret key** in the `Authorization` header. The key's role must carry the
        refund permission — a role that can read transactions but not refund them fails here
        with a 401, not a 403.

        Refund outcomes: `SUCCESS` (the processor took it), `PENDING` (initiated, waiting on
        the processor), `FAILURE` (it could not be processed, and your account is credited
        back the refund amount). A refund cannot exceed the original transaction amount, and
        it draws on your available balance — pending balance does not count.
      security:
        - secretKey: []
      parameters:
        - name: orderId
          in: path
          required: true
          description: Kashier's order id.
          schema:
            type: string
      requestBody:
        required: true
        description: The same body the checkout host forwards for a refund.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RefundRequest"
            examples:
              partialRefund:
                summary: Refund part of the order
                value:
                  apiOperation: REFUND
                  reason: Customer returned one item
                  transaction:
                    amount: 3
      responses:
        "200":
          description: The refund result. Read `response.status` for the resulting order state.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrderOperationResult"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/void/{orderId}:
    put:
      operationId: voidOrder
      tags:
        - Order operations
      summary: Void an order
      description: |
        Cancels a transaction on the order before it settles — the clean undo while the money
        has not actually moved yet. Use it to cancel a pay, an authorization, a capture or a
        refund; pass the `targetTransactionId` you got back from the transaction you are
        cancelling. Once the transaction has settled, void no longer applies and you need a
        refund instead.

        **The same operation as `PUT /v3/orders/{orderId}` with `apiOperation: VOID`.** The
        checkout host forwards to this exact route without applying any authentication of its
        own, so the two are interchangeable.

        Send your **secret key** in the `Authorization` header. Like refund, this requires the
        refund permission on the key's role.
      security:
        - secretKey: []
      parameters:
        - name: orderId
          in: path
          required: true
          description: Kashier's order id.
          schema:
            type: string
      requestBody:
        required: true
        description: The same body the checkout host forwards for a void.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/VoidRequest"
            examples:
              void:
                value:
                  apiOperation: VOID
                  transaction:
                    amount: 3
                    targetTransactionId: TX-1902526801
      responses:
        "200":
          description: The void result. A successful void leaves the order at `CANCELLED`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrderOperationResult"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/capture/{orderId}:
    put:
      operationId: captureOrder
      tags:
        - Order operations
      summary: Capture an authorized order
      description: |
        Takes the money on an order you previously authorized, fully or partially. Capture
        before the hold expires — 7 or 30 days depending on your configuration — or the
        authorization lapses and the funds go back to the customer on their own. To release
        an authorization deliberately, use void rather than letting it expire.

        **The same operation as `PUT /v3/orders/{orderId}` with `apiOperation: CAPTURE`.** The
        checkout host forwards to this exact route without authenticating, so the two are
        interchangeable.

        Authorize-and-capture must be switched on for your account — contact your account
        manager or customer success if a capture is rejected as unsupported.

        Send your **secret key** in the `Authorization` header. Unlike refund and void, capture
        does not require the refund permission.
      security:
        - secretKey: []
      parameters:
        - name: orderId
          in: path
          required: true
          description: Kashier's order id.
          schema:
            type: string
      requestBody:
        required: true
        description: The same body the checkout host forwards for a capture.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CaptureRequest"
            examples:
              capture:
                value:
                  apiOperation: CAPTURE
                  transaction:
                    amount: 3
      responses:
        "200":
          description: The capture result. A successful capture leaves the order at `CAPTURED`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrderOperationResult"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/reversal/{orderId}:
    put:
      operationId: reverseOrder
      tags:
        - Order operations
      summary: Reverse an order
      description: |
        Reverses a transaction at the rail level. This is the card-present and BNPL undo — for
        an ordinary online card sale reach for void (before settlement) or refund (after)
        instead, which is almost always what you want.

        **The same operation as `PUT /v3/orders/{orderId}` with `apiOperation: REVERSAL`.** The
        checkout host forwards to this exact route without authenticating.

        Send your **secret key** in the `Authorization` header.

        > Kashier has not published the request fields for reversal beyond `apiOperation`, so
        > only that one is described here. Anything else you send is forwarded as-is.
      security:
        - secretKey: []
      parameters:
        - name: orderId
          in: path
          required: true
          description: Kashier's order id.
          schema:
            type: string
      requestBody:
        required: true
        description: The same body the checkout host forwards for a reversal.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ReversalRequest"
            examples:
              reversal:
                value:
                  apiOperation: REVERSAL
      responses:
        "200":
          description: The reversal result. A successful reversal leaves the order at `REVERSED`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrderOperationResult"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/cards/customer:
    servers:
      - url: https://test-fep.kashier.io
        description: Test — no real money moves
    get:
      operationId: retrieveTokens
      tags:
        - Tokens
      summary: Retrieve tokens
      description: Retrieves a customer's saved card tokens and info. The request is validated with a Kashier-Hash header — an HMAC SHA256 of the path /?tokenization={mid}.{customerReference} keyed with your Payment API Key (not the Secret Key). Use only those parameters in the hash creation; don't add extra parameters. A customer with no saved card returns 400 with "There are no cards with this token" — an empty result, not an auth failure.
      security: []
      parameters:
        - $ref: "#/components/parameters/KashierHash"
        - name: customerReference
          in: query
          required: true
          description: your customer Id
          schema:
            type: string
        - name: merchantId
          in: query
          required: true
          description: your merchant Id
          schema:
            type: string
      responses:
        "200":
          description: The customer's saved card tokens.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  messages:
                    $ref: "#/components/schemas/LocalizedMessage"
                  response:
                    type: object
                    properties:
                      paymentMethods:
                        type: array
                        items:
                          $ref: "#/components/schemas/SavedPaymentMethod"
              examples:
                tokens:
                  value:
                    status: SUCCESS
                    messages:
                      en: Card tokens retrieved successfully
                      ar: Card tokens retrieved successfully
                    response:
                      paymentMethods:
                        - type: CARD
                          card:
                            expiry:
                              month: "06"
                              year: "25"
                            number: 5123********0008
                            nameOnCard: John Doe
                            cardToken: 7a5e3c72-61d9-4ebf-88b9-27dc0f77b638
                          customer:
                            reference: "01163550555"
                        - type: CARD
                          card:
                            expiry:
                              month: "12"
                              year: "25"
                            number: 5123********2346
                            nameOnCard: Mohamed Khaled
                            cardToken: 9d8332cb-6195-40ea-aed0-86c3aa60fbaa
                          customer:
                            reference: "01163550555"
                            customerIp: ""
                        - type: CARD
                          card:
                            expiry:
                              month: "12"
                              year: "25"
                            number: 5506********0305
                            nameOnCard: Mohamed Khaled
                            cardToken: 886f122a-2d9e-4a35-8be8-79fdd88b9ffd
                          customer:
                            reference: "01163550555"
                        - type: CARD
                          card:
                            expiry:
                              month: "12"
                              year: "25"
                            number: 5506********0347
                            nameOnCard: Hossam El-Kassas
                            cardToken: a6791b9e-78ea-46e0-bc51-bef7d85b8c28
                          customer:
                            reference: "01163550555"
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/cards/tokens/{token}:
    servers:
      - url: https://test-fep.kashier.io
        description: Test — no real money moves
    delete:
      operationId: deleteToken
      tags:
        - Tokens
      summary: Delete token
      description: Removes a saved card token — useful for removing an expired card, a new card, or a stolen card's old information. The request is validated with a Kashier-Hash header — an HMAC SHA256 hash of the path /?tokenization={mid}.{reference} generated from your backend with your secret. Use only those parameters in the hash creation; don't add extra parameters.
      security: []
      parameters:
        - $ref: "#/components/parameters/KashierHash"
        - name: token
          in: path
          required: true
          description: the card token you have saved before
          schema:
            type: string
        - name: customerReference
          in: query
          required: true
          description: your customer Id
          schema:
            type: string
        - name: merchantId
          in: query
          required: true
          description: your merchant Id
          schema:
            type: string
      responses:
        "200":
          description: Token deleted successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  messages:
                    $ref: "#/components/schemas/LocalizedMessage"
                  response:
                    type: object
                    properties:
                      token:
                        type: string
                      merchantId:
                        type: string
                      customerReference:
                        type: string
              examples:
                deleted:
                  value:
                    status: SUCCESS
                    messages:
                      en: Token deleted successfully.
                      ar: Token deleted successfully.
                    response:
                      token: 7a5e3c72-61d9-4ebf-88b9-27dc0f77b638
                      merchantId: MID-24-989
                      customerReference: "01163550555"
        "400":
          $ref: "#/components/responses/BadRequest"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    get:
      operationId: getToken
      tags:
        - Tokens
      summary: Get token
      description: |-
        Retrieves a single saved card token by its value, returning the masked card number, expiry, and cardholder name. Use it to show a customer which card is on file before charging it, or to check that a token is still valid.
        To list every token a customer has saved, use [Retrieve tokens](#operation/retrieveTokens) instead.
        The request is validated with a Kashier-Hash header — an HMAC SHA256 hash of the path /?tokenization={merchantId}.{customerReference} generated from your backend with your secret. Use only those parameters in the hash creation; don't add extra parameters.
      security: []
      parameters:
        - $ref: "#/components/parameters/KashierHash"
        - name: token
          in: path
          required: true
          description: the card token you have saved before
          schema:
            type: string
        - name: merchantId
          in: query
          required: true
          description: your merchant Id
          schema:
            type: string
        - name: customerReference
          in: query
          required: false
          description: your customer Id
          schema:
            type: string
      responses:
        "200":
          description: The saved card token.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TokenizationGetTokenResponse"
              examples:
                token:
                  value:
                    status: SUCCESS
                    messages:
                      en: Card tokens is retrieved successfully
                      ar: Card tokens is retrieved successfully
                    response:
                      paymentMethod:
                        type: CARD
                        card:
                          expiry:
                            month: "12"
                            year: "25"
                          number: 512345********2346
                          nameOnCard: John Doe
                          cardToken: 7a5e3c72-61d9-4ebf-88b9-27dc0f77b638
                          type: perm
        "404":
          description: The token was not found for this merchant, or the `merchantId` is not a valid Kashier merchant id.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TokenizationError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/tokenization/tokens:
    get:
      operationId: listSavedTokens
      tags:
        - Tokens
      summary: List saved card tokens
      description: |
        Lists every card token saved on your merchant account, with the agreement each one was
        saved under.

        This is the account-wide view, and it is a different endpoint from the customer-scoped
        `GET /v3/cards/customer` read on the checkout host: this one lives on the dashboard host
        and authenticates with your **secret key** in `Authorization`, with no `Kashier-Hash`.
        Reach for it to audit or reconcile what you hold on file; reach for the customer read
        when you are rendering someone's saved cards at checkout.

        Card numbers come back masked. There is no way to retrieve a full PAN from Kashier.
      security:
        - secretKey: []
      parameters:
        - name: page
          in: query
          required: false
          description: Current page number.
          schema:
            type: integer
          example: 1
        - name: limit
          in: query
          required: false
          description: Number of tokens per page.
          schema:
            type: integer
          example: 20
        - name: sortType
          in: query
          required: false
          description: Sort direction — `-1` newest first, `1` oldest first.
          schema:
            type: integer
            enum:
              - 1
              - -1
      responses:
        "200":
          description: The saved tokens.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/SavedCardToken"
                  pagination:
                    $ref: "#/components/schemas/Pagination"
              examples:
                tokens:
                  value:
                    message: success
                    data:
                      - cardHolderName: Hegab
                        token: a559ecc6-11a2-431a-b40c-c10df4e7a9df
                        agreementId: 65d4717c2b2c17002469e463
                        customerReference: "12345"
                        agreementType: UNSCHEDULED
                        agreementExpiry: N/A
                        cardNumber: 5123********2346
                      - cardHolderName: TEST
                        token: c34faed2-b1e3-4ebf-99ab-992ef2f70d61
                        agreementId: 66043d39ec69ad0024b9c012
                        customerReference: "123456"
                        agreementType: RECURRING
                        agreementExpiry: 2024-11-14T15:47:29.448Z
                        cardNumber: 5078********5581
                    pagination:
                      total: 2
                      limit: 20
                      page: 1
                      pages: 1
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/tokenization/tokens/export:
    get:
      operationId: exportSavedTokens
      tags:
        - Tokens
      summary: Export saved card tokens
      description: |
        Returns the saved-token list as a downloadable file rather than JSON — the same data as
        List saved card tokens, in a form you can hand to finance or diff against your own
        records.

        Because the response is a file, not JSON, the "Try it" panel will show you raw bytes
        rather than a formatted body.
      security:
        - secretKey: []
      responses:
        "200":
          description: The export file. Your browser downloads it rather than displaying it.
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
        "400":
          $ref: "#/components/responses/BadRequest"
  /v3/payment/tokenization/tokens/{token}:
    delete:
      operationId: deleteSavedToken
      tags:
        - Tokens
      summary: Delete a saved card token
      description: |
        Removes a saved card token. Any recurring charge that still references it fails
        afterwards, so cancel the billing arrangement on your side first.

        Deleting the token is also how you honour a customer asking you to stop storing their
        card. This is the dashboard-host, secret-key counterpart of
        `DELETE /v3/cards/tokens/{token}` on the checkout host, which uses a `Kashier-Hash`
        instead.
      security:
        - secretKey: []
      parameters:
        - name: token
          in: path
          required: true
          description: The card token to delete, from List saved card tokens.
          schema:
            type: string
      responses:
        "200":
          description: The token was deleted.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
              examples:
                deleted:
                  value:
                    message: success
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
        "400":
          $ref: "#/components/responses/BadRequest"
  /merchant/installments/banks/plans:
    get:
      operationId: getInstallmentBanks
      tags:
        - Installments
      summary: Get available banks
      description: Retrieves the installment-enabled banks (with their plans, BIN ranges, and terms & conditions) for a given merchant and product price. Step 1 of retrieving installment plans.
      security: []
      parameters:
        - name: mid
          in: query
          required: true
          description: Merchant account number or merchant ID
          schema:
            type: string
        - name: amount
          in: query
          required: true
          description: the price of the product you want to get installments for
          schema:
            type: string
      responses:
        "200":
          description: Installment enabled banks retrieved successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: object
                    properties:
                      banks:
                        type: array
                        items:
                          $ref: "#/components/schemas/InstallmentBank"
                      allowValu:
                        type: boolean
                      allowFawry:
                        description: Deprecated. Fawry is no longer supported and has no payment route.
                        type: boolean
                      allowOcto:
                        description: Octo BNPL is available — set when the merchant has the provider or the `octo` payment-channel method.
                        type: boolean
                      allowSouhoola:
                        description: Souhoola BNPL is available — set from the `souhoola` payment-channel method.
                        type: boolean
                  messages:
                    $ref: "#/components/schemas/LocalizedMessage"
                  status:
                    type: string
              examples:
                banks:
                  summary: One bank shown (docs example lists six banks; abridged)
                  value:
                    response:
                      banks:
                        - logoUrl: https://static.kashier.io/financial-institution/fiLogo88.67764148407942
                          bankNameEn: Abu Dhabi Islamic Bank
                          bankNameAr: مصرف أبوظبي الإسلامي
                          bankAbbreviation: ADIB
                          banknSystemID: FI-13
                          planFinancing: 1
                          plans:
                            - planFinancing: true
                              bankId: 63fca87d0c82af705635fabb
                          termsAndConditions:
                            termsAndConditionsEn: https://www.adib.eg/personal-banking/adib-cards/cardsoffer
                            termsAndConditionsAr: https://www.adib.eg/arabic/personal-banking/adib-cards/cardsoffer
                          minimunInstallmentAmount: 10
                          binRanges:
                            - _id: 650c250f4bd0150013b9bec5
                              prefix: "548457"
                              product: Gold Mastercard
                              range:
                                from: "0000"
                                to: "9999"
                            - _id: 650c250f4bd0150013b9bec6
                              prefix: "524524"
                              product: Titanium MasterCard
                              range:
                                from: "0000"
                                to: "9999"
                            - _id: 650c250f4bd0150013b9bec7
                              prefix: "513896"
                              product: Platinum MasterCard
                              range:
                                from: "0000"
                                to: "9999"
                      allowValu: true
                      allowFawry: true
                      allowOcto: false
                      allowSouhoola: false
                    messages:
                      en: Installment enabled banks retrieved successfully.
                      ar: Installment enabled banks retrieved successfully.
                    status: SUCCESS
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /merchant/installments/plans:
    get:
      operationId: getInstallmentPlans
      tags:
        - Installments
      summary: Get plans for specific bank
      description: Retrieves the installment plans for a specific bank (selected by fiId, the banknSystemID retrieved from the "Get available banks" step). After a successful response, the monthly amount for every plan is in the Installment amount per month parameter. Step 2 of retrieving installment plans.
      security: []
      parameters:
        - name: mid
          in: query
          required: true
          description: Merchant account number or merchant ID
          schema:
            type: string
        - name: amount
          in: query
          required: true
          description: the price of the product you want to get installment plans for
          schema:
            type: string
        - name: currency
          in: query
          required: true
          description: the currency of the product
          schema:
            type: string
        - name: fiId
          in: query
          required: true
          description: banknSystemID for the selected bank, retrieved from the first step
          schema:
            type: string
      responses:
        "200":
          description: Installment plans retrieved successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: object
                    properties:
                      bankPlans:
                        type: array
                        items:
                          type: object
                          additionalProperties: true
                  messages:
                    $ref: "#/components/schemas/LocalizedMessage"
                  status:
                    type: string
              examples:
                plans:
                  summary: ADIB plans for a 10000 EGP product (Supported BINs abridged)
                  value:
                    response:
                      bankPlans:
                        - Logo URL: https://static.kashier.io/financial-institution/fiLogo88.67764148407942
                          Terms & Conditions url EN: https://www.adib.eg/personal-banking/adib-cards/cardsoffer
                          Terms & Conditions url AR: https://www.adib.eg/arabic/personal-banking/adib-cards/cardsoffer
                          Bank Name EN: Abu Dhabi Islamic Bank
                          Bank Name AR: مصرف أبوظبي الإسلامي
                          Bank Abbreviation: ADIB
                          Bank system ID: FI-13
                          Minimum installment amount: 10
                          Supported BINs:
                            - Prefix: "548457"
                              From: "0000"
                              To: "9999"
                              Product Name: Gold Mastercard
                            - Prefix: "524524"
                              From: "0000"
                              To: "9999"
                              Product Name: Titanium MasterCard
                          plans:
                            - Plan Financing: true
                              Merchant Plan ID: INSPLAN-53
                              Name EN: Pay with installments on 3 months
                              Name AR: تقسيط على 3 شهور
                              Duration: 3
                              Full Amount / Original amount: "10000.00"
                              Bank Interest Rate: "7.00"
                              Installment amount per month: "3566.67"
                              Authorization Amount: "10000.00"
                            - Plan Financing: true
                              Merchant Plan ID: INSPLAN-54
                              Name EN: Pay with installments on 6 months
                              Name AR: تقسيط على 6 شهور
                              Duration: 6
                              Full Amount / Original amount: "10000.00"
                              Bank Interest Rate: "8.14"
                              Installment amount per month: "1802.33"
                              Authorization Amount: "10000.00"
                            - Plan Financing: true
                              Merchant Plan ID: INSPLAN-55
                              Name EN: Pay with installments on 9 months
                              Name AR: تقسيط على 9 شهور
                              Duration: 9
                              Full Amount / Original amount: "10000.00"
                              Bank Interest Rate: "10.00"
                              Installment amount per month: "1222.22"
                              Authorization Amount: "10000.00"
                            - Plan Financing: true
                              Merchant Plan ID: INSPLAN-56
                              Name EN: Pay with installments on 12 months
                              Name AR: تقسيط على 12 شهور
                              Duration: 12
                              Full Amount / Original amount: "10000.00"
                              Bank Interest Rate: "12.15"
                              Installment amount per month: "934.58"
                              Authorization Amount: "10000.00"
                            - Plan Financing: true
                              Merchant Plan ID: INSPLAN-57
                              Name EN: Pay with installments on 18 months
                              Name AR: تقسيط على 18 شهور
                              Duration: 18
                              Full Amount / Original amount: "10000.00"
                              Bank Interest Rate: "15.95"
                              Installment amount per month: "644.17"
                              Authorization Amount: "10000.00"
                            - Plan Financing: true
                              Merchant Plan ID: INSPLAN-58
                              Name EN: Pay with installments on 24 months
                              Name AR: تقسيط على 24 شهور
                              Duration: 24
                              Full Amount / Original amount: "10000.00"
                              Bank Interest Rate: "20.40"
                              Installment amount per month: "501.67"
                              Authorization Amount: "10000.00"
                            - Plan Financing: true
                              Merchant Plan ID: INSPLAN-59
                              Name EN: Pay with installments on 36 months
                              Name AR: تقسيط على 36 شهور
                              Duration: 36
                              Full Amount / Original amount: "10000.00"
                              Bank Interest Rate: "26.87"
                              Installment amount per month: "352.42"
                              Authorization Amount: "10000.00"
                    messages:
                      en: Installment plans retrieved successfully
                      ar: Installment plans retrieved successfully
                    status: SUCCESS
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/account:
    get:
      operationId: getAccountInfo
      tags:
        - Payouts
      summary: Get account info
      description: Retrieves account info — balances, payout method, and last-transfer details for the merchant identified by the secret key.
      security:
        - secretKey: []
      responses:
        "200":
          description: Account info with balances and payout method.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
                  pagination:
                    $ref: "#/components/schemas/Pagination"
              examples:
                account:
                  value:
                    message: success
                    data:
                      - _id: 65ce339471eee2b3302a791e
                        totalBalance: 228366.11999999985
                        availableBalance: 228366.11999999985
                        allowedNegativeBalance: 0
                        merchantId: MID-1007-931
                        accountId: ACC-1007-931-01
                        createdAt: 2024-02-15 15:53:56.947000+00:00
                        updatedAt: 2024-11-20 18:05:15.432000+00:00
                        merchantName: kashier store
                        payoutMethod:
                          method: bankAccount
                          payoutFields:
                            bankName: AAIB
                            bankBranch: Tanta
                            accountHolderName: Ahmed wageeh
                            accountNumber: "010001000"
                            branchCode: "3"
                        isIncludeInBulkTransfer: false
                        lastTransfer: 1000
                        totalBalanceBeforeLastTransfer: 1000
                        lastTransferDate: 2024-05-08 11:19:15.656000+00:00
                    pagination:
                      total: 1
                      limit: 20
                      page: 1
                      pages: 1
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/transfers:
    get:
      operationId: listTransfers
      tags:
        - Payouts
      summary: List all transfers
      description: Lists all payout transfers, with pagination.
      security:
        - secretKey: []
      parameters:
        - name: sortType
          in: query
          description: Sorting direction.
          schema:
            type: string
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
      responses:
        "200":
          description: The transfers list with per-batch status counts and pagination info.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      inProgressTransfersCount:
                        type: integer
                      transfers:
                        type: array
                        items:
                          $ref: "#/components/schemas/TransferListItem"
                  pagination:
                    $ref: "#/components/schemas/Pagination"
              examples:
                transfers:
                  summary: First transfers of the docs example (list abridged)
                  value:
                    message: success
                    data:
                      inProgressTransfersCount: 28
                      transfers:
                        - merchantId: MID-1007-931
                          storeName: kashier store
                          amount: 100
                          id: TRS-1007931103
                          method: wallet
                          createdAt: 2024-11-20 18:05:15.442000+00:00
                          initiatedCount: 0
                          inTransitCount: 1
                          transferredCount: 0
                          failedCount: 0
                          transfersCount: 1
                          status: IN_TRANSIT
                          name: AHmed daoud
                        - merchantId: MID-1007-931
                          storeName: kashier store
                          amount: 100
                          id: TRS-1007931102
                          method: card
                          createdAt: 2024-11-20 18:04:39.054000+00:00
                          initiatedCount: 0
                          inTransitCount: 1
                          transferredCount: 0
                          failedCount: 0
                          transfersCount: 1
                          status: IN_TRANSIT
                          name: ahmed
                        - merchantId: MID-1007-931
                          storeName: kashier store
                          amount: 100
                          id: TRS-1007931100
                          method: bank
                          createdAt: 2024-11-20 13:15:49.224000+00:00
                          initiatedCount: 0
                          inTransitCount: 0
                          transferredCount: 1
                          failedCount: 0
                          transfersCount: 1
                          status: TRANSFERRED
                          name: November payouts
                        - merchantId: MID-1007-931
                          storeName: kashier store
                          amount: 100
                          id: TRS-100793199
                          method: bank
                          createdAt: 2024-11-20 13:10:43.829000+00:00
                          initiatedCount: 0
                          inTransitCount: 0
                          transferredCount: 0
                          failedCount: 1
                          transfersCount: 1
                          status: FAILED
                          name: AHmed dswg
                    pagination:
                      total: 103
                      limit: 20
                      page: 1
                      pages: 6
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/transfers/{transferId}:
    get:
      operationId: getTransferDetails
      tags:
        - Payouts
      summary: Get transfer details
      description: Retrieves the details of a payout transfer, including its status history and fees.
      security:
        - secretKey: []
      parameters:
        - name: transferId
          in: path
          required: true
          description: The transfer id (e.g., `TRS-1007931100`).
          schema:
            type: string
      responses:
        "200":
          description: The transfer details.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
              examples:
                transfer:
                  value:
                    amount: 100
                    method: bank
                    recipientName: Ahmed Hassan
                    recipientBank: ADIB
                    recipientNumber: xxxxxxxxxxxxx141
                    transferId: TRS-1007931100
                    status: TRANSFERRED
                    merchantId: MID-xxx-xxx
                    merchantDetails:
                      email: owner@merchant-example.com
                      businessEmail: billing@merchant-example.com
                      storeName: kashier store
                    createdBy:
                      id: 640ef8f8ae16f9001ab269c9
                      name: Sara Ahmed
                      email: owner@merchant-example.com
                    batch:
                      _id: 673de105937e00001236fd71
                      name: November payouts
                      id: TRS-1007931100
                      method: bank
                      transfersCount: 1
                    history:
                      - _id: 673de105937e00001236fd72
                        status: INITIATED
                        date: 2024-11-20 13:15:49.186000+00:00
                      - _id: 673de105937e00001236fd75
                        status: IN_TRANSIT
                        date: 2024-11-20 13:15:49.238000+00:00
                        response:
                          status: SUCCESS
                          transactionResponseCode: "8000"
                          transactionResponseMessage:
                            en: Received and Validated Successfully
                            ar: تم الاستلام والتحقق بنجاح
                      - _id: 673e0b50937e00001236fd9b
                        status: TRANSFERRED
                        date: 2024-11-20 16:16:16.752000+00:00
                        response:
                          status: SUCCESS
                          transactionResponseCode: "8222"
                          transactionResponseMessage:
                            en: Settled
                            ar: تم التسوية
                    __v: 0
                    createdAt: 2024-11-20 13:15:49.224000+00:00
                    updatedAt: 2024-11-20 16:16:16.752000+00:00
                    fees:
                      PCC_selling_rate: 3
                      PCC_selling_flat: 4
                      total_selling_rate: "3.00"
                      total_selling_fees: "7.00"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/transfers/fee-inquiry:
    post:
      operationId: feeInquiry
      tags:
        - Payouts
      summary: Fees inquiry
      description: Inquires about the fees for one or more prospective transfers.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - transfers
              properties:
                transfers:
                  type: array
                  description: 'it is an array of objects, you need to provide {"transfers": [{"amount": "100","method": "wallet" }]}'
                  items:
                    type: object
                    properties:
                      amount:
                        type: string
                        description: transfer amount that you want to inquire about its fees
                      method:
                        type: string
                        description: use card, wallet, bank or instant wallet for different methods
                        enum:
                          - card
                          - wallet
                          - bank
                          - instant wallet
            examples:
              feeInquiry:
                value:
                  transfers:
                    - amount: "100"
                      method: wallet
      responses:
        "200":
          description: The processing fee and total amount due for the requested transfer(s).
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      amount:
                        type: string
                      processingFee:
                        type: string
                      totalAmountDue:
                        type: string
              examples:
                fees:
                  value:
                    message: success
                    data:
                      amount: "100.00"
                      processingFee: "3.42"
                      totalAmountDue: "103.42"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/transfers/single:
    servers:
      - url: https://test-fep.kashier.io
        description: Test — no real money moves
    post:
      operationId: createTransfer
      tags:
        - Payouts
      summary: Create transfer
      description: Creates a single payout transfer.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - amount
                - method
                - recipientName
                - recipientNumber
              properties:
                amount:
                  type: number
                  description: the amount of the transfer
                method:
                  type: string
                  description: the method of the transfer, it can be wallet, card, bank or instant wallet
                  enum:
                    - wallet
                    - card
                    - bank
                    - instant wallet
                recipientName:
                  type: string
                  description: the name of the person who is receiving the transfer, sent to him by the sender. Between 3 and 70 characters.
                merchantTransferId:
                  type: string
                  description: It refers to a unique identifier assigned by a merchant for a specific transaction.
                recipientBank:
                  type: string
                  description: The recipient's bank, as an uppercase Kashier bank abbreviation (for example `CIB`, `NBE`, `ADIB`). Required for the `bank` and `card` methods and ignored for the others, which return it as `null`. The accepted values are listed in the bank abbreviations sheet linked from the [Payouts guide](/docs/payouts#bank-codes).
                recipientNumber:
                  type: string
                  description: >-
                    The recipient's account identifier, 1-34 characters. For `wallet` and
                    `instant wallet` it must be an Egyptian mobile number matching
                    `^(010|011|012|015)\d{8}$`. For `bank` it is the recipient's account
                    number, validated on length only. For `card` it identifies the
                    recipient, not the card — the card itself travels in `cardToken`.
                cardToken:
                  type: string
                  description: The tokenized payout card. Required when `method` is `card`, and supplied by you — Kashier does not derive it from a card number, and no field on this endpoint accepts a raw PAN. Ask your account manager how payout card tokens are issued for your account.
            examples:
              wallet:
                summary: Wallet payout — no recipientBank
                value:
                  amount: 10
                  method: wallet
                  recipientName: Jhon Doe
                  merchantTransferId: transfer12349
                  recipientNumber: "01555539512"
              bank:
                summary: Bank payout — recipientBank required
                value:
                  amount: 250
                  method: bank
                  recipientName: Jhon Doe
                  merchantTransferId: transfer12350
                  recipientBank: CIB
                  recipientNumber: "100012345678"
      responses:
        "200":
          description: >-
            Transfer accepted for processing. Fields that do not apply to the
            `method` you sent are echoed back as `null` rather than rejected —
            a `recipientBank` sent with a wallet transfer, for example, comes
            back as `recipientBank: null`.
          content:
            application/json:
              schema:
                type: object
                properties:
                  messages:
                    $ref: "#/components/schemas/LocalizedMessage"
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        transferId:
                          type: string
                        status:
                          type: string
                          enum: [PENDING]
                          description: >-
                            Always `PENDING` on create — the transfer is accepted, not sent.
                            It moves through `INITIATED` → `IN_TRANSIT` → `TRANSFERRED` or
                            `FAILED` asynchronously; track it with the payouts webhook or
                            the transfer-details endpoint.
                        amount:
                          type: number
                        method:
                          type: string
                        recipientNumber:
                          type: string
                        recipientName:
                          type: string
                        recipientBank:
                          type: [string, "null"]
                          description: >-
                            The bank abbreviation for `bank` and `card` transfers.
                            `null` for every other method, including when you sent
                            a value that the method does not use.
                        merchantTransferId:
                          type: string
              examples:
                pending:
                  value:
                    messages:
                      en: We're processing your transfer.
                      ar: .جاري معالجة المعاملة
                    data:
                      - transferId: TRS-212328888
                        status: PENDING
                        amount: 10
                        method: wallet
                        recipientNumber: "01555539512"
                        recipientName: Jhon Doe
                        recipientBank: null
                        merchantTransferId: transfer12349
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/transfers/batch:
    servers:
      - url: https://test-fep.kashier.io
        description: Test — no real money moves
    post:
      operationId: createBulkTransfer
      tags:
        - Payouts
      summary: Bulk transfers
      description: Creates a bulk payout transfer from an uploaded file of transfers.
      security:
        - secretKey: []
      parameters:
        - name: merchantBatchId
          in: query
          required: true
          description: Refers to a unique identifier assigned by a merchant to a specific batch of transactions
          schema:
            type: string
        - name: batchName
          in: query
          required: true
          description: refers to a human-readable label or name assigned to a batch of transactions. It is used primarily for identification and organization purposes, making it easier to manage and understand the context of a batch without relying on technical IDs like merchantBatchId
          schema:
            type: string
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  contentEncoding: binary
                  description: Refers to the file that contains the list of transfers to be processed.
      responses:
        "200":
          description: Bulk transfer accepted for processing.
          content:
            application/json:
              schema:
                type: object
                properties:
                  messages:
                    $ref: "#/components/schemas/LocalizedMessage"
              examples:
                processing:
                  value:
                    messages:
                      en: We're processing your transfer.
                      ar: .جاري معالجة المعاملة
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/customers:
    get:
      operationId: listCustomers
      tags:
        - Customers
      summary: List all customers
      description: Retrieves the merchant's customers. All parameters are optional and can be combined; results are paginated.
      security:
        - secretKey: []
      parameters:
        - name: page
          in: query
          description: Current page number.
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: search
          in: query
          description: Search for a customer by name, phone number, or email address.
          schema:
            type: string
        - name: sortBy
          in: query
          description: "Field to sort by: customer name, phone number, or email address."
          schema:
            type: string
        - name: sortType
          in: query
          description: "Sorting direction: 1 = ascending, -1 = descending."
          schema:
            type: integer
            enum:
              - 1
              - -1
        - name: startDate
          in: query
          description: "Only return customers created after this date. Example: 10-12-2024"
          schema:
            type: string
        - name: endDate
          in: query
          description: "Only return customers created before this date. Example: 10-12-2024"
          schema:
            type: string
      responses:
        "200":
          description: The merchant's customers, with pagination info.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/CustomerListPage"
                  message:
                    type: string
              examples:
                list:
                  value:
                    body:
                      customers:
                        - _id: 67ba0311bf4f31001203c6c2
                          name: John Doe
                          phoneNumber: "1123456789"
                          emailAddress: john.doe@example.com
                          customerId: C-1740243729820
                          merchantId: MID-XXXXX-XXX
                          customFields:
                            - name: custom-key-1
                              value: custom-value-1
                            - name: custom-key-2
                              value: custom-value-2
                          createdAt: 2025-02-22 17:02:10.098000+00:00
                          updatedAt: 2025-02-25 12:31:40.474000+00:00
                          id: 67ba0311bf4f31001203c6c2
                        - _id: 67b9f78287c9970012383912
                          name: Jane Doe
                          phoneNumber: "1123456780"
                          emailAddress: ""
                          customerId: C-1740240770780
                          merchantId: MID-XXXXX-XXX
                          customFields:
                            - name: custom-key-1
                              value: custom-value-2
                          createdAt: 2025-02-22 16:12:51.254000+00:00
                          updatedAt: 2025-02-25 08:32:06.998000+00:00
                          id: 67b9f78287c9970012383912
                      totalCustomers: 2
                      limit: 20
                      totalPages: 1
                      page: 1
                      pagingCounter: 1
                      hasPrevPage: false
                      hasNextPage: false
                      prevPage: null
                      nextPage: null
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
    post:
      operationId: createCustomer
      tags:
        - Customers
      summary: Add a new customer
      description: Creates a customer profile. Kashier assigns the customerId (a C- prefixed value) that you use to link the customer to payments and payment links.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CustomerCreateRequest"
            examples:
              create:
                summary: Customer with one custom field, contacted by SMS
                value:
                  name: John Doe
                  phoneNumber: "1123456789"
                  emailAddress: john.doe@example.com
                  customFields:
                    - name: custom-key-1
                      value: custom-value-1
                  preferredCommunicationChannel: sms
      responses:
        "200":
          description: The created customer.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/CustomerProfile"
                  message:
                    type: string
              examples:
                created:
                  value:
                    body:
                      _id: 67bde55fd5a33d00120b202d
                      name: John Doe
                      phoneNumber: "1123456789"
                      emailAddress: john.doe@example.com
                      customFields:
                        - name: custom-key-1
                          value: custom-value-1
                      preferredCommunicationChannel: sms
                      merchantId: MID-XXXXX-XXX
                      customerId: C-1740498271115
                      createdAt: 2025-02-25 15:44:31.120000+00:00
                      updatedAt: 2025-02-25 15:44:31.120000+00:00
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/customers/{id}:
    get:
      operationId: getCustomer
      tags:
        - Customers
      summary: Get customer details
      description: Retrieves a single customer, including the timeLine of changes made to the profile and who made them.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The customer's record id.
          schema:
            type: string
      responses:
        "200":
          description: The customer, with the audit timeline of the profile.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/CustomerDetails"
                  message:
                    type: string
              examples:
                retrieved:
                  value:
                    body:
                      _id: 67ba05fd87c9970012389428
                      name: John Doe
                      phoneNumber: "1123456789"
                      emailAddress: ""
                      customerId: C-1740244477202
                      merchantId: MID-XXXXX-XXX
                      customFields:
                        - name: custom-key-1
                          value: custom-value-1
                        - name: custom-key-2
                          value: custom-value-2
                      createdAt: 2025-02-22 19:14:37+02:00
                      updatedAt: 2025-02-22 19:14:37+02:00
                      timeLine:
                        - _id: 67ba05fd87c9970012389508
                          customerId: 67ba05fd87c9970012389428
                          operation: created
                          actionBy:
                            email: user@your-company.com
                            fullName: Dashboard User
                          updatedFields: []
                          updatedAt: 2025-02-22 19:14:37+02:00
                    message: Customer retrieved successfully
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    put:
      operationId: updateCustomer
      tags:
        - Customers
      summary: Update a customer
      description: Updates a customer profile. Send the fields you want the customer to end up with — customFields replaces the existing array rather than merging into it.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The customer's record id.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CustomerUpdateRequest"
            examples:
              update:
                value:
                  name: John Doe
                  phoneNumber: "1123456789"
                  emailAddress: john.doe@example.com
                  customFields:
                    - name: custom-key-1
                      value: custom-value-1
                  preferredCommunicationChannel: sms
      responses:
        "200":
          description: The updated customer.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: object
                    properties:
                      message:
                        type: string
                      body:
                        $ref: "#/components/schemas/CustomerProfile"
                  message:
                    type: string
              examples:
                updated:
                  value:
                    body:
                      message: Customer updated successfully
                      body:
                        _id: 67ba05fd87c9970012389429
                        name: John Doe
                        phoneNumber: "1123456789"
                        emailAddress: john.doe@example.com
                        customerId: C-XXXXXXXXXXXXX
                        merchantId: MID-XXXXX-XXX
                        customFields:
                          - name: custom-key-1
                            value: custom-value-1
                        createdAt: 2025-02-22 17:14:37.203000+00:00
                        updatedAt: 2025-02-26 09:55:34.630000+00:00
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    delete:
      operationId: deleteCustomer
      tags:
        - Customers
      summary: Delete a customer
      description: Deletes a customer profile.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The customer's record id.
          schema:
            type: string
      responses:
        "200":
          description: The customer was deleted.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
              examples:
                deleted:
                  value:
                    message: Customer deleted successfully
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/customers/{id}/payment-links:
    get:
      operationId: getCustomerPaymentLinks
      tags:
        - Customers
      summary: Get a customer's payment links
      description: Retrieves the payment links created for a single customer — the customer-side view of the Payment links endpoints. Results are paginated.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The customer's record id.
          schema:
            type: string
        - name: page
          in: query
          description: Current page number.
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
      responses:
        "200":
          description: The customer's payment links. Each entry has the same shape as the payment links returned by the Payment links endpoints.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: object
                    additionalProperties: true
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/customers/audit-logs/{id}:
    get:
      operationId: getCustomerAuditLogs
      tags:
        - Customers
      summary: Get a customer's audit logs
      description: Retrieves the full audit trail for a customer — every create and edit, which fields changed, and which dashboard user made the change. This is the same data the profile returns under timeLine, retrievable on its own so you can page through a long trail.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The customer's record id.
          schema:
            type: string
        - name: page
          in: query
          description: Current page number.
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
      responses:
        "200":
          description: The customer's audit log entries.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: array
                    items:
                      $ref: "#/components/schemas/CustomerTimelineEntry"
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/customers/export-async:
    get:
      operationId: exportCustomers
      tags:
        - Customers
      summary: Export customers
      description: Exports the customers matching the given filters. The export is generated asynchronously and delivered to the merchant account's email address, so the response only acknowledges that the request is being processed.
      security:
        - secretKey: []
      parameters:
        - name: search
          in: query
          description: Search for a customer by name, phone number, or email address.
          schema:
            type: string
        - name: sortBy
          in: query
          description: "Field to sort by: customer name, phone number, or email address."
          schema:
            type: string
        - name: sortType
          in: query
          description: "Sorting direction: 1 = ascending, -1 = descending."
          schema:
            type: integer
            enum:
              - 1
              - -1
        - name: startDate
          in: query
          description: "Only export customers created after this date. Example: 01-06-2024"
          schema:
            type: string
        - name: endDate
          in: query
          description: "Only export customers created before this date. Example: 30-06-2024"
          schema:
            type: string
      responses:
        "200":
          description: Export accepted for processing — an email with the export follows shortly.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/customers/export-batch-async:
    post:
      operationId: exportCustomerPaymentLinks
      tags:
        - Customers
      summary: Export customers with their payment links
      description: Exports a chosen set of customers together with the payment links created for them. Pass customerIds to export specific customers, or the date/search filters to export everything that matches. Like the other exports, the file is emailed to the merchant account.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CustomerExportBatchRequest"
            examples:
              byIds:
                summary: Export two specific customers
                value:
                  customerIds:
                    - 67ba0311bf4f31001203c6c2
                    - 67b9f78287c9970012383912
                  startDate: 01-06-2024
                  endDate: 30-06-2024
                  search: ""
      responses:
        "200":
          description: Export accepted for processing — an email with the export follows shortly.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/customers/import:
    post:
      operationId: importCustomers
      tags:
        - Customers
      summary: Upload a customers sheet for review
      description: Step 1 of the bulk import. Uploads an Excel sheet of customers and validates it without saving anything. Rows that fail validation come back with their errors populated so you can correct them; if the sheet is valid the response carries a correlationId that references the validated data. Pass that correlationId to saveImportedCustomers to actually create the customers.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - file
              properties:
                file:
                  type: string
                  format: binary
                  description: The Excel sheet (.xlsx) containing the customers to import.
      responses:
        "200":
          description: The parsed customers with per-row `errors`, plus the `correlationId` to pass to the save step.
          content:
            application/json:
              schema:
                type: object
                properties:
                  customers:
                    type: array
                    items:
                      $ref: "#/components/schemas/CustomerImportRow"
                  correlationId:
                    type: string
                  message:
                    type: string
              examples:
                imported:
                  value:
                    customers:
                      - name: John Doe
                        phoneNumber: "1123456789"
                        emailAddress: ""
                        customFields:
                          - name: custom-key-1
                            value: custom-value-1
                          - name: custom-key-2
                            value: custom-value-2
                        errors: null
                      - name: Jane Doe
                        phoneNumber: "1123456780"
                        emailAddress: ""
                        customFields:
                          - name: custom-key-1
                            value: custom-value-2
                        errors: null
                    correlationId: 48701e20-ffa2-4c33-be5e-fef3dbfaf94a
                    message: Imported successfully
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/customers/savecustomers:
    get:
      operationId: saveImportedCustomers
      tags:
        - Customers
      summary: Save the uploaded customers
      description: Step 2 of the bulk import. Persists the customers that were validated by importCustomers, identified by the correlationId returned there. Separating validation from the write keeps a partially invalid sheet from creating any customers.
      security:
        - secretKey: []
      parameters:
        - name: correlationId
          in: query
          required: true
          description: The `correlationId` returned by the import step.
          schema:
            type: string
      responses:
        "200":
          description: The customers that were created from the validated sheet.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: array
                    items:
                      $ref: "#/components/schemas/CustomerProfile"
                  message:
                    type: string
              examples:
                saved:
                  value:
                    body:
                      - _id: 67bef80abf4f31001203db66
                        name: John Doe
                        phoneNumber: "1123456789"
                        emailAddress: ""
                        customerId: C-1740568586339
                        merchantId: MID-XXXXX-XXX
                        customFields:
                          - name: custom-key-1
                            value: custom-value-1
                        createdAt: 2025-02-26 11:16:26.775000+00:00
                        updatedAt: 2025-02-26 11:16:26.775000+00:00
                      - _id: 67bef80abf4f31001203db67
                        name: Jane Doe
                        phoneNumber: "1123456780"
                        emailAddress: ""
                        customerId: C-1740568586340
                        merchantId: MID-XXXXX-XXX
                        customFields:
                          - name: custom-key-1
                            value: custom-value-2
                        createdAt: 2025-02-26 11:16:26.776000+00:00
                        updatedAt: 2025-02-26 11:16:26.776000+00:00
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentRequest:
    post:
      operationId: createInvoice
      tags:
        - Invoices
      summary: Create invoice
      description: Creates an invoice (payment request). Kashier mints the invoice identifier for you — PR-… for a simple request, INV-… for a professional invoice, and ORD-… for an order — and returns a payment link you can send to the customer. The invoice starts unpaid; use [Share invoice](#operation/shareInvoice) to deliver it, or send the link yourself.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InvoiceCreateRequest"
            examples:
              simple:
                summary: Simple payment request for a single amount
                value:
                  paymentType: simple
                  totalAmount: 100
                  currency: EGP
                  description: Invoice for consulting services
                  customerName: Ahmed Hassan
                  email: customer@example.com
                  phoneNumber: "+201000000000"
                  referenceId: REF-001
                  isManualCapture: false
              professional:
                summary: Professional invoice with line items, tax, and a due date
                value:
                  paymentType: professional
                  currency: EGP
                  totalAmount: 100
                  description: February retainer
                  customerName: Ahmed Hassan
                  email: customer@example.com
                  dueDate: 2030-01-01
                  tax: 14
                  referenceId: INV-2026-014
                  isManualCapture: false
                  invoiceItems:
                    - itemName: Design work
                      description: Landing page design
                      quantity: 2
                      unitPrice: 40
                      subTotal: 80
                    - itemName: Hosting
                      description: One month
                      quantity: 1
                      unitPrice: 20
                      subTotal: 20
                  extraFees:
                    - name: Service fee
                      flatFee: 0
                      rate: 0
      responses:
        "201":
          description: The created invoice. `paymentRequestId` is the identifier you use on every other invoice operation, and `paymentLinkId` is present when the invoice was created as a payment link.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/Invoice"
                  message:
                    type: string
              examples:
                created:
                  value:
                    body:
                      paymentRequestId: PR-XXXXXXXXXX
                      merchantId: MID-XXXX-XXXX
                      paymentType: simple
                      totalAmount: 100
                      currency: EGP
                      description: Invoice for consulting services
                      customerName: Ahmed Hassan
                      email: customer@example.com
                      referenceId: REF-001
                      state: submitted
                      paymentStatus: unpaid
                      isManualCapture: false
                      availableAmountForRefund: 0
                      creationDate: 2026-07-30 09:12:44.201000+00:00
                      dueDate: null
                      transactions: []
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentRequests:
    get:
      operationId: listInvoices
      tags:
        - Invoices
      summary: List invoices
      description: Lists your invoices, with pagination. Combine the filters to narrow the list down — for example paymentStatus=unpaid together with a date range to find everything still outstanding this month.
      security:
        - secretKey: []
      parameters:
        - name: paymentRequestId
          in: query
          description: Filter by a specific invoice identifier (e.g., `PR-XXXXXXXXXX`).
          schema:
            type: string
        - name: paymentStatus
          in: query
          description: Filter by payment status.
          schema:
            type: string
            enum:
              - unpaid
              - on hold
              - paid
              - voided
        - name: state
          in: query
          description: Filter by the invoice lifecycle state.
          schema:
            type: string
            enum:
              - draft
              - submitted
              - cancelled
              - awaiting_approval
              - rejected
        - name: customerName
          in: query
          description: Filter by customer name.
          schema:
            type: string
        - name: startDate
          in: query
          description: Start of the creation-date range (e.g., 2026-01-01).
          schema:
            type: string
        - name: endDate
          in: query
          description: End of the creation-date range (e.g., 2026-01-31).
          schema:
            type: string
        - name: startAmountRange
          in: query
          description: Minimum total amount.
          schema:
            type: number
        - name: endAmountRange
          in: query
          description: Maximum total amount.
          schema:
            type: number
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
      responses:
        "200":
          description: The invoices list with pagination info.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: array
                    items:
                      $ref: "#/components/schemas/Invoice"
                  pagination:
                    $ref: "#/components/schemas/InvoicePagination"
                  message:
                    type: string
              examples:
                invoices:
                  summary: One outstanding invoice (list abridged)
                  value:
                    body:
                      - paymentRequestId: PR-XXXXXXXXXX
                        merchantId: MID-XXXX-XXXX
                        paymentType: simple
                        totalAmount: 100
                        currency: EGP
                        description: Invoice for consulting services
                        customerName: Ahmed Hassan
                        state: submitted
                        paymentStatus: unpaid
                        creationDate: 2026-07-30 09:12:44.201000+00:00
                    pagination:
                      total: 42
                      limit: 20
                      page: 1
                      pages: 3
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentRequest/{paymentRequestId}:
    get:
      operationId: getInvoice
      tags:
        - Invoices
      summary: Get invoice
      description: Retrieves a single invoice, including its line items and any payment transactions recorded against it.
      security:
        - secretKey: []
      parameters:
        - name: paymentRequestId
          in: path
          required: true
          description: The invoice identifier returned when the invoice was created (e.g., `PR-XXXXXXXXXX`).
          schema:
            type: string
      responses:
        "200":
          description: The invoice details.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/Invoice"
                  message:
                    type: string
              examples:
                invoice:
                  value:
                    body:
                      paymentRequestId: PR-XXXXXXXXXX
                      merchantId: MID-XXXX-XXXX
                      paymentType: professional
                      totalAmount: 100
                      currency: EGP
                      description: February retainer
                      customerName: Ahmed Hassan
                      email: customer@example.com
                      state: submitted
                      paymentStatus: paid
                      tax: 14
                      dueDate: 2030-01-01 00:00:00+00:00
                      creationDate: 2026-07-30 09:12:44.201000+00:00
                      availableAmountForRefund: 100
                      invoiceItems:
                        - itemName: Design work
                          description: Landing page design
                          quantity: 2
                          unitPrice: 40
                          subTotal: 80
                        - itemName: Hosting
                          description: One month
                          quantity: 1
                          unitPrice: 20
                          subTotal: 20
                      transactions:
                        - transactionInfoId: TX-243585751279
                          orderReference: TEST-ORD-193402001
                          amount: 100
                          currency: EGP
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    put:
      operationId: updateInvoice
      tags:
        - Invoices
      summary: Update invoice
      description: "Updates an invoice, or cancels it. Send operation: cancel to cancel an unpaid invoice; send any of the editable fields to change it. Only unpaid invoices can be edited."
      security:
        - secretKey: []
      parameters:
        - name: paymentRequestId
          in: path
          required: true
          description: The invoice identifier (e.g., `PR-XXXXXXXXXX`).
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InvoiceUpdateRequest"
            examples:
              edit:
                summary: Change the amount and description
                value:
                  operation: edit
                  totalAmount: 100
                  description: Updated invoice
                  customerName: Ahmed Hassan
              cancel:
                summary: Cancel an unpaid invoice
                value:
                  operation: cancel
      responses:
        "200":
          description: The updated invoice.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/Invoice"
                  message:
                    type: string
              examples:
                updated:
                  value:
                    body:
                      paymentRequestId: PR-XXXXXXXXXX
                      merchantId: MID-XXXX-XXXX
                      totalAmount: 100
                      currency: EGP
                      description: Updated invoice
                      state: submitted
                      paymentStatus: unpaid
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    delete:
      operationId: deleteInvoice
      tags:
        - Invoices
      summary: Delete invoice
      description: Deletes an invoice. The invoice is soft-deleted — it stops being payable and disappears from [List invoices](#operation/listInvoices), but its history is retained.
      security:
        - secretKey: []
      parameters:
        - name: paymentRequestId
          in: path
          required: true
          description: The invoice identifier (e.g., `PR-XXXXXXXXXX`).
          schema:
            type: string
      responses:
        "200":
          description: The invoice was deleted.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: object
                    additionalProperties: true
                  message:
                    type: string
              examples:
                deleted:
                  value:
                    body:
                      paymentRequestId: PR-XXXXXXXXXX
                      isDeleted: true
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentRequest/share:
    post:
      operationId: shareInvoice
      tags:
        - Invoices
      summary: Share invoice
      description: Sends the invoice's payment link to a customer by email or SMS. Kashier records the delivery outcome on the invoice, so a later [Get invoice](#operation/getInvoice) shows whether the message was delivered, opened, or clicked. This endpoint is rate-limited.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InvoiceShareRequest"
            examples:
              email:
                summary: Share by email
                value:
                  operation: email
                  key: customer@example.com
                  urlIdentifier: PR-XXXXXXXXXX
              sms:
                summary: Share by SMS
                value:
                  operation: sms
                  key: "+201000000000"
                  urlIdentifier: PR-XXXXXXXXXX
      responses:
        "200":
          description: The invoice link was queued for delivery.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: object
                    additionalProperties: true
                  message:
                    type: string
              examples:
                shared:
                  value:
                    body:
                      paymentRequestId: PR-XXXXXXXXXX
                      lastShareStatus:
                        email:
                          status: pending
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentRequest/export:
    get:
      operationId: exportInvoices
      tags:
        - Invoices
      summary: Export invoices
      description: Exports the invoices matching your filters as a spreadsheet, returned inline in the response. For large exports use [Export invoices asynchronously](#operation/exportInvoicesAsync) instead, which emails you the file once it is ready.
      security:
        - secretKey: []
      parameters:
        - name: status
          in: query
          description: Filter by payment status.
          schema:
            type: string
            enum:
              - unpaid
              - on hold
              - paid
              - voided
        - name: dateFrom
          in: query
          description: Start of the creation-date range (e.g., 2026-01-01).
          schema:
            type: string
        - name: dateTo
          in: query
          description: End of the creation-date range (e.g., 2026-06-30).
          schema:
            type: string
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
      responses:
        "200":
          description: The invoices spreadsheet.
          content:
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentRequest/export-async:
    get:
      operationId: exportInvoicesAsync
      tags:
        - Invoices
      summary: Export invoices asynchronously
      description: Starts an invoice export in the background and emails the finished file to the account that made the request. Use this instead of [Export invoices](#operation/exportInvoices) when the date range is wide enough that a synchronous download would time out.
      security:
        - secretKey: []
      parameters:
        - name: status
          in: query
          description: Filter by payment status.
          schema:
            type: string
            enum:
              - unpaid
              - on hold
              - paid
              - voided
        - name: dateFrom
          in: query
          description: Start of the creation-date range (e.g., 2026-01-01).
          schema:
            type: string
        - name: dateTo
          in: query
          description: End of the creation-date range (e.g., 2026-06-30).
          schema:
            type: string
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
      responses:
        "200":
          description: Export accepted for processing — the file is emailed when it is ready.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: object
                    additionalProperties: true
                  message:
                    type: string
              examples:
                processing:
                  value:
                    body:
                      status: processing
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentRequest/import:
    post:
      operationId: importInvoices
      tags:
        - Invoices
        - Payment links
      summary: Import invoices
      description: Creates many invoices at once from an uploaded spreadsheet. Each row becomes an invoice; the response reports how many rows were accepted and which ones failed, so you can fix and re-upload just the failures.
      security:
        - secretKey: []
      parameters:
        - name: currency
          in: query
          description: ISO 4217 currency code applied to the imported invoices (e.g., EGP).
          schema:
            type: string
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - file
              properties:
                file:
                  type: string
                  format: binary
                  description: Excel or CSV file containing one invoice per row.
      responses:
        "200":
          description: The import result, per row.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: object
                    properties:
                      imported:
                        type: integer
                      successful:
                        type: integer
                      failed:
                        type: integer
                      results:
                        type: array
                        items:
                          type: object
                          additionalProperties: true
                  message:
                    type: string
              examples:
                imported:
                  value:
                    body:
                      imported: 5
                      successful: 5
                      failed: 0
                      results:
                        - index: 1
                          paymentRequestId: PR-XXXXXXXXXX
                          totalAmount: 100
                          currency: EGP
                          status: created
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/payment-link:
    get:
      operationId: listPaymentLinks
      tags:
        - Payment links
      summary: Get all payment links
      description: Retrieves the merchant's payment links. All filters are optional and can be combined; results are paginated. If the currency conversion feature is enabled on your account you can also filter by a virtual currency view code (e.g. USD_VIRTUAL) to list only the links created in that foreign currency.
      security:
        - secretKey: []
      parameters:
        - name: currency
          in: query
          description: ISO 4217 currency code to filter by (e.g., EGP). Accepts a virtual currency view code (e.g., USD_VIRTUAL) when currency conversion is enabled.
          schema:
            type: string
        - name: state
          in: query
          description: "Payment link state. Example: submitted"
          schema:
            type: string
        - name: paymentStatus
          in: query
          description: Payment state.
          schema:
            type: string
            enum:
              - PAID
              - UNPAID
              - OVERDUE
              - EXPIRED
        - name: paymentType
          in: query
          description: Payment type.
          schema:
            type: string
            enum:
              - FIXED_AMOUNT
              - ITEMIZED
        - name: startDueDate
          in: query
          description: Earliest due date to include.
          schema:
            type: string
        - name: endDueDate
          in: query
          description: Latest due date to include.
          schema:
            type: string
        - name: startDate
          in: query
          description: Start of the creation date range.
          schema:
            type: string
        - name: endDate
          in: query
          description: End of the creation date range.
          schema:
            type: string
        - name: startAmountRange
          in: query
          description: Minimum total amount.
          schema:
            type: string
        - name: endAmountRange
          in: query
          description: Maximum total amount.
          schema:
            type: string
        - name: search
          in: query
          description: "Search for a payment link by its id. Example: PL-2348668602"
          schema:
            type: string
        - name: page
          in: query
          description: Page number (pagination).
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of items per page (pagination).
          schema:
            type: integer
      responses:
        "200":
          description: The merchant's payment links plus pagination info. The `virtual*` fields and `exchangeRateServiceAvailable` are only meaningful for currency conversion links.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/PaymentLinkSummary"
                  pagination:
                    $ref: "#/components/schemas/PaymentLinkPagination"
                  exchangeRateServiceAvailable:
                    type: boolean
              examples:
                list:
                  summary: One paid EGP link and one unpaid currency conversion link
                  value:
                    message: Payment links retrieved successfully
                    data:
                      - _id: 67a49c89b0d26b00127c934a
                        description: ""
                        dueDate: null
                        isSuspendedPayment: false
                        currency: EGP
                        paymentLinkId: PL-2348668603
                        isDeleted: false
                        merchantId: MID-XXXXX-XXX
                        paymentType: simple
                        totalAmount: 100
                        availableAmountForRefund: 0
                        state: submitted
                        customerName: John Doe
                        paymentRequestId: PR-2348668603
                        creationDate: 2025-02-06 11:27:05.236000+00:00
                        merchantInfo:
                          storeName: demo
                        extraFees:
                          - name: VAT
                            flatFee: 0
                            rate: 5
                        invoiceItems: []
                        paymentStatus: paid
                      - _id: 67a49c89b0d26b00127c934b
                        description: ""
                        dueDate: null
                        isSuspendedPayment: false
                        currency: EGP
                        paymentLinkId: PL-2348668604
                        isDeleted: false
                        merchantId: MID-XXXXX-XXX
                        paymentType: simple
                        totalAmount: 1900
                        availableAmountForRefund: 0
                        state: submitted
                        customerName: Jane Doe
                        paymentRequestId: PR-2348668604
                        creationDate: 2025-02-06 11:27:05.236000+00:00
                        merchantInfo:
                          storeName: demo
                        extraFees: []
                        invoiceItems: []
                        paymentStatus: unpaid
                        virtualAmount: 40
                        virtualCurrency: USD_VIRTUAL
                        virtualExchangeRate: 47.5
                        virtualRateRecordedAt: 2025-02-06 11:27:05.236000+00:00
                    pagination:
                      page: 1
                      limit: 10
                      total: 2
                      totalPages: 1
                    exchangeRateServiceAvailable: true
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
    post:
      operationId: createPaymentLink
      tags:
        - Payment links
      summary: Create a payment link
      description: Creates a single payment link for one customer. Set currency to a virtual currency code (USD_VIRTUAL, EUR_VIRTUAL, GBP_VIRTUAL, SAR_VIRTUAL, AED_VIRTUAL) with totalAmount expressed in that currency to collect in a foreign currency while settling in EGP. Currency conversion must be enabled on your account — without it a virtual currency is rejected with a 400 "Currency conversion feature is not enabled."
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PaymentLinkCreateRequest"
            examples:
              simple:
                summary: Fixed-amount EGP link with extra fees
                value:
                  customer:
                    name: John Doe
                  totalAmount: 100
                  description: ""
                  isManualCapture: false
                  paymentType: simple
                  currency: EGP
                  state: submitted
                  extraFees:
                    - name: VAT
                      flatFee: 0
                      rate: 5
                    - name: annualFee
                      flatFee: 500
                      rate: 0
                  dueDate: 2030-01-01 00:00:00+00:00
                  isSuspendedPayment: false
                  referenceId: 123ss456
              currencyConversion:
                summary: Foreign currency link that settles in EGP
                value:
                  customer:
                    name: John Doe
                  totalAmount: 40
                  description: ""
                  isManualCapture: false
                  paymentType: simple
                  currency: USD_VIRTUAL
                  state: submitted
                  extraFees: []
                  isSuspendedPayment: false
                  referenceId: 123ss456
      responses:
        "200":
          description: The created payment link.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    $ref: "#/components/schemas/PaymentLinkSummary"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/payment-link/statistics:
    get:
      operationId: getPaymentLinkStatistics
      tags:
        - Payment links
      summary: Get payment link statistics
      description: Returns aggregate statistics across the merchant's payment links (counts and amounts broken down by payment status). Accepts the same optional filters as listPaymentLinks, so the totals match the list you are looking at.
      security:
        - secretKey: []
      parameters:
        - name: currency
          in: query
          description: ISO 4217 currency code, or a virtual currency view code.
          schema:
            type: string
        - name: startDate
          in: query
          description: Start of the creation date range.
          schema:
            type: string
        - name: endDate
          in: query
          description: End of the creation date range.
          schema:
            type: string
        - name: search
          in: query
          description: Search keyword (payment link id).
          schema:
            type: string
      responses:
        "200":
          description: Aggregate payment link statistics for the merchant. The exact set of keys is not contractual and may grow, so read the counters you need by name.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/payment-link/{paymentLinkId}:
    get:
      operationId: getPaymentLink
      tags:
        - Payment links
      summary: Get payment link details
      description: Retrieves a single payment link, including its extra fees, invoice items, and the full audit history of the link (creation, edits, shares, and payments).
      security:
        - secretKey: []
      parameters:
        - name: paymentLinkId
          in: path
          required: true
          description: "The payment link identifier. Example: PL-2348668602"
          schema:
            type: string
      responses:
        "200":
          description: The payment link, its history records, and whether the exchange rate service is available. The `virtual*` fields are null unless the link uses a virtual currency.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    $ref: "#/components/schemas/PaymentLinkDetails"
                  exchangeRateServiceAvailable:
                    type: boolean
                  history:
                    type: object
                    properties:
                      records:
                        type: array
                        items:
                          $ref: "#/components/schemas/PaymentLinkHistoryRecord"
              examples:
                paid:
                  summary: A link that has been marked as paid
                  value:
                    message: Payment links retrieved successfully
                    data:
                      _id: 67a3647454cfd700129b9424
                      description: ""
                      paymentStatus: paid
                      dueDate: 2030-01-01 00:00:00+00:00
                      isSuspendedPayment: false
                      currency: EGP
                      paymentLinkId: PL-2348668602
                      merchantId: MID-XXXXX-XXX
                      paymentType: simple
                      totalAmount: 100
                      state: submitted
                      customerName: John Doe
                      paymentRequestId: PR-2348668602
                      creationDate: 2025-02-05 13:15:32.949000+00:00
                      merchantInfo:
                        storeName: demo
                      extraFees:
                        - name: shipping
                          flatFee: 60
                          rate: 0
                        - name: tax
                          flatFee: 0
                          rate: 14
                      invoiceItems: []
                      isDeleted: false
                      referenceId: 123ss456
                      totalAmountWithoutFees: 200
                      customer: null
                      virtualAmount: null
                      virtualCurrency: null
                      virtualExchangeRate: null
                      virtualRateRecordedAt: null
                    exchangeRateServiceAvailable: true
                    history:
                      records:
                        - event: MARKED_AS_PAID
                          metadata:
                            timestamp: 2025-02-06 11:25:38.642000+00:00
                            transactionInfoId: TX-2348668602
                            amount: 100
                            currency: EGP
                            status: SUCCESS
                            customerName: John Doe
                          stateChanges:
                            updated:
                              paymentStatus:
                                from: unpaid
                                to: paid
                        - event: CREATED
                          metadata:
                            timestamp: 2025-02-05 13:15:32.962000+00:00
                            source: API
                            channel: payment_link
                            createdVia: web
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    put:
      operationId: updatePaymentLink
      tags:
        - Payment links
      summary: Update a payment link
      description: Updates an existing payment link. The editable fields are wrapped in a paymentLink object; send the full object you want the link to end up with.
      security:
        - secretKey: []
      parameters:
        - name: paymentLinkId
          in: path
          required: true
          description: "The payment link identifier. Example: PL-2348668602"
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PaymentLinkUpdateRequest"
            examples:
              update:
                summary: Change the amount and the extra fees
                value:
                  paymentLink:
                    customer:
                      name: John Doe
                    totalAmount: 100
                    description: ""
                    isManualCapture: false
                    paymentType: simple
                    currency: EGP
                    state: submitted
                    extraFees:
                      - name: tax
                        flatFee: 0
                        rate: 5
                      - name: service
                        flatFee: 0
                        rate: 10
      responses:
        "200":
          description: The updated payment link.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    $ref: "#/components/schemas/PaymentLinkSummary"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    delete:
      operationId: deletePaymentLink
      tags:
        - Payment links
      summary: Delete a payment link
      description: Deletes a payment link. The link is soft-deleted (isDeleted becomes true) and stops being payable.
      security:
        - secretKey: []
      parameters:
        - name: paymentLinkId
          in: path
          required: true
          description: "The payment link identifier. Example: PL-2348668602"
          schema:
            type: string
      responses:
        "200":
          description: The payment link was deleted.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/payment-link/{paymentLinkId}/events:
    get:
      operationId: getPaymentLinkEvents
      tags:
        - Payment links
      summary: Get payment link events
      description: Retrieves the event/audit trail of a single payment link — the same records that getPaymentLink returns under history.records, retrievable on their own so you can page through a long trail without refetching the link.
      security:
        - secretKey: []
      parameters:
        - name: paymentLinkId
          in: path
          required: true
          description: "The payment link identifier. Example: PL-2348668602"
          schema:
            type: string
        - name: page
          in: query
          description: Page number (pagination).
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of events per page (pagination).
          schema:
            type: integer
      responses:
        "200":
          description: The payment link's event records, newest first.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  records:
                    type: array
                    items:
                      $ref: "#/components/schemas/PaymentLinkHistoryRecord"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/payment-link/share:
    post:
      operationId: sharePaymentLink
      tags:
        - Payment links
      summary: Share a payment link
      description: Sends an existing payment link to a customer by email or SMS. Use operation to pick the channel and key to carry the matching destination.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PaymentLinkShareRequest"
            examples:
              email:
                summary: Share by email
                value:
                  operation: email
                  urlIdentifier: PL-2348668602
                  key: john.doe@example.com
              sms:
                summary: Share by SMS
                value:
                  operation: sms
                  urlIdentifier: PL-2348668602
                  key: "1123456789"
      responses:
        "200":
          description: The payment link was sent on the requested channel.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
              examples:
                sent:
                  value:
                    message: Payment link email sent succesfully
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/payment-link/re-share:
    post:
      operationId: resharePaymentLinks
      tags:
        - Payment links
      summary: Re-share payment links
      description: Re-sends one or more existing payment links to the customers they were originally shared with, on the channel used the first time. Useful for chasing unpaid links in bulk without re-entering each customer's contact details.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PaymentLinkReshareRequest"
            examples:
              reshare:
                summary: Re-send two links
                value:
                  paymentLinkIds:
                    - PL-2348668602
                    - PL-2348668603
      responses:
        "200":
          description: The payment links were re-sent.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/payment-link/create-and-share:
    post:
      operationId: createAndSharePaymentLink
      tags:
        - Payment links
      summary: Create and share a payment link
      description: Creates a payment link and immediately sends it to the customer, in a single call. The body is the same as createPaymentLink; the customer's email address or phone number determines the channel the link is sent on.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PaymentLinkCreateRequest"
            examples:
              createAndShare:
                summary: Create a link and email it to the customer
                value:
                  customer:
                    name: John Doe
                    emailAddress: john.doe@example.com
                  totalAmount: 100
                  description: Invoice for services
                  isManualCapture: false
                  paymentType: simple
                  currency: EGP
                  state: submitted
                  extraFees: []
                  items: []
                  isSuspendedPayment: false
                  referenceId: 123ss456
      responses:
        "200":
          description: The created payment link, which has also been sent to the customer.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    $ref: "#/components/schemas/PaymentLinkSummary"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/payment-link/export:
    post:
      operationId: exportPaymentLinks
      tags:
        - Payment links
      summary: Export payment links
      description: Exports the payment links matching the given filters. The export is generated asynchronously and delivered to the merchant account's email address, so the response only acknowledges that the request is being processed.
      security:
        - secretKey: []
      parameters:
        - name: limit
          in: query
          description: Number of records per page in the export (e.g., 20).
          schema:
            type: integer
        - name: page
          in: query
          description: Page number to export.
          schema:
            type: integer
        - name: sortBy
          in: query
          description: Field to sort the export by (e.g., creation date, amount).
          schema:
            type: string
        - name: sortType
          in: query
          description: "Sorting direction: 1 = ascending, -1 = descending."
          schema:
            type: integer
            enum:
              - 1
              - -1
        - name: paymentType
          in: query
          description: Filter by payment type. Use `all` for no filtering.
          schema:
            type: string
        - name: paymentStatus
          in: query
          description: Filter by payment status.
          schema:
            type: string
        - name: currency
          in: query
          description: ISO 4217 currency code, or a virtual currency view code.
          schema:
            type: string
        - name: startDate
          in: query
          description: Start of the creation date range.
          schema:
            type: string
        - name: endDate
          in: query
          description: End of the creation date range.
          schema:
            type: string
        - name: endDueDate
          in: query
          description: Latest due date to include.
          schema:
            type: string
        - name: startAmountRange
          in: query
          description: Minimum total amount. Leave empty for no lower limit.
          schema:
            type: string
        - name: endAmountRange
          in: query
          description: Maximum total amount. Leave empty for no upper limit.
          schema:
            type: string
        - name: search
          in: query
          description: Search keyword (e.g., customer name, reference id).
          schema:
            type: string
      responses:
        "200":
          description: Export accepted for processing — an email with the export follows shortly.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
              examples:
                processing:
                  value:
                    message: Your request is being processed. You will receive an email shortly.
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentRequest/saveInvoice:
    post:
      operationId: saveImportedPaymentLinks
      tags:
        - Payment links
      summary: Save the uploaded payment links
      description: Step 2 of the bulk upload. Persists the payment links that were validated by importPaymentLinks, identified by the correlationId returned there. Separating validation from the write keeps a partially invalid sheet from creating any links.
      security:
        - secretKey: []
      parameters:
        - name: correlationId
          in: query
          required: true
          description: The `correlationId` returned by the import step.
          schema:
            type: string
        - name: operation
          in: query
          required: true
          description: The operation to perform on the validated data. Send `save`.
          schema:
            type: string
            enum:
              - save
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
            examples:
              empty:
                summary: No body is needed — the correlationId carries the data
                value: {}
      responses:
        "200":
          description: The payment links that were created from the validated sheet.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/PaymentLinkSummary"
              examples:
                saved:
                  value:
                    - _id: 68ad897323a08c00122d984e
                      description: ""
                      paymentStatus: unpaid
                      dueDate: null
                      isSuspendedPayment: false
                      currency: EGP
                      isBulkCreated: true
                      isPaymentLink: true
                      isDeleted: false
                      customer: null
                      labels:
                        - Label 1
                        - Label 2
                      merchantId: MID-XXXXX-XXX
                      storeName: TEST-Demo
                      invoiceReferenceId: Abc_12345678
                      paymentType: professional
                      totalAmount: 100
                      creationDate: 2025-08-26 10:16:19.043000+00:00
                      customerName: John Doe
                      state: submitted
                      paymentRequestId: INV-24358575129
                      paymentLinkId: PL-24358575129
                      merchantInfo:
                        storeName: TEST-Demo
                      referenceId: Abc_12345678
                      transactions: []
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentPage:
    post:
      operationId: createPaymentPage
      tags:
        - Payment pages
      summary: Create payment page
      description: Creates a payment page. Kashier mints a link identifier (PP-…) for the page, which is what the public URL and the /public reads are keyed on. Set paymentObject.isFixed to collect one fixed amount, or leave it false to let the customer enter the amount.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PaymentPageCreateRequest"
            examples:
              regular:
                summary: Regular page collecting a fixed amount
                value:
                  pageName: Q1 Sales Page
                  description: Payment page for Q1
                  currency: EGP
                  type: regular
                  isMobileRequired: true
                  isEmailRequired: true
                  paymentMethods:
                    - card
                  paymentObject:
                    isFixed: true
                    amount: "100.00"
                  tax: 0
                  isShippable: false
                  isPublished: true
              product:
                summary: Product page with a catalogue and an extra field
                value:
                  pageName: Online Store
                  description: Our product catalogue
                  currency: EGP
                  type: product
                  isMobileRequired: true
                  isEmailRequired: true
                  paymentMethods:
                    - card
                    - wallet
                  paymentObject:
                    isFixed: false
                  tax: 14
                  isShippable: false
                  isPublished: true
                  extraFields:
                    - fieldName: Company name
                      dataType: string
                      isRequired: false
                  additionalFees:
                    - feeName: Handling
                      flatFee: 5
                      rateFee: 0
                  products:
                    - productName: Laptop stand
                      productDescription: Aluminium, adjustable
                      productQuantity: "25"
                      productUnitPrice: "100.00"
                      currency: EGP
      responses:
        "201":
          description: The created payment page, including the `linkId` its public URL is built from.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/PaymentPage"
                  message:
                    type: string
              examples:
                created:
                  value:
                    body:
                      _id: 507f1f77bcf86cd799439011
                      linkId: PP-XXXXXXXXXX
                      merchantId: MID-XXXX-XXXX
                      pageName: Q1 Sales Page
                      description: Payment page for Q1
                      type: regular
                      currency: EGP
                      isMobileRequired: true
                      isEmailRequired: true
                      isPublished: true
                      isShippable: false
                      paymentMethods:
                        - card
                      paymentObject:
                        isFixed: true
                        amount: 100
                      tax: 0
                      totalPaidAmount: 0
                      totalPaymentCount: 0
                      totalPendingCount: 0
                      creationDate: 2026-07-30 09:12:44.201000+00:00
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
    get:
      operationId: listPaymentPages
      tags:
        - Payment pages
      summary: List payment pages
      description: Lists your payment pages, with pagination, filtering, and search.
      security:
        - secretKey: []
      parameters:
        - name: type
          in: query
          description: Filter by page type.
          schema:
            type: string
            enum:
              - regular
              - product
        - name: currency
          in: query
          description: Filter by ISO 4217 currency code (e.g., EGP).
          schema:
            type: string
        - name: search
          in: query
          description: Search by page name.
          schema:
            type: string
        - name: isPublished
          in: query
          description: Filter by whether the page is published.
          schema:
            type: boolean
        - name: sortBy
          in: query
          description: Field to sort by (e.g., creationDate).
          schema:
            type: string
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
      responses:
        "200":
          description: The payment pages list with pagination info.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: array
                    items:
                      $ref: "#/components/schemas/PaymentPage"
                  pagination:
                    $ref: "#/components/schemas/PaymentPagePagination"
                  message:
                    type: string
              examples:
                pages:
                  summary: One page (list abridged)
                  value:
                    body:
                      - _id: 507f1f77bcf86cd799439011
                        linkId: PP-XXXXXXXXXX
                        merchantId: MID-XXXX-XXXX
                        pageName: Q1 Sales Page
                        type: regular
                        currency: EGP
                        isPublished: true
                        totalPaidAmount: 400
                        totalPaymentCount: 4
                        creationDate: 2026-07-30 09:12:44.201000+00:00
                    pagination:
                      total: 12
                      limit: 20
                      page: 1
                      pages: 1
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentPage/{id}:
    get:
      operationId: getPaymentPage
      tags:
        - Payment pages
      summary: Get payment page
      description: Retrieves a single payment page, including its products, extra fields, and fees.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The payment page identifier returned when the page was created.
          schema:
            type: string
      responses:
        "200":
          description: The payment page details.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/PaymentPage"
                  message:
                    type: string
              examples:
                page:
                  value:
                    body:
                      _id: 507f1f77bcf86cd799439011
                      linkId: PP-XXXXXXXXXX
                      merchantId: MID-XXXX-XXXX
                      pageName: Online Store
                      description: Our product catalogue
                      type: product
                      currency: EGP
                      isPublished: true
                      isShippable: false
                      paymentMethods:
                        - card
                        - wallet
                      tax: 14
                      totalPaidAmount: 400
                      totalPaymentCount: 4
                      totalPendingCount: 1
                      extraFields:
                        - fieldName: Company name
                          dataType: string
                          isRequired: false
                          isDeleted: false
                      additionalFees:
                        - feeName: Handling
                          flatFee: 5
                          rateFee: 0
                          isDeleted: false
                      products:
                        - productId: PROD-001
                          productName: Laptop stand
                          productDescription: Aluminium, adjustable
                          productQuantity: "25"
                          productUnitPrice: "100.00"
                          currency: EGP
                      creationDate: 2026-07-30 09:12:44.201000+00:00
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    put:
      operationId: updatePaymentPage
      tags:
        - Payment pages
      summary: Update payment page
      description: "Updates a payment page. Send only the fields you want to change; anything you omit keeps its current value. Unpublishing a page (isPublished: false) takes it offline without deleting it."
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The payment page identifier.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PaymentPageUpdateRequest"
            examples:
              rename:
                summary: Rename the page and change the fixed amount
                value:
                  pageName: Updated Page Name
                  description: Updated description
                  currency: EGP
                  paymentObject:
                    isFixed: true
                    amount: "100.00"
                  isMobileRequired: true
                  isEmailRequired: false
      responses:
        "200":
          description: The updated payment page.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/PaymentPage"
                  message:
                    type: string
              examples:
                updated:
                  value:
                    body:
                      _id: 507f1f77bcf86cd799439011
                      linkId: PP-XXXXXXXXXX
                      merchantId: MID-XXXX-XXXX
                      pageName: Updated Page Name
                      description: Updated description
                      currency: EGP
                      paymentObject:
                        isFixed: true
                        amount: 100
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    delete:
      operationId: deletePaymentPage
      tags:
        - Payment pages
      summary: Delete payment page
      description: Deletes a payment page. The page is soft-deleted — the public link stops working and the page drops out of [List payment pages](#operation/listPaymentPages), but the payments already collected against it are retained.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The payment page identifier.
          schema:
            type: string
      responses:
        "200":
          description: The payment page was deleted.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: object
                    additionalProperties: true
                  message:
                    type: string
              examples:
                deleted:
                  value:
                    body:
                      _id: 507f1f77bcf86cd799439011
                      deletedAt: 2026-07-30 09:20:11.004000+00:00
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentPage/{id}/payments:
    get:
      operationId: listPaymentPagePayments
      tags:
        - Payment pages
      summary: List payments for a payment page
      description: Lists the payments collected against one payment page, with pagination. Each record carries the customer details captured on the page and the underlying card, wallet, or cash-on-delivery transactions.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The payment page identifier.
          schema:
            type: string
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
      responses:
        "200":
          description: The payments list with pagination info.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: array
                    items:
                      $ref: "#/components/schemas/PaymentPagePayment"
                  pagination:
                    $ref: "#/components/schemas/PaymentPagePagination"
                  message:
                    type: string
              examples:
                payments:
                  summary: One successful payment (list abridged)
                  value:
                    body:
                      - _id: 507f1f77bcf86cd799439012
                        merchantId: MID-XXXX-XXXX
                        merchantOrderId: ORDER-001
                        paymentPageName: Q1 Sales Page
                        firstName: Ahmed
                        lastName: Hassan
                        email: customer@example.com
                        phone: "+201000000000"
                        amount: 100
                        subAmount: 100
                        tax: 0
                        paymentMethod: card
                        status: success
                        date: 2026-07-30 09:15:02.117000+00:00
                        transactions:
                          - transactionInfoId: TX-243585751279
                            merchantOrderId: ORDER-001
                            amount: 100
                            currency: EGP
                            status: SUCCESS
                            type: card
                    pagination:
                      total: 4
                      limit: 20
                      page: 1
                      pages: 1
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentPage/{id}/public:
    get:
      operationId: getPublicPaymentPage
      tags:
        - Payment pages
      summary: Get public payment page
      description: Retrieves the customer-facing view of a published payment page. No authentication — this is the read the hosted page itself performs to render your catalogue, so it returns only what is safe to show a shopper. Returns 404 while the page is unpublished or deleted.
      security: []
      parameters:
        - name: id
          in: path
          required: true
          description: The payment page link identifier (e.g., `PP-XXXXXXXXXX`).
          schema:
            type: string
        - name: q
          in: query
          description: Search term applied to the page's products.
          schema:
            type: string
        - name: categoriesIds
          in: query
          description: Comma-separated category identifiers to filter the products by.
          schema:
            type: string
      responses:
        "200":
          description: The public payment page view.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/PaymentPage"
                  message:
                    type: string
              examples:
                page:
                  value:
                    body:
                      _id: 507f1f77bcf86cd799439011
                      linkId: PP-XXXXXXXXXX
                      pageName: Online Store
                      description: Our product catalogue
                      type: product
                      currency: EGP
                      isMobileRequired: true
                      isEmailRequired: true
                      paymentMethods:
                        - card
                        - wallet
                      tax: 14
                      products:
                        - productId: PROD-001
                          productName: Laptop stand
                          productUnitPrice: "100.00"
                          currency: EGP
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentPage/share:
    post:
      operationId: sharePaymentPage
      tags:
        - Payment pages
      summary: Share payment page
      description: Sends a payment page's link to one or more recipients by email or SMS. Pass every recipient in key to send a single batch.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PaymentPageShareRequest"
            examples:
              email:
                summary: Share by email with two recipients
                value:
                  operation: email
                  key:
                    - customer@example.com
                    - buyer@example.com
                  id: PP-XXXXXXXXXX
              sms:
                summary: Share by SMS
                value:
                  operation: sms
                  key:
                    - "+201000000000"
                  id: PP-XXXXXXXXXX
      responses:
        "200":
          description: The page link was queued for delivery.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: object
                    additionalProperties: true
                  message:
                    type: string
              examples:
                shared:
                  value:
                    body:
                      paymentPageId: 507f1f77bcf86cd799439011
                      sharedWith:
                        - customer@example.com
                        - buyer@example.com
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentPage/transactions/{orderId}:
    get:
      operationId: getPaymentPagePayment
      tags:
        - Payment pages
      summary: Get a payment page payment
      description: Retrieves one payment collected through a payment page, looked up by the order id the page assigned to it.
      security:
        - secretKey: []
      parameters:
        - name: orderId
          in: path
          required: true
          description: The order identifier of the payment page payment.
          schema:
            type: string
      responses:
        "200":
          description: The payment details.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/PaymentPagePayment"
                  message:
                    type: string
              examples:
                payment:
                  value:
                    body:
                      _id: 507f1f77bcf86cd799439012
                      merchantId: MID-XXXX-XXXX
                      merchantOrderId: ORDER-001
                      paymentPageName: Q1 Sales Page
                      firstName: Ahmed
                      lastName: Hassan
                      email: customer@example.com
                      amount: 100
                      tax: 0
                      paymentMethod: card
                      status: success
                      date: 2026-07-30 09:15:02.117000+00:00
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentPage/transactions/{orderId}/public:
    get:
      operationId: getPublicPaymentPagePayment
      tags:
        - Payment pages
      summary: Get a payment page payment (public)
      description: The customer-facing view of one payment page payment. No authentication — this is the read the hosted page performs on its own confirmation screen. Returns 404 when the order does not exist.
      security: []
      parameters:
        - name: orderId
          in: path
          required: true
          description: The order identifier of the payment page payment.
          schema:
            type: string
      responses:
        "200":
          description: The public payment view.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/PaymentPagePayment"
                  message:
                    type: string
              examples:
                payment:
                  value:
                    body:
                      merchantOrderId: ORDER-001
                      paymentPageName: Q1 Sales Page
                      amount: 100
                      tax: 0
                      paymentMethod: card
                      status: success
                      date: 2026-07-30 09:15:02.117000+00:00
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentPage/export:
    get:
      operationId: exportPaymentPages
      tags:
        - Payment pages
      summary: Export payment pages
      description: Exports your payment pages as a spreadsheet, returned inline in the response. For a wide date range use [Export payment pages asynchronously](#operation/exportPaymentPagesAsync) instead.
      security:
        - secretKey: []
      parameters:
        - name: type
          in: query
          description: Filter by page type.
          schema:
            type: string
            enum:
              - regular
              - product
        - name: isPublished
          in: query
          description: Filter by whether the page is published.
          schema:
            type: boolean
        - name: search
          in: query
          description: Search by page name.
          schema:
            type: string
      responses:
        "200":
          description: The payment pages spreadsheet.
          content:
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentPage/export-async:
    get:
      operationId: exportPaymentPagesAsync
      tags:
        - Payment pages
      summary: Export payment pages asynchronously
      description: Starts a payment pages export in the background and emails the finished file to the account that made the request.
      security:
        - secretKey: []
      parameters:
        - name: type
          in: query
          description: Filter by page type.
          schema:
            type: string
            enum:
              - regular
              - product
        - name: isPublished
          in: query
          description: Filter by whether the page is published.
          schema:
            type: boolean
        - name: fromDate
          in: query
          description: Start of the creation-date range (e.g., 2026-01-01).
          schema:
            type: string
        - name: toDate
          in: query
          description: End of the creation-date range (e.g., 2026-12-31).
          schema:
            type: string
        - name: search
          in: query
          description: Search by page name.
          schema:
            type: string
        - name: sortBy
          in: query
          description: Field to sort by (e.g., creationDate).
          schema:
            type: string
      responses:
        "200":
          description: Export accepted for processing — the file is emailed when it is ready.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: object
                    additionalProperties: true
                  message:
                    type: string
              examples:
                processing:
                  value:
                    body:
                      status: processing
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentPage/payments/{paymentPageId}/export:
    get:
      operationId: exportPaymentPagePayments
      tags:
        - Payment pages
      summary: Export payments for a payment page
      description: Exports the payments collected against one payment page as a spreadsheet, returned inline in the response.
      security:
        - secretKey: []
      parameters:
        - name: paymentPageId
          in: path
          required: true
          description: The payment page identifier.
          schema:
            type: string
      responses:
        "200":
          description: The payments spreadsheet.
          content:
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/paymentPage/payments/{paymentPageId}/export-async:
    get:
      operationId: exportPaymentPagePaymentsAsync
      tags:
        - Payment pages
      summary: Export payments for a payment page asynchronously
      description: Starts an export of one page's payments in the background and emails the finished file to the account that made the request.
      security:
        - secretKey: []
      parameters:
        - name: paymentPageId
          in: path
          required: true
          description: The payment page identifier.
          schema:
            type: string
        - name: fromDate
          in: query
          description: Start of the payment-date range (e.g., 2026-01-01).
          schema:
            type: string
        - name: toDate
          in: query
          description: End of the payment-date range (e.g., 2026-12-31).
          schema:
            type: string
        - name: search
          in: query
          description: Search term applied to the payments.
          schema:
            type: string
      responses:
        "200":
          description: Export accepted for processing — the file is emailed when it is ready.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: object
                    additionalProperties: true
                  message:
                    type: string
              examples:
                processing:
                  value:
                    body:
                      status: processing
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/transfers/schedulers:
    get:
      operationId: listPayoutSchedulers
      tags:
        - Payouts
      summary: List payout schedulers
      description: Lists your recurring payout schedulers, with pagination. A scheduler is a saved transfer template that Kashier re-runs on the frequency you set, so you can pay a recurring salary or a monthly supplier invoice without calling [Create transfer](#operation/createTransfer) every cycle.
      security:
        - secretKey: []
      parameters:
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
      responses:
        "200":
          description: The schedulers list with pagination info.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      schedulers:
                        type: array
                        items:
                          $ref: "#/components/schemas/PayoutScheduler"
                  pagination:
                    $ref: "#/components/schemas/PayoutPagination"
              examples:
                schedulers:
                  value:
                    message: success
                    data:
                      schedulers:
                        - merchantTransferId: transfer12349
                          recipientName: Ahmed Mohamed
                          recipientNumber: "1012345678"
                          recipientBank: CIB
                          amount: 100
                          method: bank
                          status: ACTIVE
                          createdAt: 2026-06-18 10:30:00+00:00
                    pagination:
                      total: 5
                      limit: 20
                      page: 1
                      pages: 1
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/transfers/schedulers/{schedulerId}:
    get:
      operationId: getPayoutScheduler
      tags:
        - Payouts
      summary: Get payout scheduler details
      description: Retrieves one recurring payout scheduler, including the transfer template it repeats, its recurring frequency, and the date it next runs.
      security:
        - secretKey: []
      parameters:
        - name: schedulerId
          in: path
          required: true
          description: The scheduler id returned when the scheduler was created.
          schema:
            type: string
      responses:
        "200":
          description: The scheduler details.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    $ref: "#/components/schemas/PayoutScheduler"
              examples:
                scheduler:
                  value:
                    message: success
                    data:
                      merchantTransferId: transfer12349
                      recipientName: Ahmed Mohamed
                      recipientNumber: "1012345678"
                      recipientBank: CIB
                      amount: 100
                      method: bank
                      status: ACTIVE
                      createdAt: 2026-06-18 10:30:00+00:00
                      recurringFrequency: MONTHLY
                      nextRun: 2026-07-18 10:30:00+00:00
        "404":
          description: No scheduler with that id belongs to this merchant.
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/transfers/schedulers/single:
    post:
      operationId: createPayoutScheduler
      tags:
        - Payouts
      summary: Create payout scheduler
      description: |-
        Creates a recurring payout scheduler from a single transfer template. Kashier repeats the transfer on the recurringFrequency you set, starting on startDate, until you deactivate the scheduler or it passes its endDate. Each run produces an ordinary transfer you can follow with [Get transfer details](#operation/getTransferDetails).
        The recipient rules are the same as for a one-off transfer: recipientBank is required when method is bank or card, and wallet recipients must be an Egyptian mobile number.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PayoutCreateSchedulerRequest"
            examples:
              monthlyPayroll:
                summary: Pay a supplier the same amount every month
                value:
                  batchName: Monthly supplier payout
                  type: single
                  scheduler:
                    method: bank
                    recipientName: Ahmed Mohamed
                    recipientNumber: "1012345678"
                    recipientBank: CIB
                    amount: 100
                    startDate: 2026-08-01 00:00:00+00:00
                    recurringFrequency: MONTHLY
      responses:
        "200":
          description: The scheduler was created and is active.
          content:
            application/json:
              schema:
                type: object
                properties:
                  messages:
                    $ref: "#/components/schemas/PayoutMessages"
                  data:
                    $ref: "#/components/schemas/PayoutScheduler"
              examples:
                created:
                  value:
                    messages:
                      en: We're processing your transfer.
                      ar: .جاري معالجة المعاملة
                    data:
                      schedulerId: 507f1f77bcf86cd799439011
                      merchantTransferId: transfer12349
                      recipientName: Ahmed Mohamed
                      recipientNumber: "1012345678"
                      recipientBank: CIB
                      amount: 100
                      method: bank
                      status: ACTIVE
                      recurringFrequency: MONTHLY
                      nextRun: 2026-08-01 00:00:00+00:00
                      createdAt: 2026-07-30 10:30:00+00:00
        "400":
          description: The scheduler body failed validation.
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/transfers/batch:
    get:
      operationId: listTransferBatches
      tags:
        - Payouts
      summary: List payout batches
      description: Lists your payout batches, with pagination. Every bulk payout you submit with [Bulk transfers](#operation/createBulkTransfer) becomes a batch whose row shows how many of its transfers have succeeded and how many have failed, so you can watch a payroll run finish without polling each transfer.
      security:
        - secretKey: []
      parameters:
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
      responses:
        "200":
          description: The batches list with pagination info.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      batches:
                        type: array
                        items:
                          $ref: "#/components/schemas/PayoutBatchSummary"
                  pagination:
                    $ref: "#/components/schemas/PayoutPagination"
              examples:
                batches:
                  value:
                    message: success
                    data:
                      batches:
                        - batchId: BTH-1007931100
                          merchantBatchId: batch12349
                          batchName: Monthly payroll
                          totalCount: 150
                          successCount: 148
                          failureCount: 2
                          status: COMPLETED
                          createdAt: 2026-06-18 10:30:00+00:00
                    pagination:
                      total: 5
                      limit: 20
                      page: 1
                      pages: 1
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/transfers/batch/{batchId}:
    get:
      operationId: getTransferBatch
      tags:
        - Payouts
      summary: Get payout batch details
      description: Retrieves one payout batch together with the transfers it contains, paginated. Use it to find which rows of a bulk payout failed and why.
      security:
        - secretKey: []
      parameters:
        - name: batchId
          in: path
          required: true
          description: The batch id (e.g., `BTH-1007931100`).
          schema:
            type: string
        - name: limit
          in: query
          description: Number of transfers per page.
          schema:
            type: integer
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
      responses:
        "200":
          description: The batch details and its transfers.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    $ref: "#/components/schemas/PayoutBatchDetails"
                  pagination:
                    $ref: "#/components/schemas/PayoutPagination"
              examples:
                batch:
                  value:
                    message: success
                    data:
                      batchId: BTH-1007931100
                      merchantBatchId: batch12349
                      batchName: Monthly payroll
                      totalCount: 150
                      successCount: 148
                      failureCount: 2
                      status: COMPLETED
                      createdAt: 2026-06-18 10:30:00+00:00
                      updatedAt: 2026-06-18 11:45:00+00:00
                      transfers:
                        - transferId: TRS-1007931100
                          status: TRANSFERRED
                          amount: 100
                    pagination:
                      total: 150
                      limit: 20
                      page: 1
                      pages: 8
        "404":
          description: No batch with that id belongs to this merchant.
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/transfers/merchant-transfer-id/{merchantTransferId}:
    get:
      operationId: getTransferByMerchantTransferId
      tags:
        - Payouts
      summary: Get transfer by merchant transfer id
      description: Retrieves a payout transfer using the merchantTransferId your own systems assigned to it, so you can reconcile against your records without having to store Kashier's transferId. merchantTransferId is unique per merchant.
      security:
        - secretKey: []
      parameters:
        - name: merchantTransferId
          in: path
          required: true
          description: The unique identifier your systems assigned to the transfer.
          schema:
            type: string
      responses:
        "200":
          description: The transfer matching that merchant transfer id.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PayoutTransfer"
              examples:
                transfer:
                  value:
                    transferId: TRS-1007931100
                    merchantTransferId: transfer12349
                    recipientName: Ahmed Mohamed
                    recipientNumber: "1012345678"
                    recipientBank: CIB
                    amount: 100
                    method: bank
                    status: TRANSFERRED
                    createdAt: 2026-06-18 10:30:00+00:00
                    updatedAt: 2026-06-18 11:45:00+00:00
        "404":
          description: No transfer with that merchant transfer id belongs to this merchant.
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/cards/tokens:
    servers:
      - url: https://test-fep.kashier.io
        description: Test — no real money moves
    post:
      operationId: createToken
      tags:
        - Tokens
      summary: Create token
      description: |-
        Saves a card and returns a reusable cardToken you can charge later with [Pay with token](#operation/payWithToken). Send the raw card details once; Kashier stores them and hands back only the token and a masked card number, so your systems never have to keep the PAN.
        The request is validated with a Kashier-Hash header — an HMAC SHA256 hash of the path /?tokenization={merchantId}.{customerReference} generated from your backend with your secret. Use only those parameters in the hash creation; don't add extra parameters.
        The securityCode (CVV) you submit is exchanged for a **single-use** cvvToken; a stored token cannot be reused as a CVV on a later payment.
      security: []
      parameters:
        - $ref: "#/components/parameters/KashierHash"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TokenizationCreateTokenRequest"
            examples:
              createToken:
                summary: Tokenize a card for a customer
                value:
                  merchantId: YOUR_MID
                  customerReference: CUST-001
                  paymentMethod:
                    type: CARD
                    card:
                      number: "5123456789012346"
                      expiry:
                        month: "12"
                        year: "25"
                      nameOnCard: John Doe
                      securityCode: "123"
                  customer:
                    reference: CUST-001
      responses:
        "200":
          description: The card was tokenized successfully.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TokenizationCreateTokenResponse"
              examples:
                created:
                  value:
                    status: SUCCESS
                    messages:
                      en: Card is tokenized successfully
                      ar: Card is tokenized successfully
                    response:
                      paymentMethod:
                        type: CARD
                        card:
                          number: 512345********2346
                          cardToken: 7a5e3c72-61d9-4ebf-88b9-27dc0f77b638
                          cardDataToken: 7a5e3c72-61d9-4ebf-88b9-27dc0f77b638
                          cvvToken: 9d8332cb-6195-40ea-aed0-86c3aa60fbaa
                          agreement:
                            type: perm
                            id: 886f122a-2d9e-4a35-8be8-79fdd88b9ffd
        "400":
          description: The request body failed validation, or the `Kashier-Hash` header is missing or invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TokenizationError"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/account/overview/accounts-list:
    get:
      operationId: listBalanceAccountsOverview
      tags:
        - Balance and accounts
      summary: List balance accounts
      description: Lists the balance accounts belonging to the merchant identified by the secret key, with the current balance of each. This is the entry point for the balance overview — take an accountId from here and pass it to the other overview and records reads.
      security:
        - secretKey: []
      parameters:
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
      responses:
        "200":
          description: The merchant's balance accounts.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/BalanceAccount"
                  pagination:
                    $ref: "#/components/schemas/BalancePagination"
              examples:
                accounts:
                  value:
                    message: success
                    data:
                      - _id: 66c4d1f2a3b45c0012ef7a91
                        accountId: ACC-XXXX-XXX-01
                        merchantId: YOUR_MID
                        merchantName: Your store
                        totalBalance: 12500.5
                        availableBalance: 11200
                        allowedNegativeBalance: 0
                        isIncludeInBulkTransfer: false
                        createdAt: 2025-01-01 10:00:00+00:00
                        updatedAt: 2025-06-01 09:15:00+00:00
                    pagination:
                      total: 1
                      limit: 20
                      page: 1
                      pages: 1
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/account/overview/{accountId}:
    get:
      operationId: getBalanceAccountOverview
      tags:
        - Balance and accounts
      summary: Get balance account overview
      description: Retrieves the balance overview of a single account — the headline figures (total balance, available balance) you would show on a dashboard. Use GET /v2/account/{accountId} instead when you need the full account document including its payout method.
      security:
        - secretKey: []
      parameters:
        - $ref: "#/components/parameters/BalanceAccountId"
      responses:
        "200":
          description: The account's balance overview.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    $ref: "#/components/schemas/BalanceAccount"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/account/overview/payments/{accountId}:
    get:
      operationId: getBalancePaymentsOverview
      tags:
        - Balance and accounts
      summary: Get payments overview for an account
      description: Summarises the money that came **into** a balance account over a date range — the settled payments credited to it. Pair it with the payouts overview to see both sides of the account for the same period.
      security:
        - secretKey: []
      parameters:
        - $ref: "#/components/parameters/BalanceAccountId"
        - $ref: "#/components/parameters/BalanceDateFrom"
        - $ref: "#/components/parameters/BalanceDateTo"
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
      responses:
        "200":
          description: Aggregated payments credited to the account for the requested period.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BalanceOverviewSummary"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/account/overview/payouts/{accountId}:
    get:
      operationId: getBalancePayoutsOverview
      tags:
        - Balance and accounts
      summary: Get payouts overview for an account
      description: Summarises the money that left a balance account over a date range — the payouts debited from it. Pair it with the payments overview to see both sides of the account for the same period.
      security:
        - secretKey: []
      parameters:
        - $ref: "#/components/parameters/BalanceAccountId"
        - $ref: "#/components/parameters/BalanceDateFrom"
        - $ref: "#/components/parameters/BalanceDateTo"
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
      responses:
        "200":
          description: Aggregated payouts debited from the account for the requested period.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BalanceOverviewSummary"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/account/{accountId}:
    get:
      operationId: getBalanceAccountDetails
      tags:
        - Balance and accounts
      summary: Get balance account details
      description: Retrieves one balance account in full — balances, the payout method money leaves by, and the last transfer made from it. GET /v2/account returns the same document for every account you own; use this read when you already know the accountId.
      security:
        - secretKey: []
      parameters:
        - $ref: "#/components/parameters/BalanceAccountId"
      responses:
        "200":
          description: The account document.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    $ref: "#/components/schemas/BalanceAccount"
              examples:
                account:
                  value:
                    message: success
                    data:
                      _id: 66c4d1f2a3b45c0012ef7a91
                      accountId: ACC-XXXX-XXX-01
                      merchantId: YOUR_MID
                      merchantName: Your store
                      totalBalance: 12500.5
                      availableBalance: 11200
                      allowedNegativeBalance: 0
                      isIncludeInBulkTransfer: false
                      lastTransfer: 1000
                      totalBalanceBeforeLastTransfer: 13500.5
                      lastTransferDate: 2025-05-08 11:19:15.656000+00:00
                      payoutMethod:
                        method: bankAccount
                        payoutFields:
                          bankName: AAIB
                          bankBranch: Your branch
                          accountHolderName: Your company name
                          accountNumber: "0100010001000"
                          branchCode: "3"
                      createdAt: 2025-01-01 10:00:00+00:00
                      updatedAt: 2025-06-01 09:15:00+00:00
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/account/{accountId}/records:
    get:
      operationId: listBalanceAccountRecords
      tags:
        - Balance and accounts
      summary: List balance records for an account
      description: Lists the balance records of one account, newest first — the statement lines behind the balance. Each record is a single movement (a settlement credit, a payout debit, a refund, or an adjustment) and carries the operation that caused it plus the reference of the thing that originated it. Call GET /v2/balance/record-details/{recordId} for the full detail of any one line.
      security:
        - secretKey: []
      parameters:
        - $ref: "#/components/parameters/BalanceAccountId"
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: type
          in: query
          description: Filter by record type.
          schema:
            type: string
      responses:
        "200":
          description: The account's balance records, with pagination.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/BalanceRecord"
                  pagination:
                    $ref: "#/components/schemas/BalancePagination"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/account/{accountId}/records/export:
    get:
      operationId: exportBalanceAccountRecords
      tags:
        - Balance and accounts
      summary: Export balance records for an account
      description: Exports one account's balance records as a spreadsheet, applying the same filters as the records list. Pass email to have the export delivered to that address instead of returned in the response.
      security:
        - secretKey: []
      parameters:
        - $ref: "#/components/parameters/BalanceAccountId"
        - name: email
          in: query
          description: Email address the export is sent to.
          schema:
            type: string
        - name: format
          in: query
          description: Export file format.
          schema:
            type: string
      responses:
        "200":
          description: The exported records file.
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/account/export:
    get:
      operationId: exportBalanceAccounts
      tags:
        - Balance and accounts
      summary: Export balance accounts
      description: Exports the merchant's balance accounts and their balances as a spreadsheet. Pass email to have the export delivered to that address instead of returned in the response.
      security:
        - secretKey: []
      parameters:
        - name: email
          in: query
          description: Email address the export is sent to.
          schema:
            type: string
        - name: format
          in: query
          description: Export file format.
          schema:
            type: string
        - $ref: "#/components/parameters/BalanceDateFrom"
        - $ref: "#/components/parameters/BalanceDateTo"
      responses:
        "200":
          description: The exported accounts file.
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/account/search:
    get:
      operationId: searchBalanceAccounts
      tags:
        - Balance and accounts
      summary: Search balance accounts by name
      description: Looks up your balance accounts by name and returns just the id and name of each match — a lightweight read for populating an account picker before calling one of the detail reads.
      security:
        - secretKey: []
      parameters:
        - name: q
          in: query
          description: Search term matched against the account name.
          schema:
            type: string
        - name: limit
          in: query
          description: Maximum number of results to return.
          schema:
            type: integer
      responses:
        "200":
          description: Matching accounts, reduced to id and name.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        accountId:
                          type: string
                        accountName:
                          type: string
              examples:
                matches:
                  value:
                    data:
                      - accountId: ACC-XXXX-XXX-01
                        accountName: Primary account
                      - accountId: ACC-XXXX-XXX-02
                        accountName: Secondary account
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/account/payoutMethod:
    get:
      operationId: getPrimaryAccountPayoutMethod
      tags:
        - Balance and accounts
      summary: Get the primary account's payout method
      description: "Retrieves the payout method configured on your primary balance account — the bank account or wallet that settled money is paid out to. The fields inside payoutFields depend on method: a bank account carries the bank, branch, account holder, and account number, while a wallet carries the wallet number."
      security:
        - secretKey: []
      responses:
        "200":
          description: The primary account's payout method.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    $ref: "#/components/schemas/BalancePayoutMethod"
              examples:
                bankAccount:
                  summary: Payout to a bank account
                  value:
                    message: success
                    data:
                      method: bankAccount
                      payoutFields:
                        bankName: AAIB
                        bankBranch: Your branch
                        accountHolderName: Your company name
                        accountNumber: "0100010001000"
                        branchCode: "3"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/balance/record-details/{recordId}:
    get:
      operationId: getBalanceRecordDetails
      tags:
        - Balance and accounts
      summary: Get balance record details
      description: Retrieves one balance record in full — the amount, whether it credited or debited the account, the value date the money counted from, and the origin/originReference pointing back at whatever produced it (a settlement batch id, a payout, or an adjustment reference). This is how you trace a line on the statement back to its cause.
      security:
        - secretKey: []
      parameters:
        - $ref: "#/components/parameters/BalanceRecordId"
      responses:
        "200":
          description: The balance record.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BalanceRecord"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/balance/payout-details/{recordId}:
    get:
      operationId: getBalancePayoutDetails
      tags:
        - Balance and accounts
      summary: Get payout details for a balance record
      description: Expands a payout balance record into the individual transactions it paid out. Use it to answer "which sales made up this payout?" — the record gives you the total that left the account, and this read gives you the lines behind it, with pagination and date filters.
      security:
        - secretKey: []
      parameters:
        - $ref: "#/components/parameters/BalanceRecordId"
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: sortBy
          in: query
          description: Field to sort by.
          schema:
            type: string
        - name: sortOrder
          in: query
          description: "Sorting direction: `asc` or `desc`."
          schema:
            type: string
            enum:
              - asc
              - desc
        - name: status
          in: query
          description: Filter by status.
          schema:
            type: string
        - $ref: "#/components/parameters/BalanceDateFrom"
        - $ref: "#/components/parameters/BalanceDateTo"
      responses:
        "200":
          description: The payout record and the transactions it covers.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                properties:
                  recordId:
                    type: string
                  accountId:
                    type: string
                  amount:
                    type: number
                    description: Total amount paid out.
                  status:
                    type: string
                  payoutDate:
                    type: string
                  totalTransactions:
                    type: integer
                  transactions:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/balance/payout-details/{recordId}/export:
    get:
      operationId: exportBalancePayoutDetails
      tags:
        - Balance and accounts
      summary: Export payout details for a balance record
      description: Exports the transactions behind a payout balance record as a spreadsheet, applying the same status and date filters as the payout details read.
      security:
        - secretKey: []
      parameters:
        - $ref: "#/components/parameters/BalanceRecordId"
        - name: status
          in: query
          description: Filter by status.
          schema:
            type: string
        - $ref: "#/components/parameters/BalanceDateFrom"
        - $ref: "#/components/parameters/BalanceDateTo"
      responses:
        "200":
          description: The exported payout details file.
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/hold/account/{accountId}:
    get:
      operationId: listBalanceAccountHolds
      tags:
        - Balance and accounts
      summary: List holds on a balance account
      description: Lists the holds placed on a balance account. A hold reserves part of the balance so it cannot be paid out yet — it explains a gap between an account's total balance and its available balance.
      security:
        - secretKey: []
      parameters:
        - $ref: "#/components/parameters/BalanceAccountId"
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: status
          in: query
          description: Filter by hold status.
          schema:
            type: string
      responses:
        "200":
          description: The holds on the account, with pagination.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/BalanceHold"
                  total:
                    type: integer
                  page:
                    type: integer
                  limit:
                    type: integer
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/aggregator/settlement-transactions:
    get:
      operationId: listSettledTransactions
      tags:
        - Settlement reporting
      summary: List settled transactions
      description: Lists your transactions that have been settled, with a summary of the total settled amount alongside the page of results. Use it for a transaction-level view of settlement; use GET /v3/payment/settlement/windows when you want the window and batch grouping instead.
      security:
        - secretKey: []
      parameters:
        - name: page
          in: query
          description: Page number.
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: sortBy
          in: query
          description: Field to sort by.
          schema:
            type: string
        - name: sortDirection
          in: query
          description: "Sorting direction: `asc` or `desc`."
          schema:
            type: string
            enum:
              - asc
              - desc
        - name: sortType
          in: query
          description: "Sorting direction as a number: 1 = ascending, -1 = descending."
          schema:
            type: integer
            enum:
              - 1
              - -1
        - name: search
          in: query
          description: Search term.
          schema:
            type: string
        - name: branchIds
          in: query
          description: Restrict the results to specific branches.
          schema:
            type: string
      responses:
        "200":
          description: The settled transactions, with pagination and a settled-amount summary.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                properties:
                  body:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
                  pagination:
                    $ref: "#/components/schemas/BalancePagination"
                  summary:
                    type: object
                    additionalProperties: true
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/settlement/windows:
    get:
      operationId: listSettlementWindows
      tags:
        - Settlement reporting
      summary: List settlement windows
      description: |
        Lists your settlement windows, newest first. A window groups the transactions that became
        ready for settlement on a given date; when it closes it produces one or more batches, and
        each batch is what actually reaches your bank.

        A window's status is one of:

        - **open** — still accumulating transactions; nothing has been paid out yet.
        - **in_progress** — the window is being closed and its batches produced.
        - **closed** — finalised; the transactions in it have been paid out.
        - **failed** — closing the window failed.

        Add action=export to download the same list as a spreadsheet instead of JSON.

        > Settlement windows exist in **live mode only**. Test mode never produces windows or
        > batches, so this read returns an empty list against the test host.
      security:
        - secretKey: []
      parameters:
        - name: page
          in: query
          description: Page number. Defaults to 1.
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of records per page. Defaults to 20.
          schema:
            type: integer
        - name: sortBy
          in: query
          description: Field to sort by. Defaults to `createdAt`.
          schema:
            type: string
        - name: sortType
          in: query
          description: "Sorting direction: 1 = ascending, -1 = descending. Defaults to -1."
          schema:
            type: integer
            enum:
              - 1
              - -1
        - name: status
          in: query
          description: Filter by window status. `all` applies no status filter, and is the default.
          schema:
            type: string
            enum:
              - all
              - open
              - in_progress
              - closed
              - failed
        - name: q
          in: query
          description: Search term. A value starting with `TX-` is treated as a settlement transaction id and resolves to the window containing that transaction.
          schema:
            type: string
        - name: dateFrom
          in: query
          description: Only return windows on or after this date.
          schema:
            type: string
        - name: action
          in: query
          description: Set to `export` to download the windows list as a spreadsheet instead of JSON.
          schema:
            type: string
            enum:
              - export
      responses:
        "200":
          description: The settlement windows, with pagination.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/SettlementWindow"
                  pagination:
                    $ref: "#/components/schemas/BalancePagination"
              examples:
                windows:
                  value:
                    message: success
                    data:
                      - windowId: STW-XXXXXXXX
                        accountId: ACC-XXXX-XXX-01
                        merchantId: YOUR_MID
                        windowDate: 2025-07-21 00:00
                        status: closed
                        totalOriginalAmount: 5000
                        totalSettlementAmount: 4850.5
                        transactionsCount: 12
                        batchesCount: 2
                        batchesIds: BATCH-XXXX-1,BATCH-XXXX-2,
                    pagination:
                      total: 1
                      limit: 20
                      page: 1
                      pages: 1
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/settlement/windows/{windowId}:
    get:
      operationId: getSettlementWindow
      tags:
        - Settlement reporting
      summary: Get a settlement window
      description: Retrieves one settlement window together with its batches. Each batch carries its own rfsDate (the ready-for-settlement date), channel and method, gross and net amounts, and the fees and VAT taken — the numbers you reconcile a settlement against.
      security:
        - secretKey: []
      parameters:
        - $ref: "#/components/parameters/SettlementWindowId"
      responses:
        "200":
          description: The settlement window and its batches.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    allOf:
                      - $ref: "#/components/schemas/SettlementWindow"
                      - type: object
                        properties:
                          batches:
                            type: array
                            items:
                              $ref: "#/components/schemas/SettlementBatch"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/settlement/windows/{windowId}/batches/{batchId}:
    get:
      operationId: getSettlementWindowBatch
      tags:
        - Settlement reporting
      summary: Get a batch within a settlement window
      description: "Retrieves one batch of one settlement window. This is the last step of reconciling a single order: read the order's settlementWindowId and settlementBatchId from the transaction, then fetch the batch here. A batch inside a closed window has been paid out."
      security:
        - secretKey: []
      parameters:
        - $ref: "#/components/parameters/SettlementWindowId"
        - $ref: "#/components/parameters/SettlementBatchId"
      responses:
        "200":
          description: The batch, with its fee breakdown and settled amount.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    $ref: "#/components/schemas/SettlementBatch"
              examples:
                batch:
                  value:
                    message: success
                    data:
                      batchId: BATCH-XXXX-1
                      rfsDate: 2025-07-23 00:00:00+00:00
                      channel: ECOMMERCE
                      method: card
                      transactionsCount: 8
                      totalOriginalAmount: 3000
                      totalFees: 45
                      totalVat: 6.3
                      totalSettlementAmount: 2948.7
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/settlement/batches/{batchId}:
    get:
      operationId: getSettlementBatch
      tags:
        - Settlement reporting
      summary: Get a settlement batch
      description: Retrieves one settlement batch by its id, without needing to know which window it belongs to. Use it when a transaction gave you a settlementBatchId on its own.
      security:
        - secretKey: []
      parameters:
        - $ref: "#/components/parameters/SettlementBatchId"
      responses:
        "200":
          description: The settlement batch.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    $ref: "#/components/schemas/SettlementBatch"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/settlement/windows/batches/export:
    get:
      operationId: exportSettlementBatches
      tags:
        - Settlement reporting
      summary: Export settlement batch transactions
      description: Exports the transactions inside settlement batches as a spreadsheet, one row per transaction with its selling fees, VAT, settlement amount, ready-for-settlement date, method, and channel. This is the file to reconcile a settlement against line by line.
      security:
        - secretKey: []
      parameters:
        - name: status
          in: query
          description: Filter by window status.
          schema:
            type: string
        - name: dateFrom
          in: query
          description: Only include settlements on or after this date.
          schema:
            type: string
      responses:
        "200":
          description: The exported settlement batch transactions file.
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/batch:
    get:
      operationId: listBatches
      tags:
        - Bulk batches
      summary: List batches
      description: Retrieves the merchant's batches, paginated. currency is required, so a batch list is always scoped to one currency; every other filter is optional.
      security:
        - secretKey: []
      parameters:
        - name: currency
          in: query
          required: true
          description: "Currency the batches were created in. Example: `EGP`"
          schema:
            type: string
            enum:
              - EGP
              - USD
              - EUR
              - GBP
        - name: q
          in: query
          description: Free-text search across batch names.
          schema:
            type: string
        - name: page
          in: query
          description: Current page number. Defaults to 1.
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of records per page. Defaults to 20.
          schema:
            type: integer
        - name: sortBy
          in: query
          description: Field to sort by.
          schema:
            type: string
            enum:
              - name
              - batchId
              - createdAt
              - totalAmount
              - status
        - name: sortType
          in: query
          description: "Sorting direction: 1 = ascending, -1 = descending."
          schema:
            type: integer
            enum:
              - 1
              - -1
        - name: branchIds
          in: query
          description: Comma-separated branch ids — only return batches created by these branches.
          schema:
            type: string
      responses:
        "200":
          description: The batches matching the filters.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Batch"
                  total:
                    type: integer
                  page:
                    type: integer
                  limit:
                    type: integer
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
    post:
      operationId: createBatch
      tags:
        - Bulk batches
      summary: Create a batch
      description: Creates an empty batch. batchType decides which import sheet the batch expects — withCustomer when each row carries the customer's details so Kashier can create or match a customer record, withoutCustomer when the rows are amounts only. Fill the batch afterwards with importBatchItems.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BatchCreateRequest"
            examples:
              create:
                summary: A batch of customer invoices in EGP
                value:
                  batchName: June invoices
                  currency: EGP
                  batchType: withCustomer
      responses:
        "201":
          description: The created batch, still empty.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Batch"
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/batch/{batchId}:
    get:
      operationId: getBatch
      tags:
        - Bulk batches
      summary: Get a batch
      description: Retrieves a single batch together with the items it contains, so you can review what was imported before sharing it.
      security:
        - secretKey: []
      parameters:
        - name: batchId
          in: path
          required: true
          description: The batch's record id.
          schema:
            type: string
      responses:
        "200":
          description: The batch and its items.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/BatchWithItems"
                  message:
                    type: string
        "404":
          description: No batch with that id belongs to this merchant.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BatchError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
    put:
      operationId: updateBatch
      tags:
        - Bulk batches
      summary: Update a batch
      description: Renames an existing batch. The items inside it are left untouched — to change those use updateBatchItem.
      security:
        - secretKey: []
      parameters:
        - name: batchId
          in: path
          required: true
          description: The batch's record id.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BatchUpdateRequest"
            examples:
              rename:
                summary: Rename a batch
                value:
                  batchName: June invoices — revised
      responses:
        "200":
          description: The updated batch.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Batch"
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    delete:
      operationId: deleteBatch
      tags:
        - Bulk batches
      summary: Delete a batch or empty it
      description: Deletes a batch, or just its contents. Pass operation=batch to remove the batch itself, or operation=batch_items to empty it and keep the batch so you can re-import a corrected sheet into it.
      security:
        - secretKey: []
      parameters:
        - name: batchId
          in: path
          required: true
          description: The batch's record id.
          schema:
            type: string
        - name: operation
          in: query
          required: true
          description: What to delete — the batch itself, or only the items inside it.
          schema:
            type: string
            enum:
              - batch
              - batch_items
      responses:
        "200":
          description: The batch was deleted, or emptied.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      _id:
                        type: string
                      isDeleted:
                        type: boolean
                      deletedAt:
                        type: string
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/batch/import:
    post:
      operationId: importBatchItems
      tags:
        - Bulk batches
      summary: Import batch items from a sheet
      description: Fills a batch by uploading an Excel sheet of invoices. sheetType must match how the batch was created — withCustomer when each row carries the customer's details, withoutCustomer when the rows are amounts only. The response reports how many rows were imported and returns a per-row errors list for the ones that failed, so a partly wrong sheet still imports everything that was valid.
      security:
        - secretKey: []
      parameters:
        - name: currency
          in: query
          required: true
          description: "Currency of the amounts in the sheet. Example: `EGP`"
          schema:
            type: string
            enum:
              - EGP
              - USD
              - EUR
              - GBP
        - name: batchId
          in: query
          required: true
          description: "The batch to import into, in `B-` form. Example: `B-123`"
          schema:
            type: string
        - name: sheetType
          in: query
          description: Which sheet layout is being uploaded.
          schema:
            type: string
            enum:
              - withCustomer
              - withoutCustomer
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - sheet
              properties:
                sheet:
                  type: string
                  format: binary
                  description: The Excel sheet (.xlsx) of invoices to import.
      responses:
        "200":
          description: How many rows imported, and what went wrong with the ones that did not.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BatchImportResult"
              examples:
                partial:
                  summary: Two rows rejected out of a hundred
                  value:
                    data:
                      imported: 98
                      failed: 2
                      skipped: 0
                      batchId: B-123
                      errors:
                        - row: 5
                          error: Invalid amount format
                        - row: 12
                          error: Email already used
                    message: Batch items imported
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/batch/{batchId}/create-share:
    post:
      operationId: createBatchShare
      tags:
        - Bulk batches
      summary: Share a batch
      description: Turns the batch into live invoices and sends each customer their own payment link, on the channel their row carries. Call this once the imported items look right; the response carries the share record for the batch.
      security:
        - secretKey: []
      parameters:
        - name: batchId
          in: path
          required: true
          description: The batch's record id.
          schema:
            type: string
      responses:
        "201":
          description: The batch was shared.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/BatchShare"
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/batch/{batchId}/re-share:
    post:
      operationId: reshareBatch
      tags:
        - Bulk batches
      summary: Re-share a batch
      description: Re-sends an already-shared batch to the same customers, on the channel used the first time. Useful for chasing a batch of unpaid invoices without rebuilding it.
      security:
        - secretKey: []
      parameters:
        - name: batchId
          in: path
          required: true
          description: The batch's record id.
          schema:
            type: string
      responses:
        "200":
          description: The batch was re-sent.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/BatchShare"
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/batch-item/{batchItemId}:
    get:
      operationId: getBatchItem
      tags:
        - Bulk batches
      summary: Get a batch item
      description: Retrieves a single item from a batch — one invoice-to-be, with its amount, due date, and status.
      security:
        - secretKey: []
      parameters:
        - name: batchItemId
          in: path
          required: true
          description: The batch item's record id.
          schema:
            type: string
      responses:
        "200":
          description: The batch item.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BatchItem"
        "404":
          description: No batch item with that id belongs to this merchant.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BatchError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
    put:
      operationId: updateBatchItem
      tags:
        - Bulk batches
      summary: Update a batch item
      description: Corrects a single row inside a batch before it is shared — most often to fix an amount or a due date that came in wrong from the imported sheet. The fields live under a batchItem wrapper and mirror the ones on an invoice.
      security:
        - secretKey: []
      parameters:
        - name: batchItemId
          in: path
          required: true
          description: The batch item's record id.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BatchItemUpdateRequest"
            examples:
              fixAmount:
                summary: Correct the amount and due date on one row
                value:
                  batchItem:
                    description: Product purchase
                    totalAmount: 100
                    paymentType: simple
                    referenceId: REF-001
                    isSuspendedPayment: false
                    dueDate: 2026-12-31 23:59:59+00:00
                    extraFees: []
                    items: []
      responses:
        "200":
          description: The updated batch item.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BatchItem"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    delete:
      operationId: deleteBatchItem
      tags:
        - Bulk batches
      summary: Delete a batch item
      description: Removes a single row from a batch. Use it to drop a customer from a bulk billing run without re-importing the whole sheet.
      security:
        - secretKey: []
      parameters:
        - name: batchItemId
          in: path
          required: true
          description: The batch item's record id.
          schema:
            type: string
      responses:
        "200":
          description: The batch item was deleted.
          content:
            application/json:
              schema:
                type: object
                properties:
                  _id:
                    type: string
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/merchants/{merchantId}/paymentMethods:
    get:
      operationId: getMerchantPaymentMethods
      tags:
        - Checkout reference data
      summary: Get a merchant's allowed payment methods
      description: Retrieves the payment methods your merchant account is entitled to. A custom checkout calls this first and renders only the methods it gets back — the hosted checkout and iframe apply the same entitlement, intersecting whatever allowedMethods you request with this list.
      security: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Merchant account number or merchant ID, in the `MID-XXX-XXX` format, e.g. `YOUR_MID`.
          schema:
            type: string
          example: YOUR_MID
      responses:
        "200":
          description: The methods enabled on the merchant account, as a map of method name to whether it is available.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CheckoutMerchantPaymentMethods"
              examples:
                methods:
                  summary: Shape of the response — the key set reflects the methods configured on your own account
                  value:
                    card: true
                    wallet: true
                    bank_installments: false
        "400":
          description: The `merchantId` is malformed, or no merchant matches it.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CheckoutReferenceError"
              examples:
                badFormat:
                  summary: Malformed merchant ID
                  value:
                    error: Invalid merchantId format. It should be in the format MID-XXX-XXX
                notFound:
                  summary: No such merchant
                  value:
                    message: Merchant not found
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/merchants/{merchantId}/installments/banks:
    get:
      operationId: getMerchantInstallmentBanks
      tags:
        - Checkout reference data
      summary: Get a merchant's installment banks
      description: Retrieves the banks that offer card installments on the merchant account, with their names in English and Arabic, their abbreviation, and a logo you can render in the checkout. Use the returned bankId to fetch that bank's plans.
      security: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Merchant account number or merchant ID, in the `MID-XXX-XXX` format, e.g. `YOUR_MID`.
          schema:
            type: string
          example: YOUR_MID
      responses:
        "200":
          description: The installment-enabled banks.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/CheckoutInstallmentBank"
              examples:
                banks:
                  summary: Two banks shown (the live response lists every enabled bank)
                  value:
                    - logoUrl: https://static.kashier.io/financial-institution/logo30.388156112719432
                      bankNameEn: Attijariwafa bank
                      bankNameAr: التجاري وفا بنك
                      bankAbbreviation: BBE
                      bankId: 603d0bccd1efbd0011ed5364
                    - logoUrl: https://static.kashier.io/financial-institution/logo56.26990974318187
                      bankNameEn: Banque Misr
                      bankNameAr: بنك مصر
                      bankAbbreviation: BM
                      bankId: 62fb84f3f16be70011f066e2
        "400":
          $ref: "#/components/responses/BadRequest"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/merchants/{merchantId}/installments/banks/{bankId}:
    get:
      operationId: getMerchantInstallmentBankPlans
      tags:
        - Checkout reference data
      summary: Get one bank's installment plans
      description: Retrieves the installment plans a single bank offers on the merchant account — the durations the customer can pick from and the minimum amount each plan requires. Returns an empty array when the bank has no plans enabled on the account. To price a plan against a specific basket amount, including the monthly instalment and the bank interest rate, use the Installments endpoints instead.
      security: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Merchant account number or merchant ID, in the `MID-XXX-XXX` format, e.g. `YOUR_MID`.
          schema:
            type: string
          example: YOUR_MID
        - name: bankId
          in: path
          required: true
          description: The bank's `bankId`, taken from the installment banks lookup.
          schema:
            type: string
      responses:
        "200":
          description: The bank's installment plans, or an empty array when none are enabled.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/CheckoutInstallmentPlan"
              examples:
                none:
                  summary: Bank has no plans enabled on this account
                  value: []
        "400":
          $ref: "#/components/responses/BadRequest"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/merchants/{merchantId}/installments/banks/{bankAbbreviation}/fees:
    get:
      operationId: getMerchantInstallmentBankFees
      tags:
        - Checkout reference data
        - Fees and discounts
      summary: Get one bank's installment fees
      description: Retrieves the fee charged per plan duration for a single bank on the merchant account, so a checkout can show the customer what each instalment length costs. The bank is addressed by its abbreviation rather than its ID. Returns an empty array when the bank has no fees configured on the account.
      security: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Merchant account number or merchant ID, in the `MID-XXX-XXX` format, e.g. `YOUR_MID`.
          schema:
            type: string
          example: YOUR_MID
        - name: bankAbbreviation
          in: path
          required: true
          description: The bank's `bankAbbreviation`, taken from the installment banks lookup, e.g. `NBE`.
          schema:
            type: string
      responses:
        "200":
          description: The bank's fee per plan duration, or an empty array when none are configured.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/CheckoutInstallmentFee"
              examples:
                none:
                  summary: Bank has no fees configured on this account
                  value: []
        "400":
          $ref: "#/components/responses/BadRequest"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/constants/banks:
    get:
      operationId: listBankConstants
      tags:
        - Constants
      summary: List banks
      description: Retrieves the Egyptian banks Kashier publishes, with each name in English and Arabic and its abbreviation. Use it to populate a bank picker or to address a bank in the installment fee lookup. For payout transfers, use the bank abbreviations sheet linked from the [Payouts guide](/docs/payouts#bank-codes) instead — payouts validate against their own list.
      security: []
      responses:
        "200":
          description: >-
            The bank list, returned under two different keys. `bankNames` is the
            bank-level list — one entry per bank, carrying the `Abbreviation` you
            send as `recipientBank` on a payout. `banks` is the branch-level list:
            one entry per bank *branch*, repeating the bank fields alongside a
            branch name and `Branch Code`. It is much longer than `bankNames`.
            Read `bankNames` unless you specifically need branches.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BankConstants"
              examples:
                banks:
                  summary: Trimmed — the live response lists every Egyptian bank, and every branch
                  value:
                    bankNames:
                      - ar: البنك العربى الافريقى الدولى
                        en: Arab African International Bank
                        Abbreviation: AAIB
                      - ar: بنك الأسكندرية
                        en: Bank of Alexandria
                        Abbreviation: BOA
                    banks:
                      - Bank Name: Bank of Alexandria
                        Arabic Bank Name: بنك الأسكندرية
                        Abbreviation: BOA
                        Arabic Branch Name: العمليات المصرفية
                        English Branch Name: Banking Operations
                        Branch Code: 100
                      - Bank Name: Bank of Alexandria
                        Arabic Bank Name: بنك الأسكندرية
                        Abbreviation: BOA
                        Arabic Branch Name: فرع القاهرة
                        English Branch Name: Cairo Branch
                        Branch Code: 101
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/constants/cities:
    get:
      operationId: listCityConstants
      tags:
        - Constants
      summary: List cities
      description: Retrieves the Egyptian governorates Kashier recognises, in English and Arabic, each with the ISO 3166-2 subdivision code to store against an address.
      security: []
      responses:
        "200":
          description: The city list.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/CityConstant"
              examples:
                cities:
                  summary: Two cities shown (the live response lists every governorate)
                  value:
                    - id: "1"
                      governorate_id: "1"
                      city_name_ar: الاسكندرية
                      city_name_en: Alexandria
                      value: EG-ALX
                    - id: "6"
                      governorate_id: "6"
                      city_name_ar: القاهرة
                      city_name_en: Cairo
                      value: EG-C
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/constants/countries:
    get:
      operationId: listCountryConstants
      tags:
        - Constants
      summary: List countries
      description: Retrieves every country Kashier recognises, with its two- and three-letter codes, its international dialling prefix, and its flag as an embedded image. Useful for country and phone-prefix pickers. The response is large because each entry embeds its flag, so cache it rather than fetching it per page load.
      security: []
      responses:
        "200":
          description: The country list.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/CountryConstant"
              examples:
                countries:
                  summary: One country shown, flag truncated (the live response lists every country)
                  value:
                    - abbreviation2: eg
                      abbreviation3: egy
                      name: مصر
                      phone: "+20"
                      flag: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA…
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/constants/industries:
    get:
      operationId: listIndustryConstants
      tags:
        - Constants
      summary: List industries
      description: Retrieves the industries and their sectors that a merchant business profile can be classified under, in English and Arabic.
      security: []
      responses:
        "200":
          description: The industry list, each industry carrying its sectors.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/IndustryConstant"
              examples:
                industries:
                  summary: One industry shown (the live response lists every industry)
                  value:
                    - id: 1
                      en: Government
                      ar: الحكومة
                      sectors:
                        - en: Government Service
                          ar: خدمات حكومية
                          value: Government Service
                        - en: Ministry
                          ar: وزارة
                          value: Ministry
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/constants/payment-method-definition:
    get:
      operationId: getPaymentMethodDefinitions
      tags:
        - Constants
      summary: Get payment method definitions
      description: Retrieves every payment method Kashier supports, mapped to the provider integrations that can process it. It is the canonical list of method names — card, wallet, bank_installments, and the rest — used across payment sessions, payment links, and the checkout entitlement lookup.
      security: []
      responses:
        "200":
          description: Each payment method mapped to the provider integrations behind it.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentMethodDefinitions"
              examples:
                definitions:
                  value:
                    card:
                      - mpgs_v68
                      - host2host
                      - upg_card
                    wallet:
                      - upg_wallet
                    valu:
                      - valu_v1
                      - valu_v2
                    octo:
                      - octo_v1
                    souhoola:
                      - souhoola_v1
                    aman:
                      - aman_v1
                    bank_installments:
                      - mpgs_v68_installment_acquirer
                      - mpgs_v68_installment_issuer
                      - host2host_installment_acquirer
                      - host2host_installment_issuer
                    transfer:
                      - ebc_v1
                    contact:
                      - contact_v1
        "404":
          description: The payment method definition schema is unavailable.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CheckoutReferenceError"
              examples:
                missing:
                  value:
                    message: Schema not found
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/payment-fees/calculate:
    get:
      operationId: calculatePaymentFees
      tags:
        - Fees and discounts
      summary: Calculate the fee on an amount
      description: Works out the processing fee for an amount under the merchant's pricing model and returns the total the customer would be charged. Use it when fees are passed on to the customer, so your checkout can show the fee as its own line and the grand total before the payment is created.
      security:
        - secretKey: []
      parameters:
        - name: amount
          in: query
          required: true
          description: "The transaction amount to calculate the fee on. Example: `100.00`"
          schema:
            type: string
        - name: interactionSource
          in: query
          required: true
          description: Where the payment is being taken, since fees differ by channel.
          schema:
            type: string
            enum:
              - POS
              - ECOMMERCE
        - name: apiVersion
          in: query
          description: API version to calculate against.
          schema:
            type: string
      responses:
        "200":
          description: The amount, the fee on it, and the total to charge.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentFeeCalculation"
              examples:
                withFee:
                  summary: A 100.00 EGP e-commerce payment
                  value:
                    amount: 100
                    fees: 5
                    totalAmount: 105
                    currency: EGP
                    interactionSource: ECOMMERCE
        "403":
          description: No secret key was sent.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DiscountError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/discounts/calculate:
    post:
      operationId: calculateDiscount
      tags:
        - Fees and discounts
      summary: Calculate a discount and the fee together
      description: "Given an amount and a discount, returns the fee, the discount taken off, and the final amount the customer pays. Unauthenticated so a checkout page can call it while the customer is still choosing how to pay — it identifies the merchant by merchantId rather than by a key, and reads nothing back that the page did not already send. Send all four fields: a partial body is rejected at the edge before it reaches the calculator. When no discount applies, the response carries the fee alone."
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DiscountCalculationRequest"
            examples:
              online:
                summary: An online payment with a discount applied
                value:
                  merchantId: YOUR_MID
                  amount: 100
                  interactionSource: online
                  discount: {}
      responses:
        "200":
          description: The fee, the discount, and the resulting amounts. Fields that do not apply are left out — with no discount in play you get `paymentFees` on its own.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DiscountCalculation"
              examples:
                withDiscount:
                  summary: A discount applies
                  value:
                    paymentFees: 15
                    discountAmount: 10
                    originalAmount: 100
                    finalAmount: 90
                feeOnly:
                  summary: No discount applies
                  value:
                    paymentFees: 0
        "400":
          description: The calculation parameters were rejected.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DiscountError"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/discounts:
    get:
      operationId: listDiscountNames
      tags:
        - Fees and discounts
      summary: List your discount campaigns
      description: Returns the names of the discount campaigns configured on the merchant account and whether each one is currently active. Campaigns are set up by Kashier rather than through the API, so this is a read-only view — use it to label a discount in your own UI once calculateDiscount or checkCardDiscount tells you one applies.
      security:
        - secretKey: []
      responses:
        "200":
          description: The merchant's discount campaigns.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/DiscountName"
        "403":
          description: No secret key was sent.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DiscountError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/discounts/{merchantId}/active:
    get:
      operationId: listActiveDiscounts
      tags:
        - Fees and discounts
      summary: List a merchant's active discounts (public)
      description: Returns the discount campaigns that are live right now for a merchant, optionally narrowed to the card BIN the customer is paying with and the channel they are paying on. Unauthenticated, because a checkout page calls it directly to decide what discount banner to show.
      security: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: "The merchant id the discounts belong to. Example: `YOUR_MID`"
          schema:
            type: string
        - name: binRanges
          in: query
          description: Comma-separated card BINs — only return discounts that apply to these.
          schema:
            type: string
        - name: channel
          in: query
          description: Only return discounts that apply on this channel.
          schema:
            type: string
            enum:
              - pos
              - online
      responses:
        "200":
          description: The discounts that are currently live.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Discount"
                  total:
                    type: integer
        "404":
          description: No merchant with that id exists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DiscountError"
              examples:
                notFound:
                  value:
                    message: Merchant Not Found
                    error: NotFound
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/discounts/card:
    servers:
      - url: https://test-fep.kashier.io
        description: Test — no real money moves
    post:
      operationId: checkCardDiscount
      tags:
        - Fees and discounts
      summary: Check whether a card qualifies for a discount
      description: Checks the card the customer has just entered against the merchant's live bank discount campaigns and, when one applies, returns how much comes off and what the fee would be. This is the call a checkout makes the moment the card number is complete, so the customer sees the bank discount before pressing pay. Served from the fep.kashier.io hosts. A card with no discount still returns 200 — the absence of a response object is the signal, not an error.
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CardDiscountRequest"
            examples:
              check:
                summary: Check a card on an e-commerce checkout
                value:
                  merchantId: YOUR_MID
                  card: "4111111111111111"
                  type: card
                  channel: ecommerce
                  amount: 100
      responses:
        "200":
          description: Whether the card qualifies, and the discount if it does.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CardDiscountResponse"
              examples:
                hasDiscount:
                  summary: The card qualifies
                  value:
                    status: SUCCESS
                    messages:
                      en: Card has discount
                    response:
                      discountId: 507f1f77bcf86cd799439020
                      cardBin: "518888"
                      discountAmount: "10.50"
                      discountPercentage: 5
                      maxDiscountAmount: 50
                      paymentFees: "2.50"
                      minAmount: 100
                      maxAmount: 5000
                      validFrom: 2026-06-01 00:00:00+00:00
                      validTo: 2026-12-31 23:59:59+00:00
                noDiscount:
                  summary: The card does not qualify
                  value:
                    status: SUCCESS
                    messages:
                      en: Card does not have discount
        "400":
          description: The card could not be read — for example no card number was sent.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CardDiscountError"
              examples:
                missingCard:
                  value:
                    error:
                      cause: Card Number not found
                    messages:
                      en: Something went wrong.
                    status: FAILURE
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/instant-settlements/instant/eligible-transactions:
    get:
      operationId: listEligibleInstantSettlementTransactions
      tags:
        - Instant settlement
      summary: List eligible transactions
      description: |
        Returns a paginated list of your not-yet-settled transactions that are eligible for instant
        settlement, together with summary totals across the whole eligible set and the caps that
        apply to your account.

        A transaction qualifies when it is a captured payment that has not been voided or refunded,
        was taken on a card or wallet, has not passed its normal settlement date, and is not already
        part of another instant settlement request.

        Requires the `instant_settlement_request` feature flag and the
        `instant_settlements.all.view_instant_settlement` permission.
      security:
        - secretKey: []
      parameters:
        - name: page
          in: query
          required: false
          description: 1-based page number. Clamped to at least `1`.
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          required: false
          description: Records per page. Clamped to the range 1–100.
          schema:
            type: integer
            default: 20
        - name: channel
          in: query
          required: false
          description: Optional channel filter.
          schema:
            type: string
            enum:
              - online
              - pos
        - name: method
          in: query
          required: false
          description: Optional payment-method filter, intersected with the eligible methods.
          schema:
            type: string
            enum:
              - card
              - wallet
        - name: dateFrom
          in: query
          required: false
          description: Inclusive lower bound on the transaction date (ISO).
          schema:
            type: string
            example: 2026-06-01
        - name: dateTo
          in: query
          required: false
          description: Inclusive upper bound on the transaction date (ISO). Extended to the end of that day.
          schema:
            type: string
            example: 2026-06-30
      responses:
        "200":
          description: The eligible transactions for this page, plus totals for the whole eligible set and your current caps.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementEligibleTransactionsResponse"
              examples:
                eligible:
                  value:
                    message: success
                    data:
                      - transactionId: TX-1001
                        amount: 10000
                        settlementAmount: 10000
                        accountId: ACC-39550-436-01
                        method: card
                        channel: online
                        transactionDate: 2026-06-10T11:20:00.000Z
                        rfsDate: 2026-06-15T00:00:00.000Z
                      - transactionId: TX-1002
                        amount: 5000
                        settlementAmount: 5000
                        accountId: ACC-39550-436-02
                        method: wallet
                        channel: online
                        transactionDate: 2026-06-11T09:05:00.000Z
                        rfsDate: 2026-06-16T00:00:00.000Z
                    pagination:
                      total: 2
                      limit: 20
                      page: 1
                      pages: 1
                    summary:
                      count: 2
                      totalAmount: 15000
                      totalSettlementAmount: 15000
                    limits:
                      perRequestCap: 100000
                      dailyCap: 250000
                      usedToday: 0
                      remainingToday: 250000
        "401":
          description: |
            The `instant_settlement_request` feature flag is off for your account, or your user's role
            does not carry `instant_settlements.all.view_instant_settlement`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
              examples:
                featureDisabled:
                  summary: Feature flag off
                  value:
                    message: Unauthorized
        "403":
          description: No `Authorization` header was sent, or the calling session has no merchant selected.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
              examples:
                noSelectedMerchant:
                  value:
                    status: FAILURE
                    error:
                      cause: A selected merchant is required for this operation
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/instant-settlements/instant/suggestions:
    post:
      operationId: getInstantSettlementSuggestions
      tags:
        - Instant settlement
      summary: Get amount suggestions
      description: |
        Given a target amount, returns the combination of your eligible transactions whose combined
        `settlementAmount` comes closest to it — one combination at or below the target (`below`) and
        one at or above it (`above`) — so you do not have to hand-pick transactions to hit a number.

        Both sides are clamped to your effective cap (the lower of `perRequestCap` and your remaining
        daily cap), and a side is `null` when no combination fits. Ties are broken in favour of the
        combination with fewer transactions. Each side carries the `transactionIds` you can pass
        straight to the fee inquiry or to create a request.

        Requires the `instant_settlement_request` feature flag and the
        `instant_settlements.all.view_instant_settlement` permission.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InstantSettlementSuggestionsInput"
            examples:
              target:
                summary: Get the combinations nearest to 50,000
                value:
                  targetAmount: 50000
      responses:
        "200":
          description: The nearest combination below and above the target.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementSuggestions"
              examples:
                bothSides:
                  summary: A combination fits on both sides
                  value:
                    targetAmount: 50000
                    below:
                      totalAmount: 38500
                      transactionsCount: 4
                      transactionIds:
                        - TX-A30000
                        - TX-B7000
                        - TX-C1000
                        - TX-D500
                    above:
                      totalAmount: 55000
                      transactionsCount: 2
                      transactionIds:
                        - TX-A30000
                        - TX-E25000
                    candidatesConsidered: 5
                    truncated: false
                    approximate: false
                    limits:
                      perRequestCap: 100000
                      dailyCap: 250000
                      remainingToday: 250000
                capped:
                  summary: The cap rules out anything at or above the target
                  value:
                    targetAmount: 50000
                    below:
                      totalAmount: 30000
                      transactionsCount: 1
                      transactionIds:
                        - TX-A30000
                    above: null
                    candidatesConsidered: 2
                    truncated: false
                    approximate: false
                    limits:
                      perRequestCap: 40000
                      dailyCap: 0
                      remainingToday: null
        "400":
          description: The request body failed validation.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
              examples:
                invalidTarget:
                  value:
                    message: targetAmount must be a positive number
        "401":
          description: |
            The `instant_settlement_request` feature flag is off for your account, or your user's role
            does not carry `instant_settlements.all.view_instant_settlement`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
              examples:
                featureDisabled:
                  value:
                    message: Unauthorized
        "403":
          description: No `Authorization` header was sent, or the calling session has no merchant selected.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/instant-settlements/instant/inquiry:
    post:
      operationId: inquireInstantSettlement
      tags:
        - Instant settlement
      summary: Inquire about an instant settlement
      description: |
        Works out what you would receive for a set of transactions **without committing to it**. It
        runs the same calculation the create-request endpoint runs and returns the same breakdown,
        but it changes nothing: no transactions are flagged and no payout is started. Call this first
        to show the merchant what they are agreeing to.

        The fee is a percentage of the settled amount, plus VAT on that percentage, plus a flat
        transfer fee charged once per request. Your rate and flat fee are configured on your account.

        Your per-request and daily caps are enforced here too, so a selection that would breach them
        is rejected before a request is ever created.

        Requires the `instant_settlement_request` feature flag and the
        `instant_settlements.all.create_instant_settlement` permission.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InstantSettlementTransactionIds"
            examples:
              inquiry:
                summary: Quote a fee for two transactions
                value:
                  transactionIds:
                    - TX-1001
                    - TX-1002
      responses:
        "200":
          description: The amount you would receive and the fees that would be deducted. Nothing has been committed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementQuote"
              examples:
                quote:
                  value:
                    totalAmount: 15000
                    totalSettlementAmount: 15000
                    totalRateFees: 225
                    vat: 31.5
                    flatFees: 0
                    totalFees: 256.5
                    netTransferAmount: 14743.5
                    transactionsCount: 2
        "400":
          description: The request body failed validation, or one of the transactions is not eligible.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
        "401":
          description: |
            The `instant_settlement_request` feature flag is off for your account, or your user's role
            does not carry `instant_settlements.all.create_instant_settlement`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
              examples:
                featureDisabled:
                  value:
                    message: Unauthorized
        "403":
          description: No `Authorization` header was sent, or the calling session has no merchant selected.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
        "422":
          description: The selection would breach your per-request cap or your daily cap.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
              examples:
                dailyCap:
                  summary: Daily cap exceeded
                  value:
                    status: FAILURE
                    error:
                      code: INSTANT_SETTLEMENT_DAILY_LIMIT_EXCEEDED
                      message: Instant settlement daily limit exceeded
                      limit: 250000
                      usedToday: 240000
                      remaining: 10000
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/instant-settlements/instant-requests:
    post:
      operationId: requestInstantSettlement
      tags:
        - Instant settlement
      summary: Create an instant settlement request
      description: |
        Creates an instant settlement request over the selected transactions. The request is created
        in `PENDING` status and is then reviewed by Kashier: approval moves it to `PROCESSING` and
        deducts the early-payout amount from your balance, and the payout itself moves it to
        `TRANSFERRED`. A request that will not be processed becomes `DECLINED` with a
        `declineReason`.

        Every transaction is re-validated against the eligibility rules at creation time, and the
        request is rejected whole if any of them is no longer eligible — no partial request is
        created. Your per-request and daily caps are enforced here as well.

        Requires the `instant_settlement_request` feature flag and the
        `instant_settlements.all.create_instant_settlement` permission.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InstantSettlementTransactionIds"
            examples:
              create:
                summary: Request early payout of two transactions
                value:
                  transactionIds:
                    - TX-1001
                    - TX-1002
      responses:
        "200":
          description: The request was created and is `PENDING`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementRequestEnvelope"
              examples:
                created:
                  value:
                    message: success
                    data:
                      id: d2719f9a-3a36-4f10-9c7b-1f2e3d4c5b6a
                      requestId: ISR-1042
                      merchantId: MID-957-917
                      merchantName: Acme Stores LLC
                      storeName: Acme Downtown
                      status: PENDING
                      declineReason: null
                      totalAmount: 15000
                      totalSettlementAmount: 15000
                      totalRateFees: 225
                      flatFees: 0
                      vat: 31.5
                      totalFees: 256.5
                      netTransferAmount: 14743.5
                      transactionsCount: 2
                      requestedBy: merchant@kashier.io
                      statusHistory:
                        - status: PENDING
                          at: 2026-06-13T08:00:00.000Z
                          by: merchant@kashier.io
                      createdAt: 2026-06-13T08:00:00.000Z
                      updatedAt: 2026-06-13T08:00:00.000Z
        "400":
          description: The request body failed validation, or one of the transactions is no longer eligible. Nothing is created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
              examples:
                ineligible:
                  value:
                    status: FAILURE
                    error:
                      cause: "Transactions not eligible for instant settlement: TX-1002"
        "401":
          description: |
            The `instant_settlement_request` feature flag is off for your account, or your user's role
            does not carry `instant_settlements.all.create_instant_settlement`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
              examples:
                featureDisabled:
                  value:
                    message: Unauthorized
        "403":
          description: No `Authorization` header was sent, or the calling session has no merchant selected.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
        "422":
          description: The selection would breach your per-request cap or your daily cap.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
              examples:
                perRequestCap:
                  value:
                    status: FAILURE
                    error:
                      code: INSTANT_SETTLEMENT_PER_REQUEST_LIMIT_EXCEEDED
                      message: Instant settlement per-request limit exceeded
                      limit: 100000
                      requested: 120000
        "500":
          $ref: "#/components/responses/ServerError"
    get:
      operationId: listInstantSettlementRequests
      tags:
        - Instant settlement
      summary: List your instant settlement requests
      description: |
        Returns a paginated list of your own instant settlement requests, newest first, with the
        totals and status of each. Use **Get request details** for the full breakdown of a single
        request.

        Requires the `instant_settlement_request` feature flag and the
        `instant_settlements.all.view_instant_settlement` permission.
      security:
        - secretKey: []
      parameters:
        - name: page
          in: query
          required: false
          description: 1-based page number.
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          required: false
          description: Records per page.
          schema:
            type: integer
            default: 20
        - name: status
          in: query
          required: false
          description: Filter by request status.
          schema:
            type: string
            enum:
              - PENDING
              - PROCESSING
              - TRANSFERRED
              - DECLINED
        - name: requestId
          in: query
          required: false
          description: Filter or search by the human-readable `requestId` (prefix-safe).
          schema:
            type: string
            example: ISR-1042
        - name: dateFrom
          in: query
          required: false
          description: Inclusive lower bound on the date range (ISO).
          schema:
            type: string
            example: 2026-06-01
        - name: dateTo
          in: query
          required: false
          description: Inclusive upper bound on the date range (ISO). Extended to the end of that day.
          schema:
            type: string
            example: 2026-06-30
      responses:
        "200":
          description: Your instant settlement requests for this page.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementRequestListResponse"
              examples:
                list:
                  value:
                    message: success
                    data:
                      - id: d2719f9a-3a36-4f10-9c7b-1f2e3d4c5b6a
                        requestId: ISR-1042
                        merchantId: MID-957-917
                        status: PENDING
                        totalSettlementAmount: 15000
                        netTransferAmount: 14743.5
                        transactionsCount: 2
                        createdAt: 2026-06-13T08:00:00.000Z
                    pagination:
                      total: 1
                      limit: 20
                      page: 1
                      pages: 1
        "401":
          description: |
            The `instant_settlement_request` feature flag is off for your account, or your user's role
            does not carry `instant_settlements.all.view_instant_settlement`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
              examples:
                featureDisabled:
                  value:
                    message: Unauthorized
        "403":
          description: No `Authorization` header was sent, or the calling session has no merchant selected.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/instant-settlements/instant-requests/{id}:
    get:
      operationId: getInstantSettlementRequest
      tags:
        - Instant settlement
      summary: Get request details
      description: |
        Returns the full detail of a single instant settlement request: its totals and fee breakdown,
        its status history, the transactions an agent excluded from it, and the balance-ledger records
        created for its early-payout deduction.

        `linkedBalanceRecords` is empty while the request is still `PENDING`, because no deduction has
        posted yet. If the balance ledger is temporarily unavailable the details still return, but
        with `linkedBalanceRecords: null` and `linkedBalanceRecordsUnavailable: true` — retry later to
        get the records.

        Requires the `instant_settlement_request` feature flag and the
        `instant_settlements.all.view_instant_settlement` permission.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The request's UUID `id` or its human-readable `requestId` (for example `ISR-1042`).
          schema:
            type: string
            example: ISR-1042
      responses:
        "200":
          description: The request's full detail.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementRequestEnvelope"
              examples:
                processing:
                  summary: Approved — the deduction has posted
                  value:
                    message: success
                    data:
                      id: d2719f9a-3a36-4f10-9c7b-1f2e3d4c5b6a
                      requestId: ISR-1042
                      merchantId: MID-957-917
                      status: PROCESSING
                      totalSettlementAmount: 15000
                      netTransferAmount: 14743.5
                      transactionsCount: 2
                      statusHistory:
                        - status: PENDING
                          at: 2026-06-13T08:00:00.000Z
                          by: merchant@kashier.io
                        - status: PROCESSING
                          at: 2026-06-13T08:05:00.000Z
                          by: agent@kashier.io
                      unselectedTransactions: []
                      unselectedCount: 0
                      unselectedSettlementAmount: 0
                      linkedBalanceRecords:
                        - recordId: ISR-1042-20260615
                          accountId: ACC-39550-436-01
                          accountName: Main Account
                          amount: -10000
                          valueDate: 2026-06-15T00:00:00.000Z
                          isReflected: false
                          type: INSTANT_SETTLEMENT_DEDUCTION
                          operation: deduct
                          origin: settlements
                        - recordId: ISR-1042-20260616
                          accountId: ACC-39550-436-02
                          accountName: Secondary Account
                          amount: -5000
                          valueDate: 2026-06-16T00:00:00.000Z
                          isReflected: false
                          type: INSTANT_SETTLEMENT_DEDUCTION
                          operation: deduct
                          origin: settlements
                pending:
                  summary: Still pending — no deduction yet
                  value:
                    message: success
                    data:
                      id: d2719f9a-3a36-4f10-9c7b-1f2e3d4c5b6a
                      requestId: ISR-1042
                      merchantId: MID-957-917
                      status: PENDING
                      linkedBalanceRecords: []
                degraded:
                  summary: Balance ledger unavailable
                  value:
                    message: success
                    data:
                      requestId: ISR-1042
                      status: PROCESSING
                      linkedBalanceRecords: null
                      linkedBalanceRecordsUnavailable: true
        "401":
          description: |
            The `instant_settlement_request` feature flag is off for your account, or your user's role
            does not carry `instant_settlements.all.view_instant_settlement`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
        "403":
          description: No `Authorization` header was sent, or the calling session has no merchant selected.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
        "404":
          description: No such request, or the request belongs to another merchant.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
              examples:
                notFound:
                  value:
                    status: FAILURE
                    error:
                      cause: Instant settlement request not found
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/instant-settlements/instant-requests/{id}/transactions:
    get:
      operationId: listInstantSettlementRequestTransactions
      tags:
        - Instant settlement
      summary: Get request transactions
      description: |
        Returns the transactions that belong to a specific request, paginated. Rows an agent removed
        from the request stay on it and come back with `selected: false` and an `unselectedAt`
        timestamp; use the `selection` filter to narrow the list to one side.

        `selectionSummary` spans the whole request and ignores the `selection` filter, so a single
        call is enough to render both a "selected" and an "unselected" count. `summary` keeps its
        usual meaning: totals for the current filter across all pages.

        Requires the `instant_settlement_request` feature flag and the
        `instant_settlements.all.view_instant_settlement` permission.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The request's UUID `id` or its human-readable `requestId` (for example `ISR-1042`).
          schema:
            type: string
            example: ISR-1042
        - name: page
          in: query
          required: false
          description: 1-based page number.
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          required: false
          description: Records per page.
          schema:
            type: integer
            default: 20
        - name: selection
          in: query
          required: false
          description: |
            Which rows to return: `ALL` (default) for both, `SELECTED` for rows still in the request,
            `UNSELECTED` for rows an agent removed. Any other value is rejected with `400`.
          schema:
            type: string
            default: ALL
            enum:
              - ALL
              - SELECTED
              - UNSELECTED
      responses:
        "200":
          description: The request's transactions for this page.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementRequestTransactionsResponse"
              examples:
                transactions:
                  value:
                    message: success
                    data:
                      - transactionId: TX-1001
                        settlementAmount: 10000
                        accountId: ACC-39550-436-01
                        rfsDate: 2026-06-15T00:00:00.000Z
                        method: card
                        selected: true
                        unselectedAt: null
                      - transactionId: TX-1002
                        settlementAmount: 5000
                        accountId: ACC-39550-436-02
                        rfsDate: 2026-06-16T00:00:00.000Z
                        method: wallet
                        selected: true
                        unselectedAt: null
                    pagination:
                      total: 2
                      limit: 20
                      page: 1
                      pages: 1
                    summary:
                      count: 2
                      totalAmount: 15000
                      totalSettlementAmount: 15000
                    selectionSummary:
                      selectedCount: 2
                      unselectedCount: 0
                      selectedSettlementAmount: 15000
                      unselectedSettlementAmount: 0
        "400":
          description: The `selection` filter carried an unknown value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
              examples:
                badSelection:
                  value:
                    message: "selection must be one of: ALL, SELECTED, UNSELECTED"
        "401":
          description: |
            The `instant_settlement_request` feature flag is off for your account, or your user's role
            does not carry `instant_settlements.all.view_instant_settlement`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
        "403":
          description: No `Authorization` header was sent, or the calling session has no merchant selected.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
        "404":
          description: No such request, or the request belongs to another merchant.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InstantSettlementError"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/pos/messages/{serialNo}:
    post:
      operationId: sendPosTerminalMessage
      tags:
        - POS terminals
      summary: Send a message to a POS terminal
      description: |
        Relays a JSON message to one of your POS terminals. Kashier authenticates you as the merchant,
        confirms the terminal belongs to your account, and forwards the message to the terminal in real
        time over its websocket connection.

        Two events are used by merchant backends:

        - sale — start a card-present payment on the terminal. Kashier additionally checks that
          data.message.merchantOrderId has not already been paid.
        - details — pull the details of a transaction you already know the transactionId of.

        A 200 only means the message reached the terminal. The card-present result (approved / declined)
        arrives later on the data.message.reconciliation.webhookUrl you supplied, carrying a
        transactionResponseCode. If the terminal is powered off or otherwise not connected, the call
        fails with 404.

        Only the top-level event and data are validated by Kashier; everything inside data.message
        is relayed verbatim and is enforced by the terminal application.
      security:
        - secretKey: []
      parameters:
        - name: serialNo
          in: path
          required: true
          description: The serial number of the POS terminal, which is the address the message is delivered to. (Some older guides call this path parameter `POSSerialNumber`; the value is the terminal serial number either way.)
          schema:
            type: string
          example: YOUR_TERMINAL_SERIAL
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PosTerminalMessageRequest"
            examples:
              sale:
                summary: Start a card-present sale on the terminal
                value:
                  event: sale
                  data:
                    message:
                      amount: "100.00"
                      currency: EGP
                      merchantOrderId: ORD123456
                      transactionType: sale
                      printReceipt: true
                      metaData: {}
                      reconciliation:
                        webhookUrl: https://your-website.com/kashier-pos-webhook
              details:
                summary: Pull the details of a transaction
                value:
                  event: details
                  data:
                    message:
                      transactionType: details
                      metaData: {}
                      details:
                        paymentMethod: card
                        merchantOrderId: ORD123456
                        transactionId: TX-00000000
                        valu:
                          type: PF
      responses:
        "200":
          description: The message was accepted and emitted to the terminal. The payment result itself is delivered later to your reconciliation webhook.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosMessageAccepted"
        "400":
          description: The request is missing the top-level `event` or `data`, or — for a `sale` — the `merchantOrderId` has already been paid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
        "404":
          description: The terminal is not currently connected, so the message could not be delivered.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
              examples:
                disconnected:
                  value:
                    messages:
                      en: Client disconnected
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/pos/qr:
    post:
      operationId: createPosQrCode
      tags:
        - POS terminals
      summary: Generate a POS payment QR code
      description: Generates a QR code that a customer scans with their phone to open a Kashier hosted payment page for the order, instead of presenting a card at the terminal. The response carries the QR image as a data URI. The request must be signed with a Kashier-Hash header or it is rejected with 403. The generated payment link is created in EGP.
      security:
        - secretKey: []
      parameters:
        - name: Kashier-Hash
          in: header
          required: true
          description: Order hash generated from your backend using the HMAC SHA256 crypto mechanism, as described in the Kashier hashing documentation.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PosQrCodeRequest"
            examples:
              cardQr:
                summary: QR for a card payment on a terminal
                value:
                  paymentMethod:
                    type: card
                  order:
                    reference: ORD123456
                    amount: "100.00"
                  merchantId: YOUR_MID
                  posTerminal: YOUR_TERMINAL_ID
                  metaData: {}
                  newPaymentUI: true
      responses:
        "200":
          description: The QR code was generated. `qrUrl` is a data URI holding the QR image.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosQrCodeResponse"
              examples:
                generated:
                  value:
                    qrUrl: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA…
                    status: SUCCESS
                    message: Successfully performed
        "403":
          description: The `Kashier-Hash` header is missing.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
              examples:
                missingHash:
                  value:
                    status: FAILURE
                    message: Missing Kashier Hash Header
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/pos/{terminalId}/transactions:
    get:
      operationId: listPosTerminalTransactions
      tags:
        - POS terminals
      summary: List a terminal's transactions
      description: Retrieves the card-present transactions processed on one of your POS terminals. The gateway passes the request through to the transaction manager unchanged, so the rows carry the same fields as the POS transaction list in the dashboard.
      security:
        - secretKey: []
      parameters:
        - name: terminalId
          in: path
          required: true
          description: The terminal ID (ISO 8583 DE 41) of one of your POS terminals.
          schema:
            type: string
          example: YOUR_TERMINAL_ID
      responses:
        "200":
          description: The terminal's transactions.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosTransactionList"
        "401":
          description: The terminal does not belong to your merchant account, or the secret key is missing or invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/pos/{terminalId}/transactions/{transactionId}:
    get:
      operationId: getPosTerminalTransaction
      tags:
        - POS terminals
      summary: Get one terminal transaction
      description: Retrieves the details of a single card-present transaction processed on one of your POS terminals.
      security:
        - secretKey: []
      parameters:
        - name: terminalId
          in: path
          required: true
          description: The terminal ID (ISO 8583 DE 41) of one of your POS terminals.
          schema:
            type: string
          example: YOUR_TERMINAL_ID
        - name: transactionId
          in: path
          required: true
          description: Kashier's transaction ID, as returned in the transactions list or in the POS webhook.
          schema:
            type: string
      responses:
        "200":
          description: The transaction details.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosTransactionDetails"
        "401":
          description: The terminal does not belong to your merchant account, or the secret key is missing or invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/pos/report/{terminalId}:
    get:
      operationId: getPosTerminalReport
      tags:
        - POS terminals
      summary: Get a terminal transaction report
      description: Retrieves a transaction report for one POS terminal over a date and time window. Pass all as the terminalId to report across every terminal on your merchant account.
      security:
        - secretKey: []
      parameters:
        - name: terminalId
          in: path
          required: true
          description: The terminal ID (ISO 8583 DE 41) of one of your POS terminals, or `all` to report on every terminal.
          schema:
            type: string
          example: YOUR_TERMINAL_ID
        - name: startDate
          in: query
          description: Report start date, in `YYYY-MM-DD` format.
          schema:
            type: string
        - name: startTime
          in: query
          description: Report start time, in `HH:mm` format.
          schema:
            type: string
        - name: endDate
          in: query
          description: Report end date, in `YYYY-MM-DD` format.
          schema:
            type: string
        - name: endTime
          in: query
          description: Report end time, in `HH:mm` format.
          schema:
            type: string
      responses:
        "200":
          description: The terminal report for the requested window.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosReport"
        "401":
          description: The terminal does not belong to your merchant account, or the secret key is missing or invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/pos/ack/{terminalId}:
    post:
      operationId: acknowledgePosTerminalTransactions
      tags:
        - POS terminals
      summary: Acknowledge a terminal's transactions
      description: Acknowledges the transactions a POS terminal has reported, so they are marked as received and can move on to settlement. Used to close a terminal's batch from your own back office.
      security:
        - secretKey: []
      parameters:
        - name: terminalId
          in: path
          required: true
          description: The terminal ID (ISO 8583 DE 41) of one of your POS terminals.
          schema:
            type: string
          example: YOUR_TERMINAL_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PosAcknowledgeRequest"
            examples:
              ackAll:
                summary: Acknowledge the terminal's outstanding transactions
                value: {}
      responses:
        "200":
          description: The transactions were acknowledged.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosOperationResult"
        "401":
          description: The terminal does not belong to your merchant account, or the secret key is missing or invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/pos/reconcile:
    post:
      operationId: reconcilePosTerminal
      tags:
        - POS terminals
      summary: Reconcile a terminal's transactions
      description: Reconciles the transactions your system holds for a POS terminal against the transactions Kashier holds, so the two sides agree before settlement. Send the terminal and the totals you expect.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PosReconcileRequest"
            examples:
              reconcile:
                summary: Reconcile a terminal's batch totals
                value:
                  terminalId: YOUR_TERMINAL_ID
                  reconciliationData:
                    transactionCount: 50
                    totalAmount: "5000.00"
      responses:
        "200":
          description: The reconciliation was accepted.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosOperationResult"
        "400":
          description: The reconciliation data is invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/pos/bnpl:
    post:
      operationId: createPosBnplPayment
      tags:
        - POS terminals
      summary: Start a buy-now-pay-later payment on a terminal
      description: Starts a buy-now-pay-later (BNPL) card-present operation on one of your POS terminals, optionally against a specific BNPL plan. Availability depends on the BNPL providers enabled on your merchant account.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PosBnplRequest"
            examples:
              bnpl:
                summary: BNPL sale on a terminal
                value:
                  terminalId: YOUR_TERMINAL_ID
                  amount: "100.00"
                  planId: BNPL-PLAN-001
      responses:
        "200":
          description: The BNPL operation was accepted.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosOperationResult"
        "400":
          description: The BNPL request is invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v3/payment/pos/branches:
    get:
      operationId: listPosBranches
      tags:
        - POS terminals
      summary: List your POS branches
      description: Retrieves the branches your POS terminals are assigned to, so you can group terminals and reports by physical location.
      security:
        - secretKey: []
      responses:
        "200":
          description: Your POS branches.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosBranchList"
        "401":
          description: The secret key is missing or invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/terminals:
    get:
      operationId: listPosTerminals
      tags:
        - Terminals
      summary: List terminals
      description: Retrieves the POS terminals registered on your merchant account. The list can be filtered by terminal ID, serial number, branch, label, status, and mode, and is paginated and sortable.
      security:
        - secretKey: []
      parameters:
        - name: terminalId
          in: query
          description: Filter by terminal ID (ISO 8583 DE 41).
          schema:
            type: string
        - name: serialNo
          in: query
          description: Filter by terminal serial number.
          schema:
            type: string
        - name: branchIds
          in: query
          description: Comma-separated branch IDs to filter by.
          schema:
            type: string
        - name: label
          in: query
          description: Comma-separated label IDs to filter by.
          schema:
            type: string
        - name: status
          in: query
          description: Filter by terminal status.
          schema:
            type: string
            enum:
              - active
              - inactive
        - name: mode
          in: query
          description: Filter by terminal mode. A `test` terminal never touches the live card networks.
          schema:
            type: string
            enum:
              - test
              - live
        - name: merchantPayformanceId
          in: query
          description: Filter by merchant ID, e.g. `YOUR_MID`. Useful when your account has connected accounts.
          schema:
            type: string
        - name: q
          in: query
          description: Quick search keyword.
          schema:
            type: string
        - name: sortBy
          in: query
          description: Field name to sort by, e.g. `createdAt`.
          schema:
            type: string
        - name: sortType
          in: query
          description: "Sorting direction: 1 = ascending, -1 = descending."
          schema:
            type: integer
            enum:
              - 1
              - -1
        - name: limit
          in: query
          description: "Number of records per page. Default: 20."
          schema:
            type: integer
        - name: page
          in: query
          description: "Page number. Default: 1."
          schema:
            type: integer
      responses:
        "200":
          description: Your terminals.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TerminalList"
        "401":
          description: The secret key is missing or invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/terminals/branches:
    get:
      operationId: listTerminalBranches
      tags:
        - Terminals
      summary: List terminal branches
      description: Retrieves the branches your terminals are assigned to, with the number of terminals in each. Paginated and searchable.
      security:
        - secretKey: []
      parameters:
        - name: q
          in: query
          description: Search keyword matched against the branch name.
          schema:
            type: string
        - name: merchantPayformanceId
          in: query
          description: Filter by merchant ID, e.g. `YOUR_MID`.
          schema:
            type: string
        - name: limit
          in: query
          description: "Number of records per page. Default: 20."
          schema:
            type: integer
        - name: page
          in: query
          description: "Page number. Default: 1."
          schema:
            type: integer
      responses:
        "200":
          description: Your terminal branches.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TerminalBranchList"
        "401":
          description: The secret key is missing or invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/terminals/export:
    get:
      operationId: exportTerminals
      tags:
        - Terminals
      summary: Export terminals
      description: Exports the terminals on your merchant account as an Excel workbook, using the same filters as the terminals list.
      security:
        - secretKey: []
      parameters:
        - name: terminalId
          in: query
          description: Filter by terminal ID (ISO 8583 DE 41).
          schema:
            type: string
        - name: serialNo
          in: query
          description: Filter by terminal serial number.
          schema:
            type: string
        - name: status
          in: query
          description: Filter by terminal status.
          schema:
            type: string
            enum:
              - active
              - inactive
        - name: mode
          in: query
          description: Filter by terminal mode.
          schema:
            type: string
            enum:
              - test
              - live
        - name: merchantPayformanceId
          in: query
          description: Filter by merchant ID, e.g. `YOUR_MID`.
          schema:
            type: string
        - name: q
          in: query
          description: Quick search keyword.
          schema:
            type: string
      responses:
        "200":
          description: An Excel workbook holding the filtered terminals.
          content:
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
        "401":
          description: The secret key is missing or invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/terminals/{identifier}:
    get:
      operationId: getTerminal
      tags:
        - Terminals
      summary: Get terminal details
      description: Retrieves one terminal on your merchant account, including its branch, status, mode, and card-acceptance limits.
      security:
        - secretKey: []
      parameters:
        - name: identifier
          in: path
          required: true
          description: The terminal's identifier — its record ID, terminal ID, or serial number.
          schema:
            type: string
          example: YOUR_TERMINAL_ID
      responses:
        "200":
          description: The terminal.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Terminal"
        "401":
          description: The terminal does not belong to your merchant account, or the secret key is missing or invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
        "404":
          description: No terminal matches the identifier.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PosError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/products:
    get:
      operationId: listProducts
      tags:
        - Products
      summary: List products
      description: Retrieves the merchant's products. Every filter is optional — call it with no query at all to page through the whole catalogue, or narrow it down by category, stock status, currency, or a free-text search. This is the read an ERP uses to reconcile its own catalogue against Kashier's.
      security:
        - secretKey: []
      parameters:
        - name: ids
          in: query
          description: Comma-separated product record ids, to fetch a specific set of products.
          schema:
            type: string
        - name: categoryIds
          in: query
          description: Comma-separated category ids — only return products in these categories.
          schema:
            type: string
        - name: withVariants
          in: query
          description: Include each product's variants in the response. Defaults to `false`.
          schema:
            type: boolean
        - name: quantity
          in: query
          description: Only return products that track a stock quantity.
          schema:
            type: boolean
        - name: q
          in: query
          description: Free-text search across product names.
          schema:
            type: string
        - name: status
          in: query
          description: Filter by stock status. Defaults to `all`.
          schema:
            type: string
            enum:
              - outOfStock
              - available
              - all
        - name: isShippable
          in: query
          description: Only return products that are shippable.
          schema:
            type: boolean
        - name: isVariant
          in: query
          description: Only return products that are variants of another product.
          schema:
            type: boolean
        - name: currency
          in: query
          description: Only return products priced in this currency. Defaults to `EGP`.
          schema:
            type: string
            enum:
              - EGP
              - USD
              - EUR
              - GBP
        - name: page
          in: query
          description: Current page number. Defaults to 1.
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of records per page. Defaults to 20.
          schema:
            type: integer
        - name: sortBy
          in: query
          description: Field to sort by, for example `creationDate`.
          schema:
            type: string
        - name: sortType
          in: query
          description: "Sorting direction: 1 = ascending, -1 = descending. Defaults to -1."
          schema:
            type: integer
            enum:
              - 1
              - -1
      responses:
        "200":
          description: The products matching the filters, with pagination info.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/CatalogueProduct"
                  pagination:
                    $ref: "#/components/schemas/CataloguePagination"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
    post:
      operationId: createProduct
      tags:
        - Products
      summary: Create a product
      description: Adds a single product to the catalogue. Only the name, currency, and unit price are required; set isVariant when the product is a variation of another item, and quantity when you want Kashier to track stock and mark the product out of stock once it runs out.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CatalogueProductCreateRequest"
            examples:
              simple:
                summary: A stocked product priced in EGP
                value:
                  productName: Premium Widget
                  currency: EGP
                  unitPrice: 100
                  isVariant: false
                  quantity: 100
      responses:
        "200":
          description: The created product.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/CatalogueProduct"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/products/{id}:
    get:
      operationId: getProduct
      tags:
        - Products
      summary: Get a product
      description: Retrieves a single product by its record id, including its description, image, price, and stock status.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The product's record id.
          schema:
            type: string
      responses:
        "200":
          description: The product.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/CatalogueProduct"
        "404":
          description: No product with that id belongs to this merchant.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CatalogueError"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
    put:
      operationId: updateProduct
      tags:
        - Products
      summary: Update a product
      description: Updates an existing product. Send only the fields you want to change — anything you leave out keeps its current value, so this is safe to call from an ERP that only knows about price and stock movements.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The product's record id.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CatalogueProductUpdateRequest"
            examples:
              repriceAndRestock:
                summary: Change the price and the stock level
                value:
                  productName: Premium Widget
                  unitPrice: 110
                  quantity: 150
      responses:
        "200":
          description: The updated product.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/CatalogueProduct"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/products/{id}/timeline:
    get:
      operationId: getProductTimeline
      tags:
        - Products
      summary: Get a product's timeline
      description: Retrieves the audit trail for a product — every create and edit, which fields changed, and which dashboard user made the change.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The product's record id.
          schema:
            type: string
      responses:
        "200":
          description: The product's timeline entries.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      productId:
                        type: string
                      timeline:
                        type: array
                        items:
                          $ref: "#/components/schemas/CatalogueTimelineEntry"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/products/assign/categories:
    put:
      operationId: assignProductCategories
      tags:
        - Products
      summary: Assign or unassign categories in bulk
      description: Adds categories to, or removes them from, a set of products in one call. operation picks the direction, so the same endpoint covers both filing products into a new category and clearing them out of an old one.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CatalogueCategoryAssignRequest"
            examples:
              assign:
                summary: File two products into a category
                value:
                  categoryIds:
                    - 507f1f77bcf86cd799439011
                  productIds:
                    - 507f1f77bcf86cd799439012
                    - 507f1f77bcf86cd799439013
                  operation: assign
      responses:
        "200":
          description: How many products were updated.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: object
                    properties:
                      updatedCount:
                        type: integer
                      productIds:
                        type: array
                        items:
                          type: string
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/products/categories/change:
    put:
      operationId: changeProductCategories
      tags:
        - Products
      summary: Replace the categories on products
      description: Replaces the full category set on the given products with categoryIds, rather than adding to it. Use this when your ERP is the source of truth and you want Kashier to match it exactly.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CatalogueCategoryChangeRequest"
            examples:
              change:
                summary: Move a product into a single category
                value:
                  categoryIds:
                    - 507f1f77bcf86cd799439011
                  productIds:
                    - 507f1f77bcf86cd799439012
      responses:
        "200":
          description: How many products were updated.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: object
                    properties:
                      updatedCount:
                        type: integer
                      message:
                        type: string
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/products/export:
    get:
      operationId: exportProducts
      tags:
        - Products
      summary: Export products
      description: Exports the products matching the given filters and returns the Excel workbook directly in the response. The filters are the same ones listProducts accepts. For a large catalogue use exportProductsAsync instead, which emails the file rather than holding the request open.
      security:
        - secretKey: []
      parameters:
        - name: ids
          in: query
          description: Comma-separated product record ids, to export a specific set of products.
          schema:
            type: string
        - name: categoryIds
          in: query
          description: Comma-separated category ids — only export products in these categories.
          schema:
            type: string
        - name: withVariants
          in: query
          description: Include each product's variants.
          schema:
            type: boolean
        - name: q
          in: query
          description: Free-text search across product names.
          schema:
            type: string
        - name: status
          in: query
          description: Filter by stock status.
          schema:
            type: string
            enum:
              - outOfStock
              - available
              - all
        - name: isShippable
          in: query
          description: Only export products that are shippable.
          schema:
            type: boolean
        - name: currency
          in: query
          description: Only export products priced in this currency.
          schema:
            type: string
        - name: sortBy
          in: query
          description: Field to sort by, for example `creationDate`.
          schema:
            type: string
        - name: sortType
          in: query
          description: "Sorting direction: 1 = ascending, -1 = descending."
          schema:
            type: integer
            enum:
              - 1
              - -1
      responses:
        "200":
          description: The export as an Excel workbook.
          content:
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/products/export-async:
    get:
      operationId: exportProductsAsync
      tags:
        - Products
      summary: Export products asynchronously
      description: Exports the products matching the given filters without holding the request open. The workbook is generated in the background and emailed to email — or to the merchant account's own address when you leave it out — so the response only acknowledges the task.
      security:
        - secretKey: []
      parameters:
        - name: ids
          in: query
          description: Comma-separated product record ids, to export a specific set of products.
          schema:
            type: string
        - name: withVariants
          in: query
          description: Include each product's variants.
          schema:
            type: boolean
        - name: q
          in: query
          description: Free-text search across product names.
          schema:
            type: string
        - name: status
          in: query
          description: Filter by stock status.
          schema:
            type: string
            enum:
              - outOfStock
              - available
              - all
        - name: currency
          in: query
          description: Only export products priced in this currency.
          schema:
            type: string
        - name: email
          in: query
          description: Email address the finished export is sent to.
          schema:
            type: string
        - name: sortBy
          in: query
          description: Field to sort by, for example `creationDate`.
          schema:
            type: string
        - name: sortType
          in: query
          description: "Sorting direction: 1 = ascending, -1 = descending."
          schema:
            type: integer
            enum:
              - 1
              - -1
      responses:
        "200":
          description: Export accepted for processing — an email with the export follows shortly.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      taskId:
                        type: string
                      status:
                        type: string
                      email:
                        type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/products/upload:
    post:
      operationId: uploadProductImage
      tags:
        - Products
      summary: Upload a product image
      description: Uploads an image and returns the hosted URL for it. Upload the file first, then pass the returned URL as the product's image when you create or update it. Files must be under 5 MB.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - image
              properties:
                image:
                  type: string
                  format: binary
                  description: The product image file.
      responses:
        "200":
          description: The hosted URL for the uploaded image.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      fileUrl:
                        type: string
                      fileName:
                        type: string
                      size:
                        type: integer
                  message:
                    type: string
        "400":
          description: The file was rejected — most often because it is larger than 5 MB.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CatalogueError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/category:
    get:
      operationId: listCategories
      tags:
        - Categories
      summary: List categories
      description: Retrieves the merchant's product categories, paginated. Filter by name with q, or narrow the list to categories created inside a date range.
      security:
        - secretKey: []
      parameters:
        - name: q
          in: query
          description: Free-text search across category names.
          schema:
            type: string
        - name: page
          in: query
          description: Current page number.
          schema:
            type: integer
        - name: limit
          in: query
          description: Number of records per page.
          schema:
            type: integer
        - name: sortBy
          in: query
          required: true
          description: Field to sort by, for example `name`. This one is required — a request without it comes back as `"sortBy" is required`.
          schema:
            type: string
        - name: sortType
          in: query
          description: "Sorting direction: 1 = ascending, -1 = descending."
          schema:
            type: integer
            enum:
              - 1
              - -1
        - name: from
          in: query
          description: "Only return categories created after this date. Example: 01-01-2024"
          schema:
            type: string
        - name: to
          in: query
          description: "Only return categories created before this date. Example: 31-12-2024"
          schema:
            type: string
      responses:
        "200":
          description: The categories matching the filters, with pagination info.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/CatalogueCategory"
                  pagination:
                    $ref: "#/components/schemas/CataloguePagination"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
    post:
      operationId: createCategory
      tags:
        - Categories
      summary: Create a category
      description: Creates a product category. A category only needs a name; products are filed into it afterwards with assignProductCategories or changeProductCategories.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CatalogueCategoryWriteRequest"
            examples:
              create:
                summary: Create a category
                value:
                  name: Electronics
      responses:
        "201":
          description: The created category.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/CatalogueCategory"
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/category/{id}:
    get:
      operationId: getCategory
      tags:
        - Categories
      summary: Get a category
      description: Retrieves a single category by its record id.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The category's record id.
          schema:
            type: string
      responses:
        "200":
          description: The category.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/CatalogueCategory"
                  message:
                    type: string
        "400":
          description: The id is not a valid category id.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CatalogueError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    put:
      operationId: updateCategory
      tags:
        - Categories
      summary: Update a category
      description: Renames an existing category. The products filed into it are left untouched.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The category's record id.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CatalogueCategoryWriteRequest"
            examples:
              rename:
                summary: Rename a category
                value:
                  name: Electronics and appliances
      responses:
        "200":
          description: The updated category.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/CatalogueCategory"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    delete:
      operationId: deleteCategory
      tags:
        - Categories
      summary: Delete a category
      description: Deletes a category. Products that were filed into it stay in the catalogue — only the grouping goes away.
      security:
        - secretKey: []
      parameters:
        - name: id
          in: path
          required: true
          description: The category's record id.
          schema:
            type: string
      responses:
        "200":
          description: The category was deleted.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      deletedCount:
                        type: integer
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/category/simple:
    get:
      operationId: listSimpleCategories
      tags:
        - Categories
      summary: List a merchant's categories (public)
      description: Returns just the ids and names of a merchant's categories, with no pagination and no authentication. This is the lightweight read a storefront or a payment page uses to render a category picker, so it deliberately exposes nothing beyond the names.
      security: []
      parameters:
        - name: merchantId
          in: query
          required: true
          description: 'The merchant id the categories belong to, in `MID-` form. Required — a request without it comes back as `"merchantId" is required`. Example: `YOUR_MID`'
          schema:
            type: string
      responses:
        "200":
          description: The merchant's categories, as a bare array. An unknown merchant id simply returns an empty array rather than an error.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/CatalogueCategory"
        "400":
          $ref: "#/components/responses/BadRequest"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/category/paymentPage/{ppLink}/summary:
    get:
      operationId: getPaymentPageCategories
      tags:
        - Categories
      summary: Get the categories on a payment page (public)
      description: Returns the categories used by the products on a published product payment page, looked up by the page's link identifier. Unauthenticated, because the payment page itself calls it while a customer is browsing — it is the categories counterpart to getPublicPaymentPage.
      security: []
      parameters:
        - name: ppLink
          in: path
          required: true
          description: The payment page's link identifier.
          schema:
            type: string
      responses:
        "200":
          description: The categories represented on the payment page. An unknown link returns an empty `body` rather than an error.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: array
                    items:
                      $ref: "#/components/schemas/CatalogueCategory"
                  message:
                    type: string
              examples:
                empty:
                  summary: A page with no categorised products
                  value:
                    body: []
                    message: success
        "400":
          $ref: "#/components/responses/BadRequest"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/merchants/api-keys:
    get:
      operationId: listApiKeys
      tags:
        - Credentials and access
      summary: List your Payment API keys
      description: |
        Returns the Payment API keys on your merchant account — the keys used to compute the
        `Kashier-Hash` order hash and to verify redirect and webhook signatures. Payment API
        keys are not bearer credentials: you never send one as `Authorization`.

        Only keys for the environment you are calling are returned. A call to
        `test-api.kashier.io` sees only test keys, a call to `api.kashier.io` only live keys —
        there is no way to list the other environment's keys from here, and the two are never
        interchangeable. Kashier's own internal keys are filtered out.

        Requires the API-key permission on your user's role.
      security:
        - secretKey: []
      responses:
        "200":
          description: The account's Payment API keys for the current environment.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    type: array
                    items:
                      $ref: "#/components/schemas/MerchantApiKey"
                  message:
                    type: string
              examples:
                keys:
                  value:
                    body:
                      - mode: test
                        isInternal: false
                        merchantId: MID-123-456
                    message: success
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
        "400":
          $ref: "#/components/responses/BadRequest"
    put:
      operationId: createApiKey
      tags:
        - Credentials and access
      summary: Create a Payment API key
      description: |
        Issues a new Payment API key. Despite being a create, the verb is `PUT` and the
        operation is selected by a **required** `operation=apiKey.create` query parameter —
        omit it and the call is rejected.

        The key is created in the environment you called, taken from the host, not from
        anything you send. Requires the API-key permission on your user's role.

        Rotating a key is create-then-delete: issue the new key, move your integrations onto
        it, then delete the old one. There is no in-place rotation, so nothing breaks while
        both keys are live.
      security:
        - secretKey: []
      parameters:
        - name: operation
          in: query
          required: true
          description: Must be `apiKey.create`.
          schema:
            type: string
            enum:
              - apiKey.create
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - keyName
              properties:
                keyName:
                  type: string
                  description: Your label for the key.
            examples:
              create:
                value:
                  keyName: Storefront checkout
      responses:
        "200":
          description: The created key.
          content:
            application/json:
              schema:
                type: object
                properties:
                  body:
                    $ref: "#/components/schemas/MerchantApiKey"
                  message:
                    type: string
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/merchants/api-keys/{apiKeyId}:
    delete:
      operationId: deleteApiKey
      tags:
        - Credentials and access
      summary: Delete a Payment API key
      description: |
        Permanently removes a Payment API key. Anything still computing hashes with it starts
        failing signature verification immediately, so retire it from your integrations first.

        Requires the delete-API-key permission on your user's role — a role that can create
        keys does not necessarily get to delete them.
      security:
        - secretKey: []
      parameters:
        - name: apiKeyId
          in: path
          required: true
          description: The key's identifier, from List your Payment API keys.
          schema:
            type: string
      responses:
        "200":
          description: The key was deleted.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
        "400":
          $ref: "#/components/responses/BadRequest"
  /v2/merchants/validate-credentials:
    post:
      operationId: validateMerchantCredentials
      tags:
        - Credentials and access
      summary: Validate a set of credentials
      description: |
        Checks whether the secret keys and Payment API keys you hold are the right ones for
        the modes you have filed them under. Useful in a deployment check, or when a partner
        platform stores merchant credentials on the merchant's behalf and wants to catch a
        test key pasted into a live slot before a payment fails.

        Send whichever lists you want checked; each entry names the `mode` you believe the key
        belongs to and the key itself.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                secretKeys:
                  type: array
                  description: Secret keys to check.
                  items:
                    $ref: "#/components/schemas/CredentialToValidate"
                apiKeys:
                  type: array
                  description: Payment API keys to check.
                  items:
                    $ref: "#/components/schemas/CredentialToValidate"
            examples:
              validate:
                value:
                  secretKeys:
                    - mode: test
                      key: <your test secret key>
                  apiKeys:
                    - mode: test
                      key: <your test payment api key>
      responses:
        "200":
          description: The validation result.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/identity/secret-keys:
    get:
      operationId: listSecretKeys
      tags:
        - Credentials and access
      summary: List your secret keys
      description: |
        Returns the secret keys on your account — the credential you put in the `Authorization`
        header. Requires the API-key permission on your user's role.

        > Kashier has not published the response shape for this endpoint, so it is not
        > described here. Run it against your own account to see what you get.
      security:
        - secretKey: []
      responses:
        "200":
          description: The account's secret keys.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
        "400":
          $ref: "#/components/responses/BadRequest"
  /v2/identity/secret-keys/{userId}:
    put:
      operationId: updateSecretKeys
      tags:
        - Credentials and access
      summary: Update a user's secret keys
      description: |
        Updates the secret keys held for one dashboard user. Requires the API-key permission
        on your user's role.

        > **Treat this as destructive until you have confirmed its behaviour with Kashier.**
        > Kashier has published neither the request body nor the response for this endpoint,
        > and anything that changes a secret key can cut off every integration using it. Try
        > it on a test account first, and prefer creating and retiring Payment API keys — which
        > *are* documented — where that solves your problem.
      security:
        - secretKey: []
      parameters:
        - name: userId
          in: path
          required: true
          description: The dashboard user whose secret keys are being updated.
          schema:
            type: string
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
              description: Undocumented. The saved request Kashier ships sends an empty object.
            examples:
              empty:
                value: {}
      responses:
        "200":
          description: The update result.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
        "404":
          $ref: "#/components/responses/NotFound"
  /v2/ip-address:
    get:
      operationId: listAllowedIpAddresses
      tags:
        - Credentials and access
      summary: List the IP allow-list
      description: |
        Returns the IP addresses allowed to call Kashier with your secret key.

        **Read this first when a working integration suddenly returns 403.** Every secret-key
        call is checked against this list, and an IP that is not on it is refused with
        `403 Unauthorized IP address` — which looks like an authentication problem but is not.
        Because an **empty list allows every IP**, the allow-list is opt-in and silent until
        someone adds the first entry; from that moment every server you call from must be
        listed, including new deployment targets, NAT gateways and CI runners.

        Dashboard (JWT) sessions are never IP-checked — only secret-key callers are.
      security:
        - secretKey: []
      parameters:
        - name: q
          in: query
          required: false
          description: Search term.
          schema:
            type: string
        - name: page
          in: query
          required: false
          description: Page number.
          schema:
            type: integer
        - name: limit
          in: query
          required: false
          description: Page size.
          schema:
            type: integer
        - name: sortBy
          in: query
          required: false
          description: Field to sort by, e.g. `createdAt`.
          schema:
            type: string
        - name: sortType
          in: query
          required: false
          description: Sort direction — `1` ascending, `-1` descending.
          schema:
            type: integer
            enum:
              - 1
              - -1
      responses:
        "200":
          description: The allow-list entries.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                description: Kashier has not published the exact envelope; each entry carries at least the address and whether it is active.
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
    post:
      operationId: createAllowedIpAddress
      tags:
        - Credentials and access
      summary: Add an IP to the allow-list
      description: |
        Adds one address to the allow-list.

        **Adding the first entry switches the allow-list on.** Until then every IP is allowed;
        the moment one entry exists, every other IP is refused with `403 Unauthorized IP
        address`. So add *all* of your callers before you rely on the list, and make sure the
        machine you are adding from is one of them.

        Requires the create-IP permission on your user's role.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AllowedIpAddressRequest"
            examples:
              add:
                value:
                  name: Production API server
                  ipAddress: 203.0.113.24
                  userId: 507f1f77bcf86cd799439012
      responses:
        "201":
          description: The address was added.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/ip-address/toggle-all:
    put:
      operationId: toggleAllAllowedIpAddresses
      tags:
        - Credentials and access
      summary: Enable or disable the whole allow-list
      description: |
        Turns every entry on the allow-list active or inactive in one call — the escape hatch
        for when the list has locked you out. Sending `isActive: false` deactivates every
        entry, which leaves no active entries, which means every IP is allowed again.

        Requires both the edit-IP and create-IP permissions on your user's role.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - isActive
              properties:
                isActive:
                  type: boolean
                  description: "`true` to activate every entry, `false` to deactivate every entry."
            examples:
              disable:
                summary: Lift the restriction entirely
                value:
                  isActive: false
      responses:
        "200":
          description: The entries were toggled.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/ip-address/{ipId}:
    get:
      operationId: getAllowedIpAddress
      tags:
        - Credentials and access
      summary: Get one allow-list entry
      description: Returns a single IP allow-list entry. Requires the view-IP permission on your user's role.
      security:
        - secretKey: []
      parameters:
        - name: ipId
          in: path
          required: true
          description: The entry's identifier, from List the IP allow-list.
          schema:
            type: string
      responses:
        "200":
          description: The allow-list entry.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
        "400":
          $ref: "#/components/responses/BadRequest"
    put:
      operationId: updateAllowedIpAddress
      tags:
        - Credentials and access
      summary: Update an allow-list entry
      description: Changes the address or label on an existing entry. Send the whole entry, not just the field you are changing. Requires the edit-IP permission on your user's role.
      security:
        - secretKey: []
      parameters:
        - name: ipId
          in: path
          required: true
          description: The entry's identifier.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AllowedIpAddressRequest"
            examples:
              update:
                value:
                  name: Production API server
                  ipAddress: 203.0.113.25
                  userId: 507f1f77bcf86cd799439012
      responses:
        "200":
          description: The entry was updated.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    delete:
      operationId: deleteAllowedIpAddress
      tags:
        - Credentials and access
      summary: Remove an IP from the allow-list
      description: |
        Deletes one entry. Removing the **last** entry empties the list, and an empty list
        allows every IP — deleting entries loosens the restriction rather than tightening it.

        Requires the delete-IP permission on your user's role.
      security:
        - secretKey: []
      parameters:
        - name: ipId
          in: path
          required: true
          description: The entry's identifier.
          schema:
            type: string
      responses:
        "200":
          description: The entry was removed.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
        "400":
          $ref: "#/components/responses/BadRequest"
  /v2/webhooks:
    get:
      operationId: listWebhooks
      tags:
        - Webhooks
      summary: List your webhooks
      description: Returns every webhook configured for your merchant, across both modes.
      security:
        - secretKey: []
      responses:
        "200":
          description: The merchant's configured webhooks.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Webhook"
              examples:
                webhooks:
                  value:
                    - _id: 66a1f2c3e4b0a1234567890a
                      merchantId: MID-10293
                      name: Orders production endpoint
                      url: https://shop.example.com/kashier/webhook
                      headers:
                        X-Shop-Token: whsec_live_abc123
                        X-Env: production
                      events:
                        - pay
                        - refund
                        - void
                        - TRANSFERRED
                      mode: live
                      isActive: true
                      createdAt: 2026-06-22T12:00:00.000Z
                      updatedAt: 2026-06-22T12:00:00.000Z
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
    post:
      operationId: createWebhook
      tags:
        - Webhooks
      summary: Create a webhook
      description: Creates a new webhook for your merchant. The webhook's `url` must be `https`. There is a cap on how many webhooks you can hold in each mode; once you reach it, creating another webhook in that mode is rejected until you delete one.
      security:
        - secretKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
                - url
                - events
                - mode
              properties:
                name:
                  type: string
                  description: Your label for the webhook.
                url:
                  type: string
                  format: uri
                  description: The endpoint Kashier delivers to. Must be a public `https` URL — non-`https` schemes, `localhost`, loopback, link-local, and private (RFC-1918) addresses are rejected.
                headers:
                  type: object
                  description: Optional. Custom headers to send with every delivery to this webhook, as a flat string-to-string map. Defaults to `{}`.
                  additionalProperties:
                    type: string
                events:
                  $ref: "#/components/schemas/WebhookEventList"
                mode:
                  type: string
                  description: The webhook only receives events emitted in this mode.
                  enum:
                    - test
                    - live
                isActive:
                  type: boolean
                  description: Optional. Whether the webhook is enabled. Defaults to `true`.
            examples:
              create:
                value:
                  name: Orders production endpoint
                  url: https://shop.example.com/kashier/webhook
                  headers:
                    X-Shop-Token: whsec_live_abc123
                    X-Env: production
                  events:
                    - pay
                    - refund
                    - void
                    - TRANSFERRED
                  mode: live
                  isActive: true
      responses:
        "200":
          description: The created webhook, in the same shape as an entry in the list response.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Webhook"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/webhooks/events:
    get:
      operationId: listWebhookEvents
      tags:
        - Webhooks
      summary: List subscribable events
      description: |
        Returns the catalog of event types a webhook can subscribe to — the exact values that
        are valid in the `events` array of Create a webhook and Update a webhook.

        Read this catalog rather than hard-coding a copy of the list. It is the source Kashier
        validates against, so a list you maintain separately will drift the moment Kashier adds
        an event, and a subscription containing a value that is not in the catalog is rejected.

        Each entry pairs the literal `value` you subscribe with a human `label` and the
        `resource` it belongs to. There are two families: **transaction** events, whose value
        is the operation that produced them (`pay`, `authorize`, `capture`, `refund`, `void`,
        `reversal`), and **transfer** events, whose value is the transfer status reached
        (`INITIATED`, `IN_TRANSIT`, `TRANSFERRED`, `FAILED`). Casing is significant and matched
        literally.

        Note what is *not* in the catalog: a card decline, a Meeza payment, an Apple Pay
        payment and a Fawry payment are all `pay` events — payment method and outcome are
        variations inside the payload, not separate event types. Always read `data.status`
        rather than treating the arrival of a `pay` event as proof of payment.
      security:
        - secretKey: []
      responses:
        "200":
          description: The event catalog.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/WebhookEventCatalogEntry"
              examples:
                catalog:
                  value:
                    - value: pay
                      label: Payment
                      resource: transaction
                    - value: refund
                      label: Refund
                      resource: transaction
                    - value: TRANSFERRED
                      label: Transferred
                      resource: transfer
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "500":
          $ref: "#/components/responses/ServerError"
        "400":
          $ref: "#/components/responses/BadRequest"
  /v2/webhooks/{webhookId}:
    put:
      operationId: updateWebhook
      tags:
        - Webhooks
      summary: Update a webhook
      description: Updates an existing webhook. Send only the fields you want to change. The `https`-only URL rule from webhook creation applies here too. Moving a webhook to the other `mode` re-checks that mode's webhook cap, so an update can be rejected if the target mode is already full.
      security:
        - secretKey: []
      parameters:
        - name: webhookId
          in: path
          required: true
          description: The webhook's `_id`, from List your webhooks or Create a webhook.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: Your label for the webhook.
                url:
                  type: string
                  format: uri
                  description: The endpoint Kashier delivers to. Must be a public `https` URL — non-`https` schemes, `localhost`, loopback, link-local, and private (RFC-1918) addresses are rejected.
                headers:
                  type: object
                  description: Custom headers to send with every delivery to this webhook, as a flat string-to-string map.
                  additionalProperties:
                    type: string
                events:
                  $ref: "#/components/schemas/WebhookEventList"
                mode:
                  type: string
                  description: The webhook only receives events emitted in this mode.
                  enum:
                    - test
                    - live
                isActive:
                  type: boolean
                  description: Whether the webhook is enabled.
            examples:
              deactivate:
                summary: Deactivate a webhook
                value:
                  isActive: false
      responses:
        "200":
          description: The updated webhook, in the same shape as an entry in the list response.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Webhook"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
    delete:
      operationId: deleteWebhook
      tags:
        - Webhooks
      summary: Delete a webhook
      description: Removes a webhook. There's no undo — deliveries already recorded against it stay visible in delivery records.
      security:
        - secretKey: []
      parameters:
        - name: webhookId
          in: path
          required: true
          description: The webhook's `_id`.
          schema:
            type: string
      responses:
        "200":
          description: The webhook was deleted.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/webhooks/records/transaction/{transactionId}:
    get:
      operationId: getWebhookRecordsForTransaction
      tags:
        - Webhooks
      summary: Get delivery records for a transaction
      description: |
        > **⚠️ Not yet available on the test environment.** This route is **not registered** on
        > `test-api.kashier.io` today: calling it there returns a bare `404`, not a records payload,
        > while the webhook CRUD endpoints on the same router answer normally. It is specified but
        > not shipped, so the **"Try it" panel below cannot succeed**. Check with your
        > Kashier contact before building against it.

        Returns the delivery log for a given transaction — every webhook attempt made for it, across all your configured webhooks, plus any per-session webhook you passed directly on that transaction.
      security:
        - secretKey: []
      parameters:
        - name: transactionId
          in: path
          required: true
          description: The transaction id (e.g. `TX-249893963`).
          schema:
            type: string
      responses:
        "200":
          description: Delivery records for the transaction.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  body:
                    type: array
                    items:
                      $ref: "#/components/schemas/WebhookDeliveryRecord"
              examples:
                records:
                  value:
                    success: true
                    body:
                      - resourceType: transaction
                        resourceId: TX-249893963
                        webhookId: 66a1f2c3e4b0a1234567890a
                        eventType: pay
                        mode: live
                        url: https://shop.example.com/kashier/webhook
                        status: delivered
                        attempts: 1
                        payload:
                          ...: allow-listed fields only
                        responses:
                          - status: 200
                            body: OK
                            date: 2026-06-22T12:00:01.000Z
                        isServerWebhook: false
                        isTest: false
                        createdAt: 2026-06-22T12:00:00.000Z
                        updatedAt: 2026-06-22T12:00:01.000Z
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/webhooks/records/transfer/{transferId}:
    get:
      operationId: getWebhookRecordsForTransfer
      tags:
        - Webhooks
      summary: Get delivery records for a transfer
      description: |
        > **⚠️ Not yet available on the test environment.** Like its transaction counterpart, this
        > route is **not registered** on `test-api.kashier.io` today and returns a bare `404`, while
        > the webhook CRUD endpoints on the same router answer normally. It is specified but not
        > shipped, so the **"Try it" panel below cannot succeed**. Check with your Kashier
        > contact before building against it.

        Same records lookup as Get delivery records for a transaction, scoped to a transfer instead of a transaction. `resourceType` is `transfer`, `resourceId` is the transfer id, and `eventType` is one of the transfer status values (`INITIATED`, `IN_TRANSIT`, `TRANSFERRED`, `FAILED`).
      security:
        - secretKey: []
      parameters:
        - name: transferId
          in: path
          required: true
          description: The transfer id.
          schema:
            type: string
      responses:
        "200":
          description: Delivery records for the transfer.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  body:
                    type: array
                    items:
                      $ref: "#/components/schemas/WebhookDeliveryRecord"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/webhooks/records/{recordId}/resend:
    post:
      operationId: resendWebhookRecord
      tags:
        - Webhooks
      summary: Resend a delivery
      description: Re-sends a previously recorded delivery — the original stored request, byte-for-byte, including its original signature — to the same URL. Useful after fixing an endpoint that was down or returning errors. The outcome is written to a new record; the original record is never modified, so delivery history stays intact. A record can be resent from any status, including `delivered`. Resending the same record again within 30 seconds returns `429`.
      security:
        - secretKey: []
      parameters:
        - name: recordId
          in: path
          required: true
          description: The delivery record's id to resend.
          schema:
            type: string
      responses:
        "200":
          description: The outcome of the resend, recorded as a new delivery record.
          content:
            application/json:
              schema:
                type: object
                properties:
                  recordId:
                    type: string
                    description: ID of the new delivery record created for this resend.
                  clonedFromRecordId:
                    type: string
                    description: ID of the original record this resend replayed.
                  status:
                    type: string
                    description: Outcome of the resend, e.g. `delivered` or `failed`.
                  attempts:
                    type: integer
                    description: Attempts recorded on the new record (always `1` immediately after a resend).
                  lastResponseStatus:
                    type: integer
                    description: HTTP status your endpoint returned for the resend attempt.
              examples:
                resent:
                  value:
                    recordId: 66a20a1ce4b0a1234567891b
                    clonedFromRecordId: 66a1f2c3e4b0a1234567890c
                    status: delivered
                    attempts: 1
                    lastResponseStatus: 200
        "429":
          description: Resend cooldown — the same record was resent less than 30 seconds ago.
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
  /v2/webhooks/{webhookId}/test:
    post:
      operationId: testWebhook
      tags:
        - Webhooks
      summary: Test a webhook
      description: |
        > **⚠️ Not yet available on the test environment.** This route is **not registered** on
        > `test-api.kashier.io` today: calling it there returns a bare `404` rather than sending a
        > test delivery, while the webhook CRUD endpoints on the same router answer normally. It is
        > specified but not shipped, so the **"Try it" panel below cannot succeed**.
        > Check with your Kashier contact before building against it.

        Sends a signed sample payload to a webhook's configured URL so you can confirm the endpoint is reachable and your signature verification works — without waiting for a real event. The test delivery is recorded like any other delivery, but flagged `isTest: true` so it's distinguishable in your delivery history.
      security:
        - secretKey: []
      parameters:
        - name: webhookId
          in: path
          required: true
          description: The webhook's `_id`.
          schema:
            type: string
      requestBody:
        required: false
        description: |
          Optional. Send an empty body (or no body at all) to test the webhook exactly as it is
          saved. Send any of the fields below to override the saved configuration for this one
          test delivery only — nothing is written back to the webhook.
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                  format: uri
                  description: Deliver this test to a different URL instead of the saved one. Must be `https`.
                headers:
                  type: object
                  description: Headers to send with this test delivery instead of the saved ones, as a flat string-to-string map.
                  additionalProperties:
                    type: string
                event:
                  $ref: "#/components/schemas/WebhookEvent"
            examples:
              savedConfig:
                summary: Test the webhook exactly as saved
                value: {}
              adHoc:
                summary: Override the URL and event for this test only
                value:
                  url: https://example.com/kashier-webhooks/staging
                  headers:
                    x-my-token: abc123
                  event: pay
      responses:
        "200":
          description: The result of the test delivery.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: "`true` if your endpoint returned a 2xx status."
                  statusCode:
                    type: integer
                    description: HTTP status your endpoint returned.
                  responseBody:
                    type: string
                    description: A truncated snippet of your endpoint's response body.
                  latencyMs:
                    type: integer
                    description: Round-trip time for the test delivery, in milliseconds.
              examples:
                tested:
                  value:
                    success: true
                    statusCode: 200
                    responseBody: OK
                    latencyMs: 184
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "500":
          $ref: "#/components/responses/ServerError"
components:
  securitySchemes:
    secretKey:
      type: apiKey
      in: header
      name: Authorization
      description: Merchant secret key used to identify the merchant, obtained from Kashier's dashboard. Pass the raw secret key value in the `Authorization` header (NOT a "Bearer" token).
    apiKey:
      type: apiKey
      in: header
      name: api-key
      description: API key obtained from the merchant dashboard under the Integrations section. The API key is different for the live and test environments, so make sure to use the correct one for each.
  parameters:
    KashierHash:
      name: Kashier-Hash
      in: header
      required: true
      description: Order hash generated from your backend using the HMAC SHA256 crypto mechanism, as described in the Kashier hashing documentation.
      schema:
        type: string
    BalanceAccountId:
      name: accountId
      in: path
      required: true
      description: Balance account identifier.
      schema:
        type: string
    BalanceRecordId:
      name: recordId
      in: path
      required: true
      description: Balance record identifier.
      schema:
        type: string
    SettlementWindowId:
      name: windowId
      in: path
      required: true
      description: Settlement window identifier.
      schema:
        type: string
    SettlementBatchId:
      name: batchId
      in: path
      required: true
      description: Settlement batch identifier.
      schema:
        type: string
    BalanceDateFrom:
      name: dateFrom
      in: query
      required: false
      description: Start of the date range (ISO 8601).
      schema:
        type: string
        format: date-time
    BalanceDateTo:
      name: dateTo
      in: query
      required: false
      description: End of the date range (ISO 8601).
      schema:
        type: string
        format: date-time
  responses:
    # ---------------------------------------------------------------------------
    # Shared error contract.
    #
    # Kashier does not use one error envelope everywhere: the gateway's terminal
    # handler emits `{ error: { cause }, messages: { en, ar }, status: "FAILURE" }`,
    # while the auth and validation layers that run *before* a controller each
    # return their own flat shape. Every response below therefore documents the
    # shapes that can actually reach you at that status code, so you can branch on
    # the HTTP status plus the keys that are present.
    #
    # Note the status codes for authentication — they are the opposite of what most
    # APIs do, and of what Kashier's own older docs said:
    #   * a MISSING Authorization header  -> 403 (not 401)
    #   * an INVALID/expired credential   -> 401
    #   * an IP outside your allow-list   -> 403
    # ---------------------------------------------------------------------------
    BadRequest:
      description: |
        The request was rejected before it was processed — a missing or malformed field,
        a bad `merchantId`, or a feature that is switched off for your account.

        Four different bodies can arrive with a 400, depending on which layer rejected you:

        - `{ "message": "…" }` — the usual case. Field validation failed; the message is the
          first validation error, localized with the `client-lang` request header.
        - `{ "more_info": [ … ] }` — the request failed OpenAPI schema validation, and the
          array holds one entry per schema error.
        - `{ "error": "Invalid merchantId format. It should be in the format MID-XXX-XXX" }` —
          `merchantId` did not match `MID-<digits>-<digits>`.
        - `{ "error": { "cause": … }, "messages": { "en", "ar" }, "status": "FAILURE" }` — a
          service rejected the request (this is also the shape some disabled feature flags use).
      content:
        application/json:
          schema:
            anyOf:
              - $ref: "#/components/schemas/MessageError"
              - $ref: "#/components/schemas/InputValidationError"
              - $ref: "#/components/schemas/FieldError"
              - $ref: "#/components/schemas/ErrorEnvelope"
          examples:
            validation:
              summary: Field validation failed
              value:
                message: amount is required
            schemaValidation:
              summary: OpenAPI schema validation failed
              value:
                more_info:
                  - keyword: required
                    dataPath: .body
                    message: should have required property 'amount'
            merchantIdFormat:
              summary: Malformed merchantId
              value:
                error: Invalid merchantId format. It should be in the format MID-XXX-XXX
    Unauthorized:
      description: |
        Your credential was **present but not accepted** — wrong, expired, revoked, or
        belonging to the other environment (test keys do not work on live hosts, and vice
        versa). Note that *omitting* the `Authorization` header gives you a **403**, not a
        401; a 401 always means Kashier looked at a credential and rejected it.

        A 401 is also what you get when your user's role lacks the permission the endpoint
        needs, when a dashboard session no longer matches, and — on `authorizeFeatures`-gated
        endpoints — when the feature is not enabled on your account.
      content:
        application/json:
          schema:
            anyOf:
              - $ref: "#/components/schemas/AuthorizationError"
              - $ref: "#/components/schemas/MessageError"
          examples:
            invalidCredential:
              summary: Bad or expired secret key
              value:
                error: Authorization error
                message: Invalid secret key
            notPermitted:
              summary: Role lacks the required permission
              value:
                error: Authorization error
                message: Not authorized to perform this action
            unauthorized:
              summary: Fallthrough / feature not enabled for your account
              value:
                message: Unauthorized
    Forbidden:
      description: |
        Kashier refused to even look at a credential, or looked at where the call came from
        and refused it. Three causes, all returning a flat `{ "message": … }`:

        - **No `Authorization` header at all** — `No auth token provided`. This is the one
          that surprises people: a missing header is a **403**, not a 401.
        - **Your IP is not on the allow-list** — `Unauthorized IP address`. Every secret-key
          call is checked against the per-merchant IP allow-list managed at `/v2/ip-address`.
          An **empty** allow-list allows every IP, so this only appears once you have added
          at least one entry — which makes it a common and confusing cause of a previously
          working integration suddenly failing from a new server. Dashboard (JWT) callers are
          not IP-checked.
        - **A live-only endpoint called in test mode** — `This API is only available on live mode`.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/MessageError"
          examples:
            missingHeader:
              summary: No Authorization header
              value:
                message: No auth token provided
            ipNotAllowed:
              summary: Caller IP is not on the merchant's allow-list
              value:
                message: Unauthorized IP address
            liveOnly:
              summary: Live-only endpoint called on the test host
              value:
                message: This API is only available on live mode
    NotFound:
      description: |
        The resource does not exist, or it exists but does not belong to your merchant
        account — Kashier scopes every lookup to your MID and reports someone else's record
        as missing rather than as forbidden.
      content:
        application/json:
          schema:
            anyOf:
              - $ref: "#/components/schemas/ErrorEnvelope"
              - $ref: "#/components/schemas/MessageError"
          examples:
            notFound:
              summary: Standard error envelope
              value:
                error:
                  cause: resource not found
                messages:
                  en: Payment session not found
                  ar: Payment session not found
                status: FAILURE
    Conflict:
      description: |
        The write collided with a record that already exists. `message` names the field that
        clashed — an invoice number, a category name, or a `merchantId` + `referenceId` pair.
        Retrying the same request will keep failing; change the conflicting value instead.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/DuplicateKeyError"
          examples:
            duplicate:
              value:
                status: 409
                message: The invoice number has already been used. Please enter another invoice number.
                code: DUPLICATE_KEY_ERROR
    ServerError:
      description: |
        Something failed inside Kashier. The body is either the standard envelope or a bare
        `{ "message": … }`, depending on whether the failure was recognised. These are safe
        to retry for reads; for writes, reconcile before retrying so you do not double-charge.
      content:
        application/json:
          schema:
            anyOf:
              - $ref: "#/components/schemas/ErrorEnvelope"
              - $ref: "#/components/schemas/MessageError"
  schemas:
    ErrorEnvelope:
      type: object
      description: |
        The standard Kashier error envelope, emitted by the gateway's terminal error handler
        for any error a service raised deliberately. `status` is always the literal string
        `FAILURE` here — do not confuse it with the numeric `status` on a success response.
      properties:
        error:
          type: object
          description: The technical cause. `cause` is the name of the error that was raised, not a merchant-facing message — use `messages` for anything you show a customer.
          properties:
            cause:
              type: string
              example: The request object is invalid
        messages:
          $ref: "#/components/schemas/LocalizedMessage"
        status:
          type: string
          description: Always `FAILURE` on this envelope.
          enum:
            - FAILURE
    MessageError:
      type: object
      description: A flat error message. Used by the authentication, validation, and live-mode layers, which run before a controller and do not use the standard envelope.
      properties:
        message:
          type: string
    AuthorizationError:
      type: object
      description: Returned when authentication or authorization failed after a credential was supplied. `message` varies with the underlying cause (`Invalid secret key`, `Invalid token`, `Invalid user type`, `Not authorized to perform this action`, `Your session has expired. Please log in again`, `Merchant <MID> is not live.`).
      properties:
        error:
          type: string
          enum:
            - Authorization error
        message:
          type: string
    InputValidationError:
      type: object
      description: Returned when a request fails OpenAPI schema validation at the gateway, before any other validation runs.
      properties:
        more_info:
          type: array
          description: One entry per schema violation.
          items:
            type: object
            additionalProperties: true
    FieldError:
      type: object
      description: A validation error reported under an `error` key rather than `message` — most notably a `merchantId` that does not match `MID-<digits>-<digits>`.
      properties:
        error:
          type: string
    DuplicateKeyError:
      type: object
      description: Returned when a write violates a uniqueness constraint.
      properties:
        status:
          type: integer
          enum:
            - 409
        message:
          type: string
          description: A field-specific message naming what already exists.
        code:
          type: string
          enum:
            - DUPLICATE_KEY_ERROR
    LocalizedMessage:
      type: object
      description: Message localized in English and Arabic.
      properties:
        en:
          type: string
        ar:
          type: string
    Customer:
      type: object
      description: Customer information. It should include `customer.reference`, which will be used to link the merchant's customer with the payment's customer, and it should only be included when `saveCard` is `optional` or `forced`.
      properties:
        email:
          type: string
        reference:
          type: string
          description: customer reference ID
    MetaData:
      type: object
      description: 'Order metadata. `displayNotes` is a nested key/value object whose note will be displayed on the PaymentUI screen, e.g. {"customKey": "customValue", "displayNotes": {"key": "value"}}.'
      additionalProperties: true
      properties:
        displayNotes:
          type: object
          additionalProperties: true
    Pagination:
      type: object
      properties:
        total:
          type: integer
        limit:
          type: integer
        page:
          type: integer
        pages:
          type: integer
        lastPage: {}
    HistoryEntry:
      type: object
      description: A status change / action taken on the resource.
      properties:
        status:
          type: string
          description: The action performed (e.g., "OPENED")
        date:
          type: string
          description: The timestamp of the action.
    OrderStatus:
      type: string
      description: |
        The order-level state machine — the single field that answers "was this order paid?".
        Distinct from the per-transaction `status`, and distinct again from the
        `Approved`/`Rejected`/`Unknown` labels the transactions list projects.

        An order sitting at `INITIATED` after the customer has gone is a reconciliation
        candidate, not a confirmed failure: both an in-progress transaction and one whose
        outcome is genuinely unknown land here.

        - `INITIATED` — created, with no terminal money movement yet: 3DS still pending,
          awaiting capture, or an outcome Kashier could not confirm.
        - `CAPTURED` — money captured. This is the paid state.
        - `AUTHORIZED` — funds held on the card but not yet captured (auth-and-capture flow).
        - `FAILED` — the payment attempt was declined or errored.
        - `CANCELLED` — cancelled, for example an authorization that was voided.
        - `REVERSED` — reversed (POS reversal).
        - `EXPIRED` — expired before completion.
        - `REJECTED` — rejected, for example an installment or BNPL application turned down.
      enum:
        - INITIATED
        - CAPTURED
        - AUTHORIZED
        - FAILED
        - CANCELLED
        - REVERSED
        - EXPIRED
        - REJECTED
    TransactionStatus:
      type: string
      description: The raw outcome of one transaction attempt. This is also the value Kashier sends as `data.status` on a payment webhook. `SUCCESS` maps to order `CAPTURED`; `FAILURE` to `FAILED`; `INITIATED`, `UNKNOWN` and `PENDING` all map to order `INITIATED`. Treat `UNKNOWN` as neither paid nor failed until you have reconciled it.
      enum:
        - SUCCESS
        - FAILURE
        - INITIATED
        - PENDING
        - UNKNOWN
        - EXPIRED
        - CANCEL
        - REVOKED
    ReconciliationVerdict:
      type: string
      description: |
        Kashier's own verdict on whether a transaction matches the counterpart record it was
        checked against. Defaults to `NA` — intermediate steps such as `3dsecure_verify` are
        never reconciled on their own, so `NA` on those is normal and not a warning sign.

        - `OK` — reconciled and matched.
        - `Failed` — reconciliation ran but did not match. Investigate this transaction.
        - `Not_Exists` — the counterpart record was not found on the side being reconciled.
        - `NA` — not applicable, or not yet reconciled. The default.
      enum:
        - OK
        - Failed
        - Not_Exists
        - "NA"
    ReconciledOrderTransaction:
      type: object
      description: |
        One attempt against the order. An order normally holds several: the 3DS legs, the pay
        itself, and later any capture, refund or void. Heavy internal fields (`request`,
        `response`, `requestCredentials`, `pccFees`) are stripped from this projection.
      additionalProperties: true
      properties:
        operation:
          type: string
          description: What this transaction did — `pay`, `3dsecure_verify`, `authenticate_payer`, `capture`, `refund`, `void`, `reversal`, and so on.
        status:
          $ref: "#/components/schemas/TransactionStatus"
        transactionResponseCode:
          type: string
          description: The provider or gateway code — an ISO-8583 numeric (`00`, `51`), an alpha gateway code (`APPROVED`, `DECLINED`, `AUTHENTICATION_IN_PROGRESS`), or a Kashier `k_*` code.
        transactionResponseMessage:
          $ref: "#/components/schemas/LocalizedMessage"
        reconcilation:
          allOf:
            - $ref: "#/components/schemas/ReconciliationVerdict"
          description: Kashier's reconciliation of this transaction against the provider. Note the spelling — one `i` — in both the API and the underlying schema.
        merchantWebhookReconciliation:
          allOf:
            - $ref: "#/components/schemas/ReconciliationVerdict"
          description: Whether the webhook Kashier sent you for this transaction was delivered and acknowledged.
        kashierBlocked:
          type: boolean
          description: "`true` when Kashier declined the attempt itself — for example the card-retry guard — before it reached the acquirer. Blocked transactions are excluded from reconciliation jobs."
        isSettled:
          type: boolean
          description: Whether this transaction has been settled to your balance.
        settlementDate:
          type: string
          description: The date the transaction settled.
        settlementWindowId:
          type: string
          description: The settlement window this transaction was grouped into. Use it with the settlement reporting endpoints to find the payout it landed in.
        settlementBatchId:
          type: string
          description: The settlement batch this transaction was grouped into.
    ReconciledOrder:
      type: object
      description: An order as stored by Kashier, projected for reconciliation. Fields beyond those listed here are returned as stored, so treat this as an open object.
      additionalProperties: true
      properties:
        merchantOrderId:
          type: string
          description: Your own order identifier — the one `search` matches against.
        orderId:
          type: string
          description: Kashier's order identifier.
        orderReference:
          type: string
          description: The human-readable order reference Kashier assigned.
        status:
          $ref: "#/components/schemas/OrderStatus"
        interChangeRate:
          type: string
          description: Which interchange band the transaction fell into.
        transactions:
          type: array
          description: Every transaction recorded against this order, in the order they happened.
          items:
            $ref: "#/components/schemas/ReconciledOrderTransaction"
    CreatePaymentSessionRequest:
      type: object
      required:
        - expireAt
        - maxFailureAttempts
        - amount
        - currency
        - order
        - merchantId
        - merchantRedirect
        - type
        - display
        - customer
      properties:
        expireAt:
          type: string
          description: When the payment session expires. Must be a future ISO 8601 timestamp.
        maxFailureAttempts:
          type: integer
          description: Maximum number of payment attempts.
        paymentType:
          type: string
          description: Payment type, e.g. `credit`.
        amount:
          type: string
          description: Order amount, e.g., `100`.
        currency:
          type: string
          description: Order currency, e.g., `EGP`.
          enum:
            - EGP
            - USD
            - GBP
            - EUR
        order:
          type: string
          description: Unique order identifier. (The docs' body table names this field `orderId`, but request and response examples use `order`.)
        merchantId:
          type: string
          description: Merchant account number or merchant ID, e.g., `MID-123-123`.
        mode:
          type: string
          description: Mode of operation, test or live, e.g., `mode="test"`. (Documented in the body table but not present in the docs' request example.)
        metaData:
          $ref: "#/components/schemas/MetaData"
        description:
          type: string
          description: Order description; must be less than 120 characters.
        allowedMethods:
          type: string
          description: "Defines allowed payment methods. Default: `card, bank_installments, wallet, bnpl`. If you want to display only a specific provider (for example, Valu or QNB), you can do so by specifying it within array brackets alongside its payment method. For example: bnpl[valu], bank_installments[qnb], and so on."
        defaultMethod:
          type: string
          description: 'To determine which method you want PaymentUI to open on. By default PaymentUI opens on card method. defaultMethod accepts the pattern "method,provider/abbreviation". Example: for the installment method use `bank_installments`; to open PaymentUI on certain installment plans of NBE bank use `bank_installments,NBE`.'
        merchantRedirect:
          type: string
          description: "merchantRedirect should be URI encoded: urlencode(https://www.your_website.com/redirect)"
        serverWebhook:
          type: string
          description: Pass an endpoint to receive server-to-server notifications. Your application only needs a page that accepts unauthenticated POST requests; the event object is sent as JSON in the request body.
        redirectMethod:
          type:
            - string
            - "null"
          description: 'The redirection method after payment. Default method is get, ex: redirectMethod="post"'
        failureRedirect:
          type: boolean
          description: To choose to redirect after first payment failure or not. Its value is TRUE or FALSE; default value is TRUE.
        connectedAccount:
          type: string
          description: Used in case of making payments on behalf of your Connected Account by passing the Sub Merchant/Connected Account Merchant Id, e.g. connectedAccount="MID-452-644".
        type:
          type: string
          description: "Defines the type of Kashier origin. Default: `external`."
        brandColor:
          type: string
          description: "Specifies branding color using a hex or rgba value. Default: `rgba(45, 164, 78, 0.9)`."
        display:
          type: string
          description: "Specifies the display language of the I-frame. Options: `ar` or `en`."
          enum:
            - ar
            - en
        iframeBackgroundColor:
          type: string
          description: Background color of the payment iframe, e.g. `#FFFFFF`.
        manualCapture:
          type: boolean
          description: "`TRUE`: Authorize first, then capture/release. `FALSE`: Direct capture without authorization."
        customer:
          $ref: "#/components/schemas/Customer"
        saveCard:
          type: string
          description: "Defines if card information is saved. Options: `optional` or `forced`."
          enum:
            - optional
            - forced
        retrieveSavedCard:
          type: boolean
          description: Whether to retrieve the customer's saved cards on the payment page.
        interactionSource:
          type: string
          description: Must be `MOTO` or `ECOMMERCE` when using a token or saving a card for repeat payments.
          enum:
            - MOTO
            - ECOMMERCE
        enable3DS:
          type: boolean
          description: "`TRUE`: Enables 3DS for saved card payments. `FALSE`: Disables 3DS."
        notes:
          type: string
          description: Add any additional information about this payment. This could include special instructions, or context for the recipient.
    SessionStatus:
      type: string
      description: |
        Where a payment session currently is. A session starts `CREATED`, becomes `OPENED`
        when the customer lands on the payment page, `PENDING` while an attempt is in flight,
        and then settles into one of the final states. `ABANDONED` is what Abandon a payment
        session sets; `EXPIRED` is what the session reaches on its own at `expireAt`.
      enum:
        - CREATED
        - OPENED
        - PENDING
        - ABANDONED
        - PAID
        - FAILED
        - EXPIRED
        - AUTHORIZED
        - REFUNDED
        - PARTIALLY_REFUNDED
        - REFUND_PENDING
        - VOIDED
        - REVERSED
        - REJECTED
    PaymentSession:
      type: object
      description: A created payment session.
      properties:
        status:
          $ref: "#/components/schemas/SessionStatus"
        failureAttempts:
          type: integer
        capturedAmount:
          type: number
        refundedAmount:
          type: number
        _id:
          type: string
        merchantId:
          type: string
        expireAt:
          type: string
        maxFailureAttempts:
          type: integer
        paymentParams:
          type: object
          description: The payment parameters the session was created with (echoed back, plus hash/store info).
          additionalProperties: true
        apiKey:
          type: string
        history:
          type: array
          items:
            $ref: "#/components/schemas/HistoryEntry"
        webhookNotifications:
          type: array
          items: {}
        createdAt:
          type: string
        updatedAt:
          type: string
        __v:
          type: integer
        sessionUrl:
          type: string
          description: The URL that will be used to redirect the customer to the payment page. You can use it as the `src` attribute in a link or iframe.
    PaymentSessionDetails:
      type: object
      description: Payment session details returned by "Get payment session".
      properties:
        sessionId:
          type: string
          description: A unique identifier for the payment session.
        status:
          type: string
          description: The current status of the payment session (e.g., 'PENDING').
        createdAt:
          type: string
          description: (ISO 8601 timestamp) The date and time when the session was created.
        updatedAt:
          type: string
          description: (ISO 8601 timestamp) The date and time when the session was updated.
        merchantId:
          type: string
          description: The unique identifier of the merchant initiating the session.
        merchantOrderId:
          type: string
          description: The merchant's custom order reference.
        amount:
          type: string
          description: The payment amount in the specified currency.
        currency:
          type: string
          description: The currency of the payment (e.g., "EGP").
        method:
          type: string
          description: The payment method used (e.g., 'card').
        orderId:
          type: string
          description: The unique order identifier (may be "NA" if not applicable).
        paymentChannel:
          type: string
          description: The payment channel used (e.g., "ONLINE").
        rfsDate:
          type: string
          description: Reserved for future settlement date (may be "NA" if not applicable).
        lastTransactionType:
          type: string
          description: The type of the last transaction (may be "NA" if not applicable).
        issuerAuthorizationCode:
          type: string
          description: The authorization code from the card issuer (may be "NA" if not applicable).
        metaData:
          $ref: "#/components/schemas/MetaData"
        customer:
          $ref: "#/components/schemas/Customer"
        history:
          type: array
          description: A list of status changes and actions taken on the session.
          items:
            $ref: "#/components/schemas/HistoryEntry"
    TransactionRecord:
      type: object
      description: A transaction record from the aggregator transactions list. (Some numeric fields — `totalCapturedAmount`, `totalRefundedAmount`, `amount`, `__v`, and `pcc.bank_rfs_due_after` — appear in the docs example without values and are left untyped here.)
      properties:
        _id:
          type: string
        isPOSPortalRefund:
          type: boolean
        createdAt:
          type: string
        merchantId:
          type: string
        storeName:
          type: string
        orderReference:
          type: string
        merchantOrderId:
          type: string
        totalCapturedAmount: {}
        totalRefundedAmount: {}
        totalAuthorizedAmount:
          type: string
        method:
          type: string
        sourceOfFunds:
          type: object
          properties:
            cardInfo:
              type: object
              properties:
                maskedCard:
                  type: string
                cardBrand:
                  type: string
                cardHolderName:
                  type: string
                cardDataToken:
                  type: string
                agreement: {}
        paymentAgreement:
          type: string
        provider:
          type: string
        status:
          type: string
        transactionId:
          type: string
        targetedTransaction:
          type: string
        targetedTransactionOperation:
          type: string
        id:
          type: string
        channel:
          type: string
        type:
          type: string
        currency:
          type: string
        lastStatus:
          type: string
        amount: {}
        isVoided:
          type: boolean
        isCancelled:
          type: boolean
        dateToFilter:
          type: string
        date:
          type: string
        responseDate:
          type: string
        settlementDate:
          type: string
        bankValueDate:
          type: string
        bankSettlementDate:
          type: string
        formattedDate:
          type: string
        dateTime:
          type: string
        lastModifiedDate:
          type: string
        issuer:
          type: string
        issuerAuthorizationCode:
          type: string
        transactionResponseCode:
          type: string
        transactionResponseMessage:
          $ref: "#/components/schemas/LocalizedMessage"
        pcc:
          type: object
          properties:
            operations:
              type: array
              items: {}
            financial_institution:
              type: string
            bank_rfs_due_after: {}
        transactions:
          type: array
          items: {}
        __v: {}
    RefundRequest:
      type: object
      description: Refund an order (partially or fully). Refunds use your available Kashier balance.
      required:
        - apiOperation
        - transaction
      properties:
        apiOperation:
          type: string
          description: Should be REFUND to be able to make a refund request
          enum:
            - REFUND
        reason:
          type: string
          description: Reason for the refund.
        transaction:
          type: object
          properties:
            amount:
              type: number
              description: The amount to be refunded. It is not permitted for the refund amount to exceed the amount of the original transaction.
    VoidRequest:
      type: object
      description: Void (cancel) a transaction of the order, fully or partially.
      required:
        - apiOperation
        - transaction
      properties:
        apiOperation:
          type: string
          description: Should be VOID to be able to make a void request
          enum:
            - VOID
        transaction:
          type: object
          properties:
            amount:
              type: number
              description: The amount to be captured
            targetTransactionId:
              type: string
              description: The transaction ID that is returned from the response transactionId
    CaptureRequest:
      type: object
      description: Capture a previously authorized amount, fully or partially. You should capture the amount before 7 days or 30 days depending on your configuration.
      required:
        - apiOperation
        - transaction
      properties:
        apiOperation:
          type: string
          description: Should be CAPTURE to make a capture request
          enum:
            - CAPTURE
        transaction:
          type: object
          properties:
            amount:
              type: number
              description: The amount to be captured
    ReversalRequest:
      type: object
      description: |
        Reverse a transaction on the order. Reversal is the rail-level undo used mainly by
        card-present and BNPL flows; for an ordinary online card sale you want VOID (before
        settlement) or REFUND (after).

        Kashier has not published the field list beyond `apiOperation`, so any additional
        fields are passed through as sent.
      additionalProperties: true
      required:
        - apiOperation
      properties:
        apiOperation:
          type: string
          description: Should be REVERSAL to make a reversal request.
          enum:
            - REVERSAL
    OrderOperationResult:
      type: object
      description: The result of a refund, void, capture or reversal. The top-level `status` is `SUCCESS` when Kashier processed the request; the resulting order state is inside `response.status` (for example `PARTIALLY_REFUNDED` after a partial refund, `CANCELLED` after a void, `CAPTURED` after a capture).
      properties:
        response:
          type: object
          additionalProperties: true
        transactionId:
          type: string
        messages:
          $ref: "#/components/schemas/LocalizedMessage"
        status:
          type: string
        provider:
          type: object
          properties:
            type:
              type: string
            version:
              type: string
    PayWithTokenRequest:
      type: object
      required:
        - apiOperation
        - paymentMethod
        - order
        - customer
        - interactionSource
        - merchantId
        - timestamp
      properties:
        apiOperation:
          type: string
          description: "Should be: PAY (confirmation purchase)"
          enum:
            - PAY
        paymentMethod:
          type: object
          properties:
            type:
              type: string
              enum:
                - CARD
            card:
              type: object
              properties:
                cardToken:
                  type: string
                  description: customer's card token
                securityCode:
                  type: string
                  description: card CVV; it will be required if interactionSource is ECOMMERCE
                enable3DS:
                  type: boolean
                  description: to pay direct, but when interactionSource is E-COMMERCE, 3DS should be enabled
        installments:
          type: object
          description: if provided
          properties:
            plandId:
              type: string
              description: Installment plan id. (Spelled `plandId` in the docs' request examples — copied verbatim.)
        origin:
          type: object
          description: optional
          properties:
            id:
              type: string
        connectedAccount:
          type: object
          description: Take payments on behalf of your Connected Account by passing the Sub Merchant/Connected Account Merchant Id. Optional.
          properties:
            merchantId:
              type: string
        order:
          type: object
          description: 'where contain order details {"reference": "1","amount": "1", "currency": "EGP", "description": "" }'
          properties:
            reference:
              type: string
              description: Order Identifier (merchantOrderId)
            amount:
              type: string
              description: Order amount
            currency:
              type: string
              description: 'Order currency (ISO: "EGP", "USD", "GBP", "EUR")'
              enum:
                - EGP
                - USD
                - GBP
                - EUR
            description:
              type: string
              description: Order description (optional)
        customer:
          type: object
          description: "When saving a card the customer object must be required; it contains customer details {\"reference\": \"24\"}. It's mandatory in case of pay with token; only reference is mandatory."
          required:
            - reference
          properties:
            reference:
              type: string
              description: customer reference ID (shopper reference)
        interactionSource:
          type: string
          description: It's mandatory to be MOTO, Recurring or ECOMMERCE payment based on the business case (Recurring or MOTO if you want to tokenize a card for later payment).
        reconciliation:
          type: object
          description: optional
          properties:
            webhookUrl:
              type: string
              description: Pass an endpoint to receive server-to-server notifications; the event object is sent as JSON in the request body.
            merchantRedirect:
              type: string
              description: merchantRedirect should be "URI encoded" (customer receipt)
            redirect:
              type: boolean
              description: to redirect to the MerchantRedirect url after the transaction has been completed, whether it is unsuccessful or successful
        metaData:
          type: object
          description: It is additional data you can send and receive via webhooks and responses {'email':'email@example.com'}. Optional.
          additionalProperties: true
        merchantId:
          type: string
          description: Merchant account number or merchant ID
        timestamp:
          type: string
          description: mandatory
    SavedCardToken:
      type: object
      description: One card token saved on the merchant account, as returned by the dashboard-side token list.
      properties:
        token:
          type: string
          description: The card token. This is the value you charge with, and the only handle you ever get on the card.
        cardNumber:
          type: string
          description: The masked card number. Kashier never returns a full PAN.
          example: 5123********2346
        cardHolderName:
          type: string
        customerReference:
          type: string
          description: Your own reference for the customer the card belongs to, as supplied when the token was created.
        agreementId:
          type: string
          description: The stored-credential agreement the token was saved under. Pay-with-token calls quote this alongside the token.
        agreementType:
          type: string
          description: Whether the agreement bills on a schedule or is a card kept on file for ad-hoc charges.
          enum:
            - RECURRING
            - UNSCHEDULED
        agreementExpiry:
          type: string
          description: When the agreement expires, or the literal string `N/A` when it does not.
    SavedPaymentMethod:
      type: object
      description: A saved (tokenized) card belonging to a customer.
      properties:
        type:
          type: string
          enum:
            - CARD
        card:
          type: object
          properties:
            expiry:
              type: object
              properties:
                month:
                  type: string
                year:
                  type: string
            number:
              type: string
              description: Masked card number.
            nameOnCard:
              type: string
            cardToken:
              type: string
        customer:
          type: object
          properties:
            reference:
              type: string
            customerIp:
              type: string
    InstallmentBank:
      type: object
      description: An installment-enabled bank with its plans, terms, and supported BIN ranges.
      properties:
        logoUrl:
          type: string
        bankNameEn:
          type: string
        bankNameAr:
          type: string
        bankAbbreviation:
          type: string
        banknSystemID:
          type: string
        planFinancing:
          type: integer
        plans:
          type: array
          items:
            type: object
            properties:
              planFinancing:
                type: boolean
              bankId:
                type: string
        termsAndConditions:
          type: object
          properties:
            termsAndConditionsEn:
              type: string
            termsAndConditionsAr:
              type: string
        minimunInstallmentAmount:
          type: number
        binRanges:
          type: array
          items:
            type: object
            properties:
              _id:
                type: string
              prefix:
                type: string
              product:
                type: string
              range:
                type: object
                properties:
                  from:
                    type: string
                  to:
                    type: string
    TransferListItem:
      type: object
      description: A payout transfer (batch) summary row.
      properties:
        merchantId:
          type: string
        storeName:
          type: string
        amount:
          type: number
        id:
          type: string
        method:
          type: string
        createdAt:
          type: string
        initiatedCount:
          type: integer
        inTransitCount:
          type: integer
        transferredCount:
          type: integer
        failedCount:
          type: integer
        transfersCount:
          type: integer
        status:
          type: string
        name:
          type: string
    CustomerCustomField:
      type: object
      description: A merchant-defined key/value pair stored on the customer, for data Kashier does not model itself (membership numbers, internal ids, a second phone number).
      properties:
        name:
          type: string
          description: The field name, e.g. `custom-key-1`.
        value:
          type: string
          description: The field value, e.g. `custom-value-1`.
    CustomerCreateRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          description: The customer's name.
        phoneNumber:
          type: string
          description: The customer's phone number.
        emailAddress:
          type: string
          description: The customer's email address.
        countryCode:
          type: string
          description: Dialling code for the phone number, e.g. `+20`.
        customFields:
          type: array
          description: Merchant-defined key/value pairs to store on the customer.
          items:
            $ref: "#/components/schemas/CustomerCustomField"
        preferredCommunicationChannel:
          type: string
          description: Which channel to reach the customer on when both an email address and a phone number are set.
          enum:
            - sms
            - email
        labels:
          type: array
          description: Labels to tag the customer with.
          items:
            type: string
    CustomerUpdateRequest:
      allOf:
        - $ref: "#/components/schemas/CustomerCreateRequest"
    CustomerProfile:
      type: object
      description: A stored customer profile.
      properties:
        _id:
          type: string
          description: Internal record id.
        id:
          type: string
          description: Same value as `_id`, returned in list responses.
        customerId:
          type: string
          description: The Kashier customer identifier, e.g. `C-XXXXXXXXXXXXX`. Use it to link the customer to payments and payment links.
        merchantId:
          type: string
          description: The merchant id, e.g. `MID-XXXXX-XXX`.
        name:
          type: string
        phoneNumber:
          type: string
        emailAddress:
          type: string
        countryCode:
          type: string
        preferredCommunicationChannel:
          type: string
          enum:
            - sms
            - email
        customFields:
          type: array
          items:
            $ref: "#/components/schemas/CustomerCustomField"
        labels:
          type: array
          items:
            type: string
        createdByUserId:
          type: string
          description: Id of the dashboard user who created the customer.
        createdAt:
          type: string
        updatedAt:
          type: string
    CustomerTimelineEntry:
      type: object
      description: One entry in a customer's audit trail.
      properties:
        _id:
          type: string
        customerId:
          type: string
          description: The record id of the customer this entry belongs to.
        operation:
          type: string
          description: What happened, e.g. `created`, `updated`.
        actionBy:
          type: object
          description: The dashboard user who performed the action.
          properties:
            email:
              type: string
            fullName:
              type: string
            userId:
              type: string
        updatedFields:
          type: array
          description: The fields changed by this action.
          items:
            type: object
            additionalProperties: true
        updatedAt:
          type: string
    CustomerDetails:
      allOf:
        - $ref: "#/components/schemas/CustomerProfile"
        - type: object
          description: A customer with the audit timeline that is only returned when the profile is fetched on its own.
          properties:
            timeLine:
              type: array
              items:
                $ref: "#/components/schemas/CustomerTimelineEntry"
    CustomerListPage:
      type: object
      description: A page of customers with its pagination counters.
      properties:
        customers:
          type: array
          items:
            $ref: "#/components/schemas/CustomerProfile"
        totalCustomers:
          type: integer
        limit:
          type: integer
        page:
          type: integer
        totalPages:
          type: integer
        pagingCounter:
          type: integer
        hasPrevPage:
          type: boolean
        hasNextPage:
          type: boolean
        prevPage:
          description: The previous page number, or null on the first page.
        nextPage:
          description: The next page number, or null on the last page.
    CustomerExportBatchRequest:
      type: object
      properties:
        customerIds:
          type: array
          description: The customers to export. Omit to export everything matching the filters.
          items:
            type: string
        startDate:
          type: string
          description: "Only export customers created after this date. Example: 01-06-2024"
        endDate:
          type: string
          description: "Only export customers created before this date. Example: 30-06-2024"
        search:
          type: string
          description: Search for a customer by name, phone number, or email address.
    CustomerImportRow:
      type: object
      description: A customer parsed from an uploaded sheet, before it is saved.
      properties:
        name:
          type: string
        phoneNumber:
          type: string
        emailAddress:
          type: string
        customFields:
          type: array
          items:
            $ref: "#/components/schemas/CustomerCustomField"
        errors:
          description: Validation errors found in this row, or null when the row is valid. Any non-null `errors` must be fixed before the sheet can be saved.
    InvoicePagination:
      type: object
      description: Pagination info returned alongside paged invoice lists.
      properties:
        total:
          type: integer
        limit:
          type: integer
        page:
          type: integer
        pages:
          type: integer
    InvoiceItem:
      type: object
      description: A single line item on a professional invoice.
      properties:
        itemId:
          type: string
        itemName:
          type: string
        description:
          type: string
        quantity:
          type: number
        unitPrice:
          type: number
        subTotal:
          type: number
          description: Line total, normally `quantity` × `unitPrice`.
    InvoiceExtraFee:
      type: object
      description: An extra fee added on top of the invoice items — either a flat amount, a percentage rate, or both.
      properties:
        name:
          type: string
        rate:
          type: number
          description: Percentage rate applied to the invoice subtotal.
        flatFee:
          type: number
          description: Flat amount added to the invoice.
    InvoiceTransaction:
      type: object
      description: A payment transaction recorded against the invoice.
      properties:
        transactionInfoId:
          type: string
          description: The Kashier transaction reference (e.g., `TX-243585751279`).
        paymentReferenceId:
          type: string
        cardOrderId:
          type: string
        orderReference:
          type: string
        amount:
          type: number
        currency:
          type: string
    InvoiceShareStatus:
      type: object
      description: Delivery outcome of the most recent [Share invoice](#operation/shareInvoice) call, per channel. Kashier updates these fields when the email or SMS provider reports back.
      properties:
        email:
          type: object
          properties:
            status:
              type: string
              enum:
                - pending
                - delivered
                - failed
            isOpened:
              type: boolean
            isClicked:
              type: boolean
        sms:
          type: object
          properties:
            status:
              type: string
              enum:
                - pending
                - delivered
                - failed
            isOpened:
              type: boolean
            isClicked:
              type: boolean
    InvoiceCreateRequest:
      type: object
      description: The invoice to create. `paymentType` decides the shape — `simple` is a bare amount to collect, `professional` adds line items and a due date, and `order` is an order link.
      required:
        - paymentType
        - totalAmount
        - currency
        - customerName
        - description
        - isManualCapture
      properties:
        paymentType:
          type: string
          description: The kind of invoice to mint. `simple` produces a `PR-…` identifier, `professional` an `INV-…`, and `order` an `ORD-…`.
          enum:
            - simple
            - professional
            - order
        totalAmount:
          type: number
          description: The amount to collect, in the invoice currency. Must be at least 1.
        currency:
          type: string
          description: ISO 4217 currency code (e.g., EGP).
          enum:
            - EGP
            - USD
            - GBP
            - EUR
        description:
          type: string
          description: Free-text description shown to the customer on the payment page.
        customerName:
          type: string
        email:
          type: string
          description: Customer email — the default recipient when you share the invoice by email.
        phoneNumber:
          type: string
          description: Customer mobile number — the default recipient when you share the invoice by SMS.
        referenceId:
          type: string
          description: Your own reference for the invoice. Kashier stores it alongside the invoice so you can reconcile against your books.
        dueDate:
          type: string
          description: Date the invoice falls due (e.g., 2030-01-01).
        tax:
          type: number
          description: Tax percentage applied to the invoice.
        isManualCapture:
          type: boolean
          description: When true, a card payment against this invoice is only authorized and you capture it later. Defaults to false.
        state:
          type: string
          description: Whether to save the invoice as a `draft` or publish it as `submitted`. Only a submitted invoice is payable.
          enum:
            - draft
            - submitted
        invoiceItems:
          type: array
          description: Line items, for a `professional` invoice.
          items:
            $ref: "#/components/schemas/InvoiceItem"
        extraFees:
          type: array
          description: Extra fees added on top of the line items.
          items:
            $ref: "#/components/schemas/InvoiceExtraFee"
    InvoiceUpdateRequest:
      type: object
      description: "The fields to change on an existing invoice. Send `operation: cancel` to cancel it instead of editing it."
      properties:
        operation:
          type: string
          description: "`edit` to change the invoice, `cancel` to cancel it."
          enum:
            - edit
            - cancel
        totalAmount:
          type: number
        currency:
          type: string
          enum:
            - EGP
            - USD
            - GBP
            - EUR
        description:
          type: string
        customerName:
          type: string
        email:
          type: string
        phoneNumber:
          type: string
        referenceId:
          type: string
        dueDate:
          type: string
        tax:
          type: number
        state:
          type: string
          enum:
            - draft
            - submitted
            - cancelled
        invoiceItems:
          type: array
          items:
            $ref: "#/components/schemas/InvoiceItem"
        extraFees:
          type: array
          items:
            $ref: "#/components/schemas/InvoiceExtraFee"
    InvoiceShareRequest:
      type: object
      description: Which invoice to share, with whom, and over which channel.
      required:
        - operation
        - key
        - urlIdentifier
      properties:
        operation:
          type: string
          description: The delivery channel.
          enum:
            - email
            - sms
        key:
          type: string
          description: The recipient — an email address when `operation` is `email`, a mobile number when it is `sms`.
        urlIdentifier:
          type: string
          description: The identifier of the invoice to share — its `paymentRequestId` (`PR-…`, `INV-…`, `ORD-…`) or its `paymentLinkId` (`PL-…`).
    Invoice:
      type: object
      description: An invoice (payment request) and its current payment state.
      properties:
        paymentRequestId:
          type: string
          description: The invoice identifier minted by Kashier (e.g., `PR-XXXXXXXXXX`).
        paymentLinkId:
          type: string
          description: The payment-link identifier (`PL-…`), present when the invoice is a payment link.
        merchantId:
          type: string
        storeName:
          type: string
        paymentType:
          type: string
          enum:
            - simple
            - professional
            - order
        totalAmount:
          type: number
        totalAmountWithoutFees:
          type: number
        availableAmountForRefund:
          type: number
          description: How much of the collected amount can still be refunded.
        currency:
          type: string
        description:
          type: string
        customerName:
          type: string
        email:
          type: string
        phoneNumber:
          type: string
        referenceId:
          type: string
        invoiceReferenceId:
          type: string
        state:
          type: string
          description: Where the invoice sits in its lifecycle.
          enum:
            - draft
            - submitted
            - cancelled
            - awaiting_approval
            - rejected
        paymentStatus:
          type: string
          description: Whether the invoice has been paid.
          enum:
            - unpaid
            - on hold
            - paid
            - voided
        isManualCapture:
          type: boolean
        isPaymentLink:
          type: boolean
        isBulkCreated:
          type: boolean
        isDeleted:
          type: boolean
        tax:
          type: number
        creationDate:
          type: string
        dueDate:
          type:
            - string
            - "null"
        labels:
          type: array
          items:
            type: string
        invoiceItems:
          type: array
          items:
            $ref: "#/components/schemas/InvoiceItem"
        extraFees:
          type: array
          items:
            $ref: "#/components/schemas/InvoiceExtraFee"
        transactions:
          type: array
          items:
            $ref: "#/components/schemas/InvoiceTransaction"
        lastShareStatus:
          $ref: "#/components/schemas/InvoiceShareStatus"
    PaymentLinkExtraFee:
      type: object
      description: An additional charge applied on top of the link amount. A fee can be flat, a percentage of the amount, or both.
      properties:
        name:
          type: string
          description: Name of the fee, e.g. `VAT` or `annualFee`.
        flatFee:
          type: number
          description: Fixed charge added to the total, e.g. `500`.
        rate:
          type: number
          description: Percentage of the total added as a fee, e.g. `5` for 5% VAT.
    PaymentLinkInvoiceItem:
      type: object
      description: A product or service line on an itemized payment link.
      properties:
        description:
          type: string
          description: Description of the item.
        unitPrice:
          type: number
          description: Price of a single unit.
        quantity:
          type: number
          description: Number of units.
        subTotal:
          type: number
          description: Line total — `unitPrice` × `quantity`.
    PaymentLinkCustomer:
      type: object
      description: The customer the link is for. `name` is what appears on the payment page; `emailAddress` / `phoneNumber` are what `createAndSharePaymentLink` sends the link to.
      properties:
        name:
          type: string
          description: Full name of the customer, e.g. `John Doe`.
        id:
          type: string
          description: Identifier of an existing Kashier customer to link this payment to (see the Customers endpoints).
        emailAddress:
          type: string
        phoneNumber:
          type: string
    PaymentLinkCreateRequest:
      type: object
      required:
        - totalAmount
        - currency
        - customer
        - description
        - isManualCapture
        - paymentType
        - state
      properties:
        customer:
          $ref: "#/components/schemas/PaymentLinkCustomer"
        totalAmount:
          type: number
          description: Total amount of the link, expressed in `currency` — e.g. `100.00` for an EGP link, or `40` for a `USD_VIRTUAL` link.
        currency:
          type: string
          description: Currency the customer pays in, e.g. `EGP`, or a virtual currency code (`USD_VIRTUAL`, `EUR_VIRTUAL`, `GBP_VIRTUAL`, `SAR_VIRTUAL`, `AED_VIRTUAL`) to collect in a foreign currency and settle in EGP.
        description:
          type: string
          description: Free-text note about the payment.
        paymentType:
          type: string
          description: Type of payment, e.g. `simple` for a standard one-time payment.
        state:
          type: string
          description: State to create the link in, e.g. `submitted` or `draft`.
        isManualCapture:
          type: boolean
          description: Whether the payment must be captured manually (`true`) or is captured automatically (`false`).
        isSuspendedPayment:
          type: boolean
          description: Whether the link is temporarily suspended (`true`) or active (`false`).
        dueDate:
          type: string
          description: Deadline for completing the payment, in ISO 8601 format, e.g. `2030-01-01T00:00:00.000Z`.
        referenceId:
          type: string
          description: Your own unique identifier for tracking this link.
        extraFees:
          type: array
          description: Additional charges applied to the total, such as taxes or service fees.
          items:
            $ref: "#/components/schemas/PaymentLinkExtraFee"
        items:
          type: array
          description: The products or services included, for an itemized link.
          items:
            $ref: "#/components/schemas/PaymentLinkInvoiceItem"
        labels:
          type: array
          description: Labels to tag the link with.
          items:
            type: string
    PaymentLinkUpdateRequest:
      type: object
      required:
        - paymentLink
      description: The editable payment link fields, wrapped in a `paymentLink` object.
      properties:
        paymentLink:
          $ref: "#/components/schemas/PaymentLinkCreateRequest"
    PaymentLinkShareRequest:
      type: object
      required:
        - operation
        - urlIdentifier
        - key
      properties:
        operation:
          type: string
          description: The channel to send the link on.
          enum:
            - email
            - sms
        urlIdentifier:
          type: string
          description: The payment link identifier, e.g. `PL-2348668602`.
        key:
          type: string
          description: The recipient — an email address when `operation` is `email`, a phone number when it is `sms`.
    PaymentLinkReshareRequest:
      type: object
      required:
        - paymentLinkIds
      properties:
        paymentLinkIds:
          type: array
          description: The payment links to re-send.
          items:
            type: string
    PaymentLinkPagination:
      type: object
      properties:
        page:
          type: integer
        limit:
          type: integer
        total:
          type: integer
          description: Total number of payment links matching the filters.
        totalPages:
          type: integer
    PaymentLinkSummary:
      type: object
      description: A payment link as returned in list and write responses.
      properties:
        _id:
          type: string
          description: Internal record id.
        paymentLinkId:
          type: string
          description: The payment link identifier, e.g. `PL-2348668602`.
        paymentRequestId:
          type: string
          description: The underlying payment request id, e.g. `PR-2348668602`.
        merchantId:
          type: string
          description: The merchant id, e.g. `MID-XXXXX-XXX`.
        merchantInfo:
          type: object
          properties:
            storeName:
              type: string
        storeName:
          type: string
        description:
          type: string
        customerName:
          type: string
        customer:
          description: The linked customer, or null when the link is not tied to a customer record.
        currency:
          type: string
        totalAmount:
          type: number
        totalAmountWithoutFees:
          type: number
          description: The amount before `extraFees` are applied.
        availableAmountForRefund:
          type: number
        paymentType:
          type: string
        paymentStatus:
          type: string
          description: Payment state, e.g. `paid`, `unpaid`.
        state:
          type: string
        dueDate:
          description: ISO 8601 due date, or null when the link has no deadline.
        creationDate:
          type: string
        referenceId:
          type: string
        invoiceReferenceId:
          type: string
        isSuspendedPayment:
          type: boolean
        isManualCapture:
          type: boolean
        isDeleted:
          type: boolean
        isPaymentLink:
          type: boolean
        isBulkCreated:
          type: boolean
        extraFees:
          type: array
          items:
            $ref: "#/components/schemas/PaymentLinkExtraFee"
        invoiceItems:
          type: array
          items:
            $ref: "#/components/schemas/PaymentLinkInvoiceItem"
        labels:
          type: array
          items:
            type: string
        transactions:
          type: array
          description: Transactions recorded against the link.
          items:
            type: object
            additionalProperties: true
        virtualAmount:
          description: Amount in the foreign currency, for currency conversion links. Null otherwise.
        virtualCurrency:
          description: The virtual currency code, e.g. `USD_VIRTUAL`. Null otherwise.
        virtualExchangeRate:
          description: Exchange rate applied to convert the virtual amount to EGP. Null otherwise.
        virtualRateRecordedAt:
          description: When that exchange rate was recorded. Null otherwise.
    PaymentLinkDetails:
      allOf:
        - $ref: "#/components/schemas/PaymentLinkSummary"
        - type: object
          description: A payment link with the fields that are only returned when it is fetched on its own.
          properties:
            createdByUserId:
              type: string
              description: Id of the dashboard user who created the link.
    PaymentLinkHistoryRecord:
      type: object
      description: One entry in a payment link's audit trail — what happened, who did it, and which fields changed.
      properties:
        event:
          type: string
          description: The event that occurred, e.g. `CREATED`, `MARKED_AS_PAID`.
        userInfo:
          type: object
          description: The dashboard user behind the event, when there is one.
          properties:
            name:
              type: string
        metadata:
          type: object
          description: Event details — always a `timestamp`, plus event-specific keys such as `transactionInfoId`, `amount`, `currency`, and `status` for payment events, or `source` and `channel` for creation events.
          additionalProperties: true
        stateChanges:
          type: object
          description: The fields added, updated, and removed by this event.
          properties:
            added:
              type: object
              additionalProperties: true
            updated:
              type: object
              additionalProperties: true
            removed:
              additionalProperties: true
        formattedData:
          type: object
          description: The same event rendered for display — a localized timestamp, a sentence describing what happened, a list of changes, and the text direction to render them in.
          additionalProperties: true
    PaymentPagePagination:
      type: object
      description: Pagination info returned alongside paged payment page lists.
      properties:
        total:
          type: integer
        limit:
          type: integer
        page:
          type: integer
        pages:
          type: integer
    PaymentPageAmount:
      type: object
      description: How much the page collects. When `isFixed` is true the customer pays `amount` exactly; when it is false the customer types in their own amount.
      properties:
        isFixed:
          type: boolean
          description: Whether the amount is fixed by you rather than entered by the customer.
        amount:
          type:
            - string
            - number
          description: The fixed amount, only used when `isFixed` is true. Send it as a decimal string (e.g., "100.00"); Kashier stores and returns it as a number.
    PaymentPageExtraField:
      type: object
      description: An additional input the page collects from the customer alongside the payment.
      properties:
        fieldName:
          type: string
        dataType:
          type: string
          description: The kind of value the field accepts (e.g., string, number).
        isRequired:
          type: boolean
        isDeleted:
          type: boolean
          description: Set when the field has been removed from the page but is kept for old payments.
    PaymentPageAdditionalFee:
      type: object
      description: An extra charge added on top of the page's amount — a flat amount, a percentage rate, or both.
      properties:
        feeName:
          type: string
        flatFee:
          type: number
          description: Flat amount added to the total.
        rateFee:
          type: number
          description: Percentage rate applied to the total.
        isDeleted:
          type: boolean
    PaymentPageProductVariant:
      type: object
      description: A variant of a product on a product page, such as a size or a colour.
      properties:
        name:
          type: string
        variantReference:
          type: string
        quantity:
          type: string
        unitPrice:
          type: string
        categories:
          type: array
          items:
            type: string
    PaymentPageProduct:
      type: object
      description: A product listed on a `product` payment page.
      properties:
        productId:
          type: string
        productName:
          type: string
        productDescription:
          type: string
        productQuantity:
          type: string
          description: Available stock for the product.
        productUnitPrice:
          type: string
          description: Unit price, as a decimal string (e.g., "100.00").
        currency:
          type: string
        isVariant:
          type: boolean
        categories:
          type: array
          items:
            type: string
        productVariants:
          type: array
          items:
            $ref: "#/components/schemas/PaymentPageProductVariant"
    PaymentPageCreateRequest:
      type: object
      description: The payment page to create. `type` decides the shape — `regular` collects a single amount, `product` lists a catalogue the customer buys from.
      required:
        - pageName
        - currency
        - type
        - isEmailRequired
        - isMobileRequired
        - paymentMethods
      properties:
        pageName:
          type: string
          description: The page's name, shown to the customer. Must be unique across your payment pages.
        description:
          type: string
        currency:
          type: string
          description: ISO 4217 currency code (e.g., EGP). Defaults to EGP.
          enum:
            - EGP
            - USD
            - GBP
            - EUR
        type:
          type: string
          description: "`regular` for a single-amount page, `product` for a catalogue page."
          enum:
            - regular
            - product
        isMobileRequired:
          type: boolean
          description: Whether the customer must supply a mobile number.
        isEmailRequired:
          type: boolean
          description: Whether the customer must supply an email address.
        paymentMethods:
          type: array
          description: The payment methods offered on the page. Forced to `["card"]` when `isShippable` is true.
          items:
            type: string
        paymentObject:
          $ref: "#/components/schemas/PaymentPageAmount"
        tax:
          type: number
          description: Tax percentage applied to the page total.
        isPublished:
          type: boolean
          description: Whether the page is live. An unpublished page's link does not render.
        isShippable:
          type: boolean
          description: Whether the page collects a delivery address and creates a shipping order for each payment.
        pickupAddressId:
          type: string
          description: Which of your saved pickup addresses fulfilment collects from. Only used when `isShippable` is true.
        pageImage:
          type: string
          description: URL of the banner image shown at the top of the page.
        extraFields:
          type: array
          items:
            $ref: "#/components/schemas/PaymentPageExtraField"
        additionalFees:
          type: array
          items:
            $ref: "#/components/schemas/PaymentPageAdditionalFee"
        products:
          type: array
          description: The catalogue, for a `product` page.
          items:
            $ref: "#/components/schemas/PaymentPageProduct"
    PaymentPageUpdateRequest:
      type: object
      description: The fields to change on an existing payment page. Omitted fields are left as they are.
      properties:
        pageName:
          type: string
        description:
          type: string
        currency:
          type: string
          enum:
            - EGP
            - USD
            - GBP
            - EUR
        isMobileRequired:
          type: boolean
        isEmailRequired:
          type: boolean
        paymentMethods:
          type: array
          items:
            type: string
        paymentObject:
          $ref: "#/components/schemas/PaymentPageAmount"
        tax:
          type: number
        isPublished:
          type: boolean
        isShippable:
          type: boolean
        pickupAddressId:
          type: string
        pageImage:
          type: string
        extraFields:
          type: array
          items:
            $ref: "#/components/schemas/PaymentPageExtraField"
        additionalFees:
          type: array
          items:
            $ref: "#/components/schemas/PaymentPageAdditionalFee"
        products:
          type: array
          items:
            $ref: "#/components/schemas/PaymentPageProduct"
    PaymentPageShareRequest:
      type: object
      description: Which payment page to share, with whom, and over which channel.
      required:
        - operation
        - key
        - id
      properties:
        operation:
          type: string
          description: The delivery channel.
          enum:
            - email
            - sms
        key:
          type: array
          description: The recipients — email addresses when `operation` is `email`, mobile numbers when it is `sms`.
          items:
            type: string
        id:
          type: string
          description: The payment page link identifier to share (e.g., `PP-XXXXXXXXXX`).
    PaymentPage:
      type: object
      description: A payment page definition and its running payment totals.
      properties:
        _id:
          type: string
        linkId:
          type: string
          description: The page's public link identifier (e.g., `PP-XXXXXXXXXX`), minted by Kashier and used to build the page URL.
        merchantId:
          type: string
        pageName:
          type: string
        description:
          type: string
        type:
          type: string
          enum:
            - regular
            - product
        currency:
          type: string
        isMobileRequired:
          type: boolean
        isEmailRequired:
          type: boolean
        isPublished:
          type: boolean
        isShippable:
          type: boolean
        paymentMethods:
          type: array
          items:
            type: string
        paymentObject:
          $ref: "#/components/schemas/PaymentPageAmount"
        tax:
          type: number
        pageImage:
          type: string
        pickupAddressId:
          type: string
        totalPaidAmount:
          type: number
          description: Total amount successfully collected through the page.
        totalPaymentCount:
          type: integer
          description: Number of successful payments collected through the page.
        totalPendingCount:
          type: integer
          description: Number of payments against the page that are still pending.
        suspend:
          type: object
          description: Set when Kashier has suspended the page.
          properties:
            state:
              type: boolean
            reason:
              type: string
        creationDate:
          type: string
        deletedAt:
          type:
            - string
            - "null"
        extraFields:
          type: array
          items:
            $ref: "#/components/schemas/PaymentPageExtraField"
        additionalFees:
          type: array
          items:
            $ref: "#/components/schemas/PaymentPageAdditionalFee"
        products:
          type: array
          items:
            $ref: "#/components/schemas/PaymentPageProduct"
    PaymentPagePaymentTransaction:
      type: object
      description: An underlying card, wallet, or cash-on-delivery transaction behind a page payment.
      properties:
        transactionInfoId:
          type: string
          description: The Kashier transaction reference (e.g., `TX-243585751279`).
        merchantOrderId:
          type: string
        paymentReferenceId:
          type: string
        cardOrderId:
          type: string
        orderReference:
          type: string
        amount:
          type: number
        currency:
          type: string
        status:
          type: string
        type:
          type: string
          description: How the payment was taken.
          enum:
            - card
            - wallet
            - cod
        creationDate:
          type: string
    PaymentPagePayment:
      type: object
      description: One payment collected against a payment page, with the customer details it captured.
      properties:
        _id:
          type: string
        merchantId:
          type: string
        merchantOrderId:
          type: string
        paymentPageName:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
        phone:
          type: string
        amount:
          type: number
          description: Total charged, including tax and any additional fees.
        subAmount:
          type: number
          description: Amount before tax and additional fees.
        tax:
          type: number
        paymentMethod:
          type: string
        status:
          type: string
          enum:
            - success
            - failure
            - pending
        date:
          type: string
        shippingCorrId:
          type: string
          description: Links the payment to its shipping order, on a shippable page.
        extraFields:
          type: array
          description: The values the customer entered in the page's extra fields.
          items:
            type: object
            properties:
              fieldId:
                type: string
              fieldName:
                type: string
              value:
                type: string
        additionalFees:
          type: array
          items:
            $ref: "#/components/schemas/PaymentPageAdditionalFee"
        transactions:
          type: array
          items:
            $ref: "#/components/schemas/PaymentPagePaymentTransaction"
    PayoutMessages:
      type: object
      description: Message localized in English and Arabic.
      properties:
        en:
          type: string
        ar:
          type: string
    PayoutPagination:
      type: object
      properties:
        total:
          type: integer
        limit:
          type: integer
        page:
          type: integer
        pages:
          type: integer
    PayoutTransferMethod:
      type: string
      description: How the money reaches the recipient. `bank` and `card` payouts also require a `recipientBank`.
      enum:
        - bank
        - wallet
        - instant wallet
        - card
    PayoutTransferStatus:
      type: string
      description: Where a transfer is in its lifecycle. A transfer starts `PENDING`, is debited from your balance (`INITIATED`), is sent to the provider (`IN_TRANSIT`), and finishes as `TRANSFERRED` or `FAILED`. A `FAILED` transfer is credited back to your balance.
      enum:
        - PENDING
        - INITIATED
        - IN_TRANSIT
        - TRANSFERRED
        - FAILED
    PayoutScheduler:
      type: object
      description: A recurring payout scheduler — the transfer template Kashier repeats.
      properties:
        schedulerId:
          type: string
          description: The scheduler's id.
        merchantTransferId:
          type: string
          description: The unique identifier your systems assigned to the transfer.
        recipientName:
          type: string
        recipientNumber:
          type: string
        recipientBank:
          type: string
          description: The recipient's bank code. You can find the bank codes in the sheet Kashier sent.
        amount:
          type: number
        method:
          $ref: "#/components/schemas/PayoutTransferMethod"
        status:
          type: string
          description: Whether the scheduler is still running.
        recurringFrequency:
          type: string
          description: How often the scheduler repeats, e.g. `WEEKLY` or `MONTHLY`.
        startDate:
          type: string
          description: The date of the scheduler's first run.
        endDate:
          type: string
          description: The date after which the scheduler stops running, if one was set.
        nextRun:
          type: string
          description: The date of the scheduler's next run.
        createdAt:
          type: string
    PayoutCreateSchedulerRequest:
      type: object
      description: The transfer template to repeat, plus how often to repeat it.
      required:
        - scheduler
      properties:
        batchName:
          type: string
          description: A human-readable label for the payouts this scheduler produces, used for identification and organization purposes.
        type:
          type: string
          description: The kind of scheduler being created.
          enum:
            - single
        scheduler:
          type: object
          required:
            - method
            - recipientName
            - recipientNumber
            - amount
            - startDate
            - recurringFrequency
          properties:
            merchantTransferId:
              type: string
              description: A unique identifier assigned by you for the transfer. Required if you want per-transfer webhooks.
            method:
              $ref: "#/components/schemas/PayoutTransferMethod"
            recipientName:
              type: string
              description: The name of the person receiving the transfer. Between 3 and 70 characters.
            recipientNumber:
              type: string
              description: The recipient's account number, or their phone number for wallet payouts. Wallet recipients must be an Egyptian mobile number (`010`, `011`, `012` or `015` followed by 8 digits).
            recipientBank:
              type: string
              description: The bank where the funds are to be deposited. Required when `method` is `bank` or `card`. You can find the bank codes in the sheet Kashier sent.
            amount:
              type: number
              description: The amount of each recurring transfer. Minimum `0.01`; wallet payouts are capped at `60000`.
            startDate:
              type: string
              description: The date of the scheduler's first run.
            recurringFrequency:
              type: string
              description: How often to repeat the transfer, e.g. `WEEKLY` or `MONTHLY`.
            endDate:
              type: string
              description: The date after which the scheduler stops running.
    PayoutBatchSummary:
      type: object
      description: A payout batch summary row.
      properties:
        batchId:
          type: string
        merchantBatchId:
          type: string
          description: The unique identifier your systems assigned to the batch.
        batchName:
          type: string
        method:
          type: string
          description: The payout method of the batch, or `mixed` when its rows use more than one method.
        totalCount:
          type: integer
          description: How many transfers the batch contains.
        successCount:
          type: integer
        failureCount:
          type: integer
        status:
          type: string
        createdAt:
          type: string
    PayoutBatchDetails:
      type: object
      description: A payout batch together with the transfers it contains.
      allOf:
        - $ref: "#/components/schemas/PayoutBatchSummary"
        - type: object
          properties:
            updatedAt:
              type: string
            transfers:
              type: array
              items:
                $ref: "#/components/schemas/PayoutTransfer"
    PayoutTransfer:
      type: object
      description: A payout transfer.
      properties:
        transferId:
          type: string
        merchantTransferId:
          type: string
        recipientName:
          type: string
        recipientNumber:
          type: string
        recipientBank:
          type: string
        amount:
          type: number
        method:
          $ref: "#/components/schemas/PayoutTransferMethod"
        status:
          $ref: "#/components/schemas/PayoutTransferStatus"
        openForReturn:
          type: boolean
          description: Set on a `TRANSFERRED` transfer that the receiving bank or wallet may still bounce back. Treat `true` as not yet final when you reconcile.
        createdAt:
          type: string
        updatedAt:
          type: string
    TokenizationMessages:
      type: object
      description: Message localized in English and Arabic.
      properties:
        en:
          type: string
        ar:
          type: string
    TokenizationCardExpiry:
      type: object
      description: The card's expiry date.
      properties:
        month:
          type: string
          description: Two-digit expiry month, e.g. `12`.
        year:
          type: string
          description: Two-digit expiry year, e.g. `25`.
    TokenizationCreateTokenRequest:
      type: object
      description: The card to save, plus the customer it belongs to.
      required:
        - merchantId
        - customerReference
        - paymentMethod
      properties:
        merchantId:
          type: string
          description: your merchant Id
        customerReference:
          type: string
          description: your customer Id — the reference that links your customer to the saved token. It must be the same value you use in the `Kashier-Hash` string.
        paymentMethod:
          type: object
          required:
            - type
            - card
          properties:
            type:
              type: string
              description: The payment method type being tokenized.
              enum:
                - CARD
            card:
              type: object
              required:
                - number
                - expiry
              properties:
                number:
                  type: string
                  description: The full card number (PAN).
                expiry:
                  $ref: "#/components/schemas/TokenizationCardExpiry"
                nameOnCard:
                  type: string
                  description: The cardholder name as printed on the card.
                securityCode:
                  type: string
                  description: The card's CVV. It is exchanged for a single-use `cvvToken` and is never stored.
        customer:
          type: object
          description: The customer the card is being saved for.
          properties:
            reference:
              type: string
              description: your customer Id
    TokenizationSavedCard:
      type: object
      description: A saved card, with the card number masked.
      properties:
        number:
          type: string
          description: The masked card number, e.g. `512345********2346`.
        nameOnCard:
          type: string
        expiry:
          $ref: "#/components/schemas/TokenizationCardExpiry"
        cardToken:
          type: string
          description: The reusable token to charge with Pay with token.
        cardDataToken:
          type: string
          description: The token holding the stored card data.
        cvvToken:
          type: string
          description: A single-use token standing in for the CVV that was submitted.
        type:
          type: string
          description: The storage type of the token, e.g. `perm` for a permanently stored card.
        agreement:
          type: object
          description: The stored-credential agreement created alongside the token.
          properties:
            type:
              type: string
            id:
              type: string
    TokenizationCreateTokenResponse:
      type: object
      properties:
        status:
          type: string
        messages:
          $ref: "#/components/schemas/TokenizationMessages"
        response:
          type: object
          properties:
            paymentMethod:
              type: object
              properties:
                type:
                  type: string
                card:
                  $ref: "#/components/schemas/TokenizationSavedCard"
    TokenizationGetTokenResponse:
      type: object
      properties:
        status:
          type: string
        messages:
          $ref: "#/components/schemas/TokenizationMessages"
        response:
          type: object
          properties:
            paymentMethod:
              type: object
              properties:
                type:
                  type: string
                card:
                  $ref: "#/components/schemas/TokenizationSavedCard"
    TokenizationError:
      type: object
      description: A failed tokenization request.
      properties:
        status:
          type: string
        messages:
          $ref: "#/components/schemas/TokenizationMessages"
        error:
          type: object
          properties:
            cause:
              type: string
            explanation:
              type: string
    BalancePagination:
      type: object
      description: Pagination info returned alongside a page of results.
      properties:
        total:
          type: integer
          description: Total number of records matching the query.
        limit:
          type: integer
          description: Number of records per page.
        page:
          type: integer
          description: Current page number.
        pages:
          type: integer
          description: Total number of pages.
    BalancePayoutMethod:
      type: object
      description: The destination settled money is paid out to. The contents of `payoutFields` depend on `method`.
      properties:
        method:
          type: string
          description: The kind of payout destination, for example `bankAccount` or `wallet`.
        payoutFields:
          type: object
          additionalProperties: true
          description: The destination details for the selected method.
          properties:
            bankName:
              type: string
            bankBranch:
              type: string
            accountHolderName:
              type: string
            accountNumber:
              type: string
            branchCode:
              type: string
    BalanceAccount:
      type: object
      description: A Kashier balance account and its current position.
      additionalProperties: true
      properties:
        _id:
          type: string
        accountId:
          type: string
          description: The account identifier used by the other balance reads.
        accountName:
          type: string
        merchantId:
          type: string
        merchantName:
          type: string
        totalBalance:
          type: number
          description: Everything on the account, including amounts not yet available to pay out.
        availableBalance:
          type: number
          description: The part of the balance that can be paid out now.
        allowedNegativeBalance:
          type: number
          description: How far the balance is allowed to go below zero.
        isIncludeInBulkTransfer:
          type: boolean
          description: Whether this account is picked up by bulk transfers.
        lastTransfer:
          type: number
          description: Amount of the most recent transfer out of this account.
        totalBalanceBeforeLastTransfer:
          type: number
        lastTransferDate:
          type: string
        payoutMethod:
          $ref: "#/components/schemas/BalancePayoutMethod"
        createdAt:
          type: string
        updatedAt:
          type: string
    BalanceOverviewSummary:
      type: object
      description: Aggregated totals for an account over the requested date range.
      additionalProperties: true
      properties:
        message:
          type: string
        data:
          type: object
          additionalProperties: true
    BalanceRecord:
      type: object
      description: A single movement on a balance account — one statement line. `operation` says whether the balance was credited or debited, and `origin`/`originReference` point back at what produced it, such as the settlement batch it came from.
      additionalProperties: true
      properties:
        id:
          type: string
        accountId:
          type: string
        amount:
          type: number
          description: Amount of the movement.
        fees:
          type: number
          description: Fees taken on this movement, where applicable.
        operation:
          type: string
          description: Whether the record credited or debited the account, for example `credit`, `debit`, or `settlement`.
        status:
          type: string
        comment:
          type: string
        reason:
          type: string
        valueDate:
          type: string
          description: The date the money counts from.
        origin:
          type: string
          description: What produced the record, for example `settlement window`.
        originReference:
          type: string
          description: Reference of the originating object, such as a settlement batch id.
        createdAt:
          type: string
    BalanceHold:
      type: object
      description: An amount reserved on a balance account so it cannot be paid out.
      additionalProperties: true
      properties:
        id:
          type: string
        accountId:
          type: string
        amount:
          type: number
        currency:
          type: string
        status:
          type: string
        createdAt:
          type: string
    SettlementWindow:
      type: object
      description: A group of transactions that became ready for settlement together. A window closes into one or more batches, and each batch is what reaches your bank.
      additionalProperties: true
      properties:
        windowId:
          type: string
        accountId:
          type: string
          description: The balance account the window settles into.
        merchantId:
          type: string
        windowDate:
          type: string
        startDate:
          type: string
        endDate:
          type: string
        status:
          type: string
          description: Where the window is in its lifecycle.
          enum:
            - open
            - in_progress
            - closed
            - failed
        totalOriginalAmount:
          type: number
          description: Gross amount of the transactions in the window, before fees.
        totalSettlementAmount:
          type: number
          description: Net amount to be settled for the window, after fees and VAT.
        transactionsCount:
          type: integer
        batchesCount:
          type: integer
          description: Number of batches the window produced.
        batchesIds:
          type: string
          description: The batch ids of the window, joined with commas.
    SettlementBatch:
      type: object
      description: One batch of a settlement window — a set of transactions of the same channel and method, settled together, with the fees taken on them.
      additionalProperties: true
      properties:
        batchId:
          type: string
        rfsDate:
          type: string
          description: Ready-for-settlement date of the batch.
        channel:
          type: string
        method:
          type: string
        transactionsCount:
          type: integer
        totalOriginalAmount:
          type: number
          description: Gross amount of the transactions in the batch.
        totalFees:
          type: number
          description: Total selling fees taken on the batch.
        totalVat:
          type: number
          description: VAT charged on those fees.
        totalSettlementAmount:
          type: number
          description: Net amount settled for the batch, after fees and VAT.
    BatchError:
      type: object
      description: An error returned by the batch endpoints.
      properties:
        message:
          type: string
        status:
          type: string
    Batch:
      type: object
      description: A bulk billing batch.
      properties:
        _id:
          type: string
          description: Internal record id.
        batchName:
          type: string
        currency:
          type: string
          description: Currency the batch's invoices are billed in, for example `EGP`.
        merchantId:
          type: string
        createdByUserId:
          type: string
          description: The dashboard user who created the batch.
        status:
          type: string
          description: Where the batch is up to — for example still pending, or being processed.
        itemsCount:
          type: integer
          description: How many items the batch currently holds.
        createdAt:
          type: string
        updatedAt:
          type: string
    BatchWithItems:
      allOf:
        - $ref: "#/components/schemas/Batch"
        - type: object
          properties:
            items:
              type: array
              description: The items imported into the batch.
              items:
                $ref: "#/components/schemas/BatchItem"
    BatchCreateRequest:
      type: object
      required:
        - batchName
        - currency
      properties:
        batchName:
          type: string
          description: A name for the batch, used to find it again in the list.
        currency:
          type: string
          description: Currency the batch's invoices are billed in, for example `EGP`.
          enum:
            - EGP
            - USD
            - GBP
            - EUR
        batchType:
          type: string
          description: Which import sheet the batch expects — rows that carry customer details, or rows that are amounts only.
          enum:
            - withCustomer
            - withoutCustomer
    BatchUpdateRequest:
      type: object
      properties:
        batchName:
          type: string
          description: The new name for the batch.
    BatchItem:
      type: object
      description: A single row inside a batch — one invoice waiting to be created and sent.
      properties:
        _id:
          type: string
          description: Internal record id.
        batchId:
          type: string
          description: The batch this item belongs to.
        name:
          type: string
        amount:
          type: number
          description: The amount to bill for this row.
        currency:
          type: string
        dueDate:
          type: string
          description: When the resulting invoice falls due.
        status:
          type: string
        createdAt:
          type: string
        updatedAt:
          type: string
    BatchItemUpdateRequest:
      type: object
      required:
        - batchItem
      properties:
        batchItem:
          type: object
          description: The fields to change on the row.
          properties:
            description:
              type: string
              description: What the customer is being billed for.
            totalAmount:
              type: number
              description: The amount to bill for this row.
            paymentType:
              type: string
              description: The kind of invoice to create from this row.
            referenceId:
              type: string
              description: Your own reference for this row.
            isSuspendedPayment:
              type: boolean
              description: Whether the resulting invoice is held rather than payable straight away.
            dueDate:
              type: string
              description: When the resulting invoice falls due.
            extraFees:
              type: array
              description: Additional fees added on top of the amount.
              items:
                type: object
                additionalProperties: true
            items:
              type: array
              description: Line items making up the amount.
              items:
                type: object
                additionalProperties: true
    BatchShare:
      type: object
      description: The share record created when a batch is sent to its customers.
      properties:
        _id:
          type: string
        batchId:
          type: string
        shareLink:
          type: string
          description: The link for the shared batch.
        expiresAt:
          type: string
        resharedAt:
          type: string
        createdAt:
          type: string
    BatchImportResult:
      type: object
      description: The outcome of importing a sheet into a batch.
      properties:
        data:
          type: object
          properties:
            imported:
              type: integer
              description: Rows that were imported successfully.
            failed:
              type: integer
              description: Rows that were rejected.
            skipped:
              type: integer
            batchId:
              type: string
            errors:
              type: array
              description: One entry per rejected row, with the row number and what was wrong with it.
              items:
                type: object
                properties:
                  row:
                    type: integer
                  error:
                    type: string
        message:
          type: string
    CheckoutReferenceError:
      type: object
      description: Error returned by the checkout reference lookups. The reason is carried in `message` or `error`, depending on which validation rejected the request.
      additionalProperties: true
      properties:
        message:
          type: string
        error:
          type: string
    CheckoutMerchantPaymentMethods:
      type: object
      description: The payment methods enabled on a merchant account, as a map of method name to whether it is available. Method names match the keys of the payment method definitions.
      additionalProperties: true
    CheckoutInstallmentBank:
      type: object
      description: A bank offering card installments on the merchant account.
      additionalProperties: true
      properties:
        bankId:
          type: string
          description: The bank's identifier, used to fetch its installment plans.
        bankAbbreviation:
          type: string
          description: The bank's short code, e.g. `BM`. Used to fetch its installment fees.
        bankNameEn:
          type: string
          description: The bank's name in English.
        bankNameAr:
          type: string
          description: The bank's name in Arabic.
        logoUrl:
          type: string
          description: URL of the bank's logo, for rendering in the checkout.
    CheckoutInstallmentPlan:
      type: object
      description: One installment plan a bank offers on the merchant account.
      additionalProperties: true
      properties:
        _id:
          type: string
          description: The plan's identifier.
        planDuration:
          type: integer
          description: The number of months the customer pays over.
        minimunInstallmentAmount:
          type: number
          description: The smallest amount that qualifies for the plan. (The field name is misspelled in the API and kept as-is for compatibility.)
        fees:
          type: number
          description: The fee applied to the plan.
    CheckoutInstallmentFee:
      type: object
      description: The fee a bank charges for one plan duration.
      additionalProperties: true
      properties:
        planDuration:
          type: integer
          description: The number of months the customer pays over.
        fees:
          type: number
          description: The fee applied to that duration.
    BankConstants:
      type: object
      description: The Egyptian bank list, returned at two levels of detail.
      properties:
        bankNames:
          type: array
          description: One entry per bank. This is the list to read for `recipientBank` values.
          items:
            $ref: "#/components/schemas/BankConstantShort"
        banks:
          type: array
          description: One entry per bank *branch*, repeating the bank fields alongside the branch name and code.
          items:
            $ref: "#/components/schemas/BankConstantLong"
    BankConstantShort:
      type: object
      description: A bank, in short-key form.
      properties:
        en:
          type: string
          description: The bank's name in English.
        ar:
          type: string
          description: The bank's name in Arabic.
        Abbreviation:
          type: string
          description: The bank's short code, e.g. `NBE`.
    BankConstantLong:
      type: object
      description: A single bank branch.
      properties:
        Bank Name:
          type: string
          description: The bank's name in English.
        Arabic Bank Name:
          type: string
          description: The bank's name in Arabic.
        Abbreviation:
          type: string
          description: The bank's short code, e.g. `NBE`. Repeated on every branch of that bank.
        English Branch Name:
          type: string
          description: The branch's name in English.
        Arabic Branch Name:
          type: string
          description: The branch's name in Arabic.
        Branch Code:
          type: integer
          description: The branch's numeric code, unique within the bank.
    CityConstant:
      type: object
      description: An Egyptian governorate.
      additionalProperties: true
      properties:
        id:
          type: string
        governorate_id:
          type: string
          description: The governorate the city belongs to.
        city_name_en:
          type: string
          description: The name in English.
        city_name_ar:
          type: string
          description: The name in Arabic.
        value:
          type: string
          description: The ISO 3166-2 subdivision code, e.g. `EG-C` for Cairo.
    CountryConstant:
      type: object
      description: A country, with the codes and assets needed to render a country picker.
      additionalProperties: true
      properties:
        abbreviation2:
          type: string
          description: The ISO 3166-1 alpha-2 code, lowercased, e.g. `eg`.
        abbreviation3:
          type: string
          description: The ISO 3166-1 alpha-3 code, lowercased, e.g. `egy`.
        name:
          type: string
          description: The country's name.
        phone:
          type: string
          description: The international dialling prefix, e.g. `+20`.
        flag:
          type: string
          description: The country's flag as a `data:image/png;base64` URI.
    IndustryConstant:
      type: object
      description: A business industry and the sectors under it.
      additionalProperties: true
      properties:
        id:
          type: integer
        en:
          type: string
          description: The industry's name in English.
        ar:
          type: string
          description: The industry's name in Arabic.
        sectors:
          type: array
          description: The sectors that fall under the industry.
          items:
            $ref: "#/components/schemas/IndustrySector"
    IndustrySector:
      type: object
      description: A sector within an industry.
      properties:
        en:
          type: string
          description: The sector's name in English.
        ar:
          type: string
          description: The sector's name in Arabic.
        value:
          type: string
          description: The value to store for the sector.
    PaymentMethodDefinitions:
      type: object
      description: Each supported payment method mapped to the provider integrations that can process it.
      additionalProperties:
        type: array
        items:
          type: string
    DiscountError:
      type: object
      description: An error returned by the fee and discount calculators.
      properties:
        message:
          type: string
        error:
          type: string
    PaymentFeeCalculation:
      type: object
      description: The fee worked out for an amount.
      properties:
        amount:
          type: number
          description: The amount the fee was calculated on.
        fees:
          type: number
          description: The processing fee for that amount.
        totalAmount:
          type: number
          description: What the customer is charged — the amount plus the fee.
        currency:
          type: string
          description: Currency of the amounts, for example `EGP`.
        interactionSource:
          type: string
          description: The channel the fee was calculated for.
    DiscountCalculationRequest:
      type: object
      required:
        - merchantId
        - amount
      properties:
        merchantId:
          type: string
          description: "The merchant the payment is for. Example: `YOUR_MID`"
        amount:
          type: number
          description: The amount before fee and discount.
        interactionSource:
          type: string
          description: Where the payment is being taken, since fees differ by channel.
        discount:
          type: object
          additionalProperties: true
          description: The discount to apply. Send an empty object to calculate the fee alone.
    DiscountCalculation:
      type: object
      description: The result of applying a discount and a fee to an amount.
      properties:
        paymentFees:
          type: number
          description: The processing fee on the amount.
        discountAmount:
          type: number
          description: How much comes off for the discount.
        originalAmount:
          type: number
          description: The amount before the discount.
        finalAmount:
          type: number
          description: What the customer actually pays.
    DiscountName:
      type: object
      description: A discount campaign, named so you can label it in your own UI.
      properties:
        id:
          type: string
        discountName:
          type: string
        active:
          type: boolean
          description: Whether the campaign is currently running.
    Discount:
      type: object
      description: A live discount campaign.
      properties:
        id:
          type: string
        merchantId:
          type: string
        discountName:
          type: string
        discountType:
          type: string
          description: Whether the discount is a percentage of the amount or a fixed sum.
        discountValue:
          type: number
          description: The percentage, or the fixed amount, depending on `discountType`.
        currency:
          type: string
          description: Currency of a fixed-amount discount.
        validFrom:
          type: string
        validUntil:
          type: string
        status:
          type: string
    CardDiscountRequest:
      type: object
      required:
        - merchantId
        - card
      properties:
        merchantId:
          type: string
          description: "The merchant the payment is for. Example: `YOUR_MID`"
        card:
          type: string
          description: The card number the customer entered. Only its BIN is used to match a campaign.
        type:
          type: string
          description: What `card` holds — a card number.
        channel:
          type: string
          description: Where the payment is being taken.
        amount:
          type: number
          description: The amount the discount would be applied to.
    CardDiscountResponse:
      type: object
      description: Whether the card qualifies for a discount. `response` is absent when it does not.
      properties:
        status:
          type: string
        messages:
          $ref: "#/components/schemas/DiscountMessages"
        response:
          $ref: "#/components/schemas/CardDiscount"
    CardDiscount:
      type: object
      description: The discount that applies to the card.
      properties:
        discountId:
          type: string
        cardBin:
          type: string
          description: The card BIN the campaign matched on.
        discountAmount:
          type: string
          description: How much comes off this payment.
        discountPercentage:
          type: number
        maxDiscountAmount:
          type: number
          description: Ceiling on the discount, however large the payment.
        paymentFees:
          type: string
          description: The processing fee on the payment.
        minAmount:
          type: number
          description: Smallest payment the campaign applies to.
        maxAmount:
          type: number
          description: Largest payment the campaign applies to.
        validFrom:
          type: string
        validTo:
          type: string
    CardDiscountError:
      type: object
      description: An error returned by the card discount check.
      properties:
        status:
          type: string
        error:
          type: object
          properties:
            cause:
              type: string
        messages:
          $ref: "#/components/schemas/DiscountMessages"
    DiscountMessages:
      type: object
      description: Human-readable messages, in English and Arabic.
      properties:
        en:
          type: string
        ar:
          type: string
    InstantSettlementPagination:
      type: object
      description: Standard pagination block.
      additionalProperties: true
      properties:
        total:
          type: integer
          description: Total records matching the query, across all pages.
        limit:
          type: integer
          description: Records per page.
        page:
          type: integer
          description: The page returned.
        pages:
          type: integer
          description: Total number of pages.
    InstantSettlementLimits:
      type: object
      description: The instant settlement caps configured on your account. A cap of `0` means it is not configured and is not enforced.
      additionalProperties: true
      properties:
        perRequestCap:
          type: number
          description: The maximum amount you can include in a single request.
        dailyCap:
          type: number
          description: The maximum amount you can request in a day.
        usedToday:
          type: number
          description: Amount already requested today.
        remainingToday:
          type:
            - number
            - "null"
          description: Remaining amount you can request today. `null` when `dailyCap` is not configured.
    InstantSettlementEligibleTransaction:
      type: object
      description: A not-yet-settled transaction that qualifies for instant settlement.
      additionalProperties: true
      properties:
        transactionId:
          type: string
          description: The transaction's identifier.
        amount:
          type: number
          description: The gross transaction amount.
        settlementAmount:
          type: number
          description: What this transaction would settle for, after its normal processing fees. The instant settlement fee is calculated on this amount.
        accountId:
          type: string
          description: The balance account this transaction would settle into.
        method:
          type: string
          description: Payment method — `card` or `wallet`.
        channel:
          type: string
          description: Channel the transaction was taken on — `online` or `pos`.
        transactionDate:
          type: string
          description: When the transaction was taken (ISO).
        rfsDate:
          type: string
          description: The transaction's normal "ready for settlement" date, absent instant settlement (ISO).
    InstantSettlementEligibleTransactionsResponse:
      type: object
      description: A page of eligible transactions, with totals for the whole eligible set and your current caps.
      additionalProperties: true
      properties:
        message:
          type: string
        data:
          type: array
          items:
            $ref: "#/components/schemas/InstantSettlementEligibleTransaction"
        pagination:
          $ref: "#/components/schemas/InstantSettlementPagination"
        summary:
          type: object
          description: Totals across the whole eligible set, not just the current page.
          additionalProperties: true
          properties:
            count:
              type: integer
            totalAmount:
              type: number
            totalSettlementAmount:
              type: number
        limits:
          $ref: "#/components/schemas/InstantSettlementLimits"
    InstantSettlementSuggestionsInput:
      type: object
      description: The target amount to find transaction combinations for, plus optional filters narrowing the candidate set.
      additionalProperties: true
      required:
        - targetAmount
      properties:
        targetAmount:
          type: number
          description: The amount you would like to get as close to as possible. Must be a positive number.
        channel:
          type: string
          description: Optional channel filter — `online` or `pos`.
        method:
          type: string
          description: Optional payment-method filter — `card` or `wallet`.
        dateFrom:
          type: string
          description: Optional inclusive lower bound on the transaction date (ISO).
        dateTo:
          type: string
          description: Optional inclusive upper bound on the transaction date (ISO).
    InstantSettlementSuggestion:
      type: object
      description: One combination of eligible transactions.
      additionalProperties: true
      properties:
        totalAmount:
          type: number
          description: Combined settlement amount of the combination.
        transactionsCount:
          type: integer
          description: How many transactions are in the combination.
        transactionIds:
          type: array
          description: The transaction ids — pass these straight to the fee inquiry or to create a request.
          items:
            type: string
    InstantSettlementSuggestions:
      type: object
      description: The combinations of eligible transactions nearest to the target amount, from below and from above.
      additionalProperties: true
      properties:
        targetAmount:
          type: number
          description: The target you asked for.
        below:
          description: The largest combination whose total is at or under `targetAmount`. `null` if no combination fits.
          oneOf:
            - $ref: "#/components/schemas/InstantSettlementSuggestion"
            - type: "null"
        above:
          description: The smallest combination whose total is at or over `targetAmount`. `null` if no combination fits.
          oneOf:
            - $ref: "#/components/schemas/InstantSettlementSuggestion"
            - type: "null"
        candidatesConsidered:
          type: integer
          description: How many eligible transactions were considered.
        truncated:
          type: boolean
          description: Whether the candidate set was truncated before the search ran.
        approximate:
          type: boolean
          description: Whether the result is an approximation rather than the exact nearest combination.
        limits:
          $ref: "#/components/schemas/InstantSettlementLimits"
    InstantSettlementTransactionIds:
      type: object
      description: The transactions to quote a fee for, or to include in a request.
      additionalProperties: true
      required:
        - transactionIds
      properties:
        transactionIds:
          type: array
          description: Transaction ids. Must be a non-empty array, and every id must still be eligible.
          items:
            type: string
    InstantSettlementQuote:
      type: object
      description: The instant settlement fee breakdown. `totalSettlementAmount` is what the selected transactions are worth after their normal processing fees; the instant settlement fee is then taken off that to give `netTransferAmount`, the net amount paid out to you.
      additionalProperties: true
      properties:
        totalAmount:
          type: number
          description: Gross value of the selected transactions, before any fees.
        totalSettlementAmount:
          type: number
          description: What those transactions settle for normally, after their processing fees.
        totalRateFees:
          type: number
          description: The percentage part of the instant settlement fee.
        vat:
          type: number
          description: VAT charged on the percentage part of the fee.
        flatFees:
          type: number
          description: The flat transfer fee, charged once per request.
        totalFees:
          type: number
          description: "The whole instant settlement fee: `totalRateFees + vat + flatFees`."
        netTransferAmount:
          type: number
          description: "The net amount paid out to you: `totalSettlementAmount` minus `totalFees`."
        transactionsCount:
          type: integer
          description: How many transactions were included.
    InstantSettlementRequestTransaction:
      type: object
      description: A transaction belonging to an instant settlement request.
      additionalProperties: true
      properties:
        transactionId:
          type: string
        settlementAmount:
          type: number
        accountId:
          type: string
        rfsDate:
          type: string
        method:
          type: string
        selected:
          type: boolean
          description: Whether the transaction is still part of the request. `false` when an agent removed it. Rows created before selection state existed are always `true`.
        unselectedAt:
          type:
            - string
            - "null"
          description: When the transaction was removed from the request (ISO), or `null` if it is still selected.
    InstantSettlementLinkedBalanceRecord:
      type: object
      description: A balance-ledger record created for this request's early-payout deduction — one per account and settlement date.
      additionalProperties: true
      properties:
        recordId:
          type: string
          description: The ledger record's identifier, of the form `<requestId>-<YYYYMMDD>`.
        accountId:
          type: string
        accountName:
          type:
            - string
            - "null"
          description: The account's name as it was when the deduction was created. Renaming the account does not relabel past movements. `null` when unavailable.
        amount:
          type: number
          description: The deducted amount, as a negative number.
        valueDate:
          type: string
          description: The settlement date this deduction is grouped under (ISO).
        isReflected:
          type: boolean
          description: Whether this deduction has been fully reflected in your balance yet.
        type:
          type: string
          description: Always `INSTANT_SETTLEMENT_DEDUCTION` for these records.
        operation:
          type: string
          description: Always `deduct`.
        origin:
          type: string
          description: Always `settlements`.
    InstantSettlementRequest:
      type: object
      description: An instant settlement request. The list endpoint returns a summary of these fields; the details endpoint returns the full object.
      additionalProperties: true
      properties:
        id:
          type: string
          description: The request's UUID.
        requestId:
          type: string
          description: The request's human-readable identifier, e.g. `ISR-1042`.
        merchantId:
          type: string
        merchantName:
          type: string
        storeName:
          type: string
        status:
          type: string
          description: |
            `PENDING` — created, waiting to be processed. `PROCESSING` — the early payout amount has
            been deducted from your balance. `TRANSFERRED` — the payout has reached your payout
            method. `DECLINED` — the request will not be processed; see `declineReason`.
          enum:
            - PENDING
            - PROCESSING
            - TRANSFERRED
            - DECLINED
        declineReason:
          type:
            - string
            - "null"
          description: Why the request was declined. `null` unless `status` is `DECLINED`.
        totalAmount:
          type: number
        totalSettlementAmount:
          type: number
        totalRateFees:
          type: number
        flatFees:
          type: number
        vat:
          type: number
        totalFees:
          type: number
        netTransferAmount:
          type: number
          description: The amount you will receive after fees.
        transactionsCount:
          type: integer
        requestedBy:
          type: string
          description: The merchant user who created the request.
        statusHistory:
          type: array
          description: A log of this request's status changes.
          items:
            type: object
            additionalProperties: true
            properties:
              status:
                type: string
              at:
                type: string
              by:
                type: string
        unselectedTransactions:
          type: array
          description: Transactions an agent removed from the request. Empty when nothing was removed.
          items:
            $ref: "#/components/schemas/InstantSettlementRequestTransaction"
        unselectedCount:
          type: integer
          description: How many transactions were removed from the request.
        unselectedSettlementAmount:
          type: number
          description: Combined settlement amount of the removed transactions.
        linkedBalanceRecords:
          type:
            - array
            - "null"
          description: The balance-ledger records created for this request's deduction. `[]` while the request is `PENDING`; `null` when the balance ledger was unavailable.
          items:
            $ref: "#/components/schemas/InstantSettlementLinkedBalanceRecord"
        linkedBalanceRecordsUnavailable:
          type: boolean
          description: Present and `true` only when the balance ledger could not be read, in which case `linkedBalanceRecords` is `null`. Retry later.
        createdAt:
          type: string
        updatedAt:
          type: string
    InstantSettlementRequestEnvelope:
      type: object
      description: A single instant settlement request.
      additionalProperties: true
      properties:
        message:
          type: string
        data:
          $ref: "#/components/schemas/InstantSettlementRequest"
    InstantSettlementRequestListResponse:
      type: object
      description: A page of instant settlement requests.
      additionalProperties: true
      properties:
        message:
          type: string
        data:
          type: array
          items:
            $ref: "#/components/schemas/InstantSettlementRequest"
        pagination:
          $ref: "#/components/schemas/InstantSettlementPagination"
    InstantSettlementRequestTransactionsResponse:
      type: object
      description: A page of the transactions belonging to an instant settlement request.
      additionalProperties: true
      properties:
        message:
          type: string
        data:
          type: array
          items:
            $ref: "#/components/schemas/InstantSettlementRequestTransaction"
        pagination:
          $ref: "#/components/schemas/InstantSettlementPagination"
        summary:
          type: object
          description: Totals for the current `selection` filter, across all pages.
          additionalProperties: true
          properties:
            count:
              type: integer
            totalAmount:
              type: number
            totalSettlementAmount:
              type: number
        selectionSummary:
          type: object
          description: Counts and totals spanning the whole request, ignoring the `selection` filter.
          additionalProperties: true
          properties:
            selectedCount:
              type: integer
            unselectedCount:
              type: integer
            selectedSettlementAmount:
              type: number
            unselectedSettlementAmount:
              type: number
    InstantSettlementError:
      type: object
      description: |
        Error returned by the instant settlement endpoints. The shape depends on the layer that
        rejected the call: the auth and feature gates return a bare `message`, while the module's own
        validation and limit errors return a `status`/`error` envelope.
      additionalProperties: true
      properties:
        message:
          type: string
          description: Human-readable reason, used by the auth and feature-flag gates.
        status:
          type: string
          description: Outcome of the call, e.g. `FAILURE`.
        error:
          type: object
          description: The failure detail. Carries `cause` for validation failures, or `code`/`message` plus the relevant cap figures for limit failures.
          additionalProperties: true
          properties:
            cause:
              type: string
            code:
              type: string
            message:
              type: string
            limit:
              type: number
            requested:
              type: number
            usedToday:
              type: number
            remaining:
              type: number
    PosError:
      type: object
      description: Error returned by the POS and terminal endpoints. Depending on which layer rejected the request, the human-readable reason is carried in `messages`, `message`, or `error`.
      additionalProperties: true
      properties:
        status:
          type: string
          description: Outcome of the call, e.g. `FAILURE`, `INVALID_REQUEST`, `UNAUTHORIZED`.
        message:
          type: string
        messages:
          $ref: "#/components/schemas/PosLocalizedMessage"
        error:
          type: object
          additionalProperties: true
        response:
          type: object
          additionalProperties: true
    PosLocalizedMessage:
      type: object
      description: Message localized in English and Arabic.
      properties:
        en:
          type: string
        ar:
          type: string
    PosTerminalMessageRequest:
      type: object
      description: A message relayed to the terminal. Only `event` and `data` are validated by Kashier; the contents of `data.message` are enforced by the terminal application.
      required:
        - event
        - data
      properties:
        event:
          type: string
          description: The operation the terminal should perform.
          enum:
            - sale
            - details
        data:
          $ref: "#/components/schemas/PosTerminalMessageData"
        expirationInSeconds:
          type: integer
          description: How long the message stays valid while waiting for the terminal, in seconds.
    PosTerminalMessageData:
      type: object
      description: Wrapper carrying the message the terminal receives.
      properties:
        message:
          $ref: "#/components/schemas/PosTerminalMessage"
    PosTerminalMessage:
      type: object
      description: The message payload the terminal acts on. `amount`, `currency`, and `merchantOrderId` apply to a `sale`; `details` applies to a `details` lookup.
      additionalProperties: true
      properties:
        amount:
          type: string
          description: The amount to charge, e.g. `100.00`.
        currency:
          type: string
          description: The currency the customer pays in, e.g. `EGP`.
          enum:
            - EGP
            - USD
            - GBP
            - EUR
        merchantOrderId:
          type: string
          description: The order ID for the payment in your system. For a `sale`, Kashier rejects the message if this order is already paid.
        transactionType:
          type: string
          description: The transaction type of the operation, e.g. `sale` or `details`. Relayed to the terminal as-is.
        printReceipt:
          type: boolean
          description: "`true` lets the terminal print the receipt. Default: `false`."
        metaData:
          type: object
          description: Extra key/value information to carry with the transaction. Send `{}` if you have none.
          additionalProperties: true
        reconciliation:
          $ref: "#/components/schemas/PosReconciliation"
        details:
          $ref: "#/components/schemas/PosTransactionLookup"
    PosReconciliation:
      type: object
      description: Where Kashier reports the card-present result once the terminal finishes.
      properties:
        webhookUrl:
          type: string
          description: The endpoint URL where you want to receive Kashier's webhook.
    PosTransactionLookup:
      type: object
      description: Identifies the transaction a `details` message is asking about.
      properties:
        paymentMethod:
          type: string
          description: The payment method of the order you are inquiring about, e.g. `card`.
        merchantOrderId:
          type: string
          description: The order ID of the order you are inquiring about.
        transactionId:
          type: string
          description: Kashier's transaction ID for the payment you are inquiring about. You can find it in the webhook request sent by Kashier.
        valu:
          type: object
          description: Required only for ValU payments.
          properties:
            type:
              type: string
              description: The type of ValU credentials your Kashier account uses.
              enum:
                - PF
                - PSP
    PosMessageAccepted:
      type: object
      description: Confirmation that the message reached the terminal. The payment result is not in this response — it arrives on your reconciliation webhook.
      additionalProperties: true
      properties:
        status:
          type: string
        body:
          type: object
          additionalProperties: true
    PosQrCodeRequest:
      type: object
      description: Order to generate a POS payment QR code for.
      required:
        - paymentMethod
        - order
      properties:
        paymentMethod:
          type: object
          description: The payment method the QR should open.
          required:
            - type
          properties:
            type:
              type: string
              description: Payment method type, e.g. `card`.
        order:
          type: object
          description: The order the customer is paying for.
          required:
            - reference
            - amount
          properties:
            reference:
              type: string
              description: Your order reference.
            amount:
              type: string
              description: Order amount, e.g. `100.00`.
        merchantId:
          type: string
          description: Merchant account number or merchant ID, e.g. `YOUR_MID`.
        posTerminal:
          type: string
          description: The terminal the QR is generated for.
        metaData:
          type: object
          description: Extra key/value information to carry with the order.
          additionalProperties: true
        newPaymentUI:
          type: boolean
          description: Open the generated link on the current payment page experience.
    PosQrCodeResponse:
      type: object
      description: The generated QR code.
      properties:
        qrUrl:
          type: string
          description: The QR image as a `data:image/png;base64` URI. Render it for the customer to scan.
        status:
          type: string
        message:
          type: string
    PosAcknowledgeRequest:
      type: object
      description: Acknowledgement request. Send an empty object to acknowledge the terminal's outstanding transactions.
      additionalProperties: true
    PosReconcileRequest:
      type: object
      description: The terminal and the totals your system holds for it.
      required:
        - terminalId
      properties:
        terminalId:
          type: string
          description: The terminal ID (ISO 8583 DE 41) being reconciled.
        reconciliationData:
          type: object
          description: The totals your system expects for the terminal.
          additionalProperties: true
          properties:
            transactionCount:
              type: integer
              description: Number of transactions your system holds for the terminal.
            totalAmount:
              type: string
              description: Total amount your system holds for the terminal, e.g. `5000.00`.
    PosBnplRequest:
      type: object
      description: A buy-now-pay-later operation to run on a terminal.
      required:
        - terminalId
        - amount
      properties:
        terminalId:
          type: string
          description: The terminal ID (ISO 8583 DE 41) the payment runs on.
        amount:
          type: string
          description: The amount to charge, e.g. `100.00`.
        planId:
          type: string
          description: The BNPL plan to charge against.
    PosOperationResult:
      type: object
      description: Generic result envelope returned by the POS operation endpoints.
      additionalProperties: true
      properties:
        status:
          type: string
        response:
          type: object
          additionalProperties: true
        messages:
          $ref: "#/components/schemas/PosLocalizedMessage"
    PosTransaction:
      type: object
      description: One card-present transaction processed on a terminal. Field names follow the POS transaction list projection, so they are snake_case.
      additionalProperties: true
      properties:
        merchant_order_id:
          type: string
          description: The order ID for the payment in your system.
        ref_number:
          type: string
          description: The acquirer reference number for the transaction.
        amount:
          type: number
          description: Transaction amount.
        currency:
          type: string
          description: Transaction currency, e.g. `EGP`.
        payment_type:
          type: string
          description: The type of payment, e.g. a sale or a refund.
        entry_mode:
          type: string
          description: How the card was read (ISO 8583 DE 22), e.g. `CONTACT`, `CONTACTLESS`, `MAGNETIC`, `FALLBACK`, `MANUAL`.
    PosTransactionList:
      type: object
      description: A terminal's transactions. The gateway passes the transaction manager's response through unchanged, so extra reporting fields may be present.
      additionalProperties: true
      properties:
        body:
          type: object
          additionalProperties: true
          properties:
            response:
              type: object
              additionalProperties: true
              properties:
                terminalId:
                  type: string
                transactions:
                  type: array
                  items:
                    $ref: "#/components/schemas/PosTransaction"
        status:
          type: string
    PosTransactionDetails:
      type: object
      description: One transaction's details. The gateway passes the transaction manager's response through unchanged.
      additionalProperties: true
      properties:
        body:
          type: object
          additionalProperties: true
          properties:
            response:
              $ref: "#/components/schemas/PosTransaction"
        status:
          type: string
    PosReport:
      type: object
      description: A terminal transaction report for the requested window. The gateway passes the transaction manager's response through unchanged.
      additionalProperties: true
      properties:
        body:
          type: object
          additionalProperties: true
        status:
          type: string
    PosBranch:
      type: object
      description: A physical location POS terminals are assigned to.
      additionalProperties: true
      properties:
        id:
          type: string
        name:
          type: string
        address:
          type: string
    PosBranchList:
      type: object
      description: Your POS branches.
      additionalProperties: true
      properties:
        body:
          type: object
          additionalProperties: true
          properties:
            response:
              type: object
              additionalProperties: true
              properties:
                branches:
                  type: array
                  items:
                    $ref: "#/components/schemas/PosBranch"
        status:
          type: string
    Terminal:
      type: object
      description: A POS terminal registered on your merchant account.
      additionalProperties: true
      properties:
        _id:
          type: string
          description: The terminal record ID.
        terminalId:
          type: string
          description: The terminal ID (ISO 8583 DE 41).
        serialNo:
          type: string
          description: The terminal's serial number — the address used when relaying a message to it.
        brandModel:
          type: string
          description: The terminal hardware model.
        merchantPayformanceId:
          type: string
          description: The merchant ID the terminal belongs to, e.g. `YOUR_MID`.
        branchName:
          type: string
        address:
          type: string
        status:
          type: string
          description: Whether the terminal is enabled.
          enum:
            - active
            - inactive
        mode:
          type: string
          description: Whether the terminal transacts against the live card networks.
          enum:
            - test
            - live
        communicationMethod:
          type: string
          description: How the terminal reaches the network.
          enum:
            - data
            - wifi
        limits:
          type: object
          description: Card-acceptance limits configured on the terminal.
          additionalProperties: true
        createdAt:
          type: string
    TerminalList:
      type: object
      description: A page of terminals.
      additionalProperties: true
      properties:
        terminals:
          type: array
          items:
            $ref: "#/components/schemas/Terminal"
        pagination:
          $ref: "#/components/schemas/TerminalPagination"
    TerminalBranch:
      type: object
      description: A branch terminals are assigned to.
      additionalProperties: true
      properties:
        _id:
          type: string
        branchName:
          type: string
        address:
          type: string
        terminalCount:
          type: integer
          description: How many terminals are assigned to the branch.
    TerminalBranchList:
      type: object
      description: A page of terminal branches.
      additionalProperties: true
      properties:
        branches:
          type: array
          items:
            $ref: "#/components/schemas/TerminalBranch"
        pagination:
          $ref: "#/components/schemas/TerminalPagination"
    TerminalPagination:
      type: object
      properties:
        total:
          type: integer
        limit:
          type: integer
        page:
          type: integer
        pages:
          type: integer
    CataloguePagination:
      type: object
      description: Pagination info returned alongside paged product and category lists.
      properties:
        total:
          type: integer
          description: Total number of records matching the filters.
        page:
          type: integer
        limit:
          type: integer
        pages:
          type: integer
          description: Total number of pages.
    CatalogueError:
      type: object
      description: An error returned by the products and categories endpoints.
      properties:
        message:
          type: string
        error:
          type: string
    CatalogueProduct:
      type: object
      description: A product in the merchant's catalogue.
      properties:
        _id:
          type: string
          description: Internal record id.
        merchantId:
          type: string
        name:
          type: string
          description: The product name.
        sku:
          type: string
          description: The product's stock keeping unit, when one is set.
        price:
          type: number
          description: Unit price of the product.
        currency:
          type: string
          description: Currency the product is priced in, for example `EGP`.
        description:
          type: string
        image:
          type: string
          description: URL of the product image, as returned by `uploadProductImage`.
        status:
          type: string
          description: Whether the product is available or out of stock.
        createdAt:
          type: string
        updatedAt:
          type: string
    CatalogueProductCreateRequest:
      type: object
      required:
        - productName
        - currency
        - unitPrice
      properties:
        productName:
          type: string
          description: The product name shown to customers.
        currency:
          type: string
          description: Currency the product is priced in, for example `EGP`.
          enum:
            - EGP
            - USD
            - GBP
            - EUR
        unitPrice:
          type: number
          description: Price of a single unit.
        isVariant:
          type: boolean
          description: Whether this product is a variation of another product.
        quantity:
          type: integer
          description: Stock quantity. Leave it out when the product is not stock-tracked.
    CatalogueProductUpdateRequest:
      type: object
      description: The fields to change on a product. Anything you leave out keeps its current value.
      properties:
        productName:
          type: string
        unitPrice:
          type: number
        quantity:
          type: integer
    CatalogueTimelineEntry:
      type: object
      description: One entry in a product's audit trail.
      properties:
        _id:
          type: string
        action:
          type: string
          description: What happened, for example `created` or `updated`.
        changedFields:
          type: object
          additionalProperties: true
          description: The fields that changed, and their new values.
        changedBy:
          type: string
          description: The dashboard user who made the change.
        timestamp:
          type: string
    CatalogueCategory:
      type: object
      description: A product category.
      properties:
        _id:
          type: string
          description: Internal record id.
        name:
          type: string
        description:
          type: string
        merchantId:
          type: string
        createdByUserId:
          type: string
        createdAt:
          type: string
        updatedAt:
          type: string
    CatalogueCategoryWriteRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          description: The category name.
    CatalogueCategoryAssignRequest:
      type: object
      required:
        - categoryIds
        - productIds
        - operation
      properties:
        categoryIds:
          type: array
          description: The categories to add or remove.
          items:
            type: string
        productIds:
          type: array
          description: The products to update.
          items:
            type: string
        operation:
          type: string
          description: The direction of the change. Pass `assign` to add the categories to the products.
    CatalogueCategoryChangeRequest:
      type: object
      required:
        - categoryIds
        - productIds
      properties:
        categoryIds:
          type: array
          description: The categories the products should end up in, replacing whatever they had before.
          items:
            type: string
        productIds:
          type: array
          description: The products to update.
          items:
            type: string
    Webhook:
      type: object
      description: A webhook configured through the webhook management module (`/v2/webhooks`). Each one has its own URL, its own event subscriptions, and its own mode, so you can point test and live traffic at different endpoints.
      properties:
        _id:
          type: string
          description: Unique identifier for the webhook — this is the `webhookId` used in Update a webhook and Delete a webhook.
          example: 66a1f2c3e4b0a1234567890a
        merchantId:
          type: string
          description: The merchant the webhook belongs to.
          example: MID-10293
        name:
          type: string
          description: Your label for the webhook.
        url:
          type: string
          format: uri
          description: The endpoint Kashier delivers to.
        headers:
          type: object
          description: Custom headers Kashier sends with every delivery to this webhook, as a flat string-to-string map.
          additionalProperties:
            type: string
        events:
          $ref: "#/components/schemas/WebhookEventList"
        mode:
          type: string
          description: The webhook only receives events emitted in this mode.
          enum:
            - test
            - live
        isActive:
          type: boolean
          description: Whether the webhook currently receives deliveries.
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    WebhookDeliveryRecord:
      type: object
      description: One recorded webhook delivery attempt (or set of attempts).
      properties:
        resourceType:
          type: string
          description: The kind of resource this delivery relates to.
          enum:
            - transaction
            - transfer
        resourceId:
          type: string
          description: The transaction or transfer id this delivery relates to.
        webhookId:
          type:
            - string
            - "null"
          description: The webhook this delivery came from, or `null` if it was a per-session webhook passed directly on the transaction.
        eventType:
          type: string
          description: The event that triggered this delivery — a transaction operation value for transaction records, or a transfer status value for transfer records.
        mode:
          type: string
          enum:
            - test
            - live
        url:
          type: string
          format: uri
          description: The destination URL the delivery was sent to.
        status:
          type: string
          description: Delivery status, e.g. `delivered`, `failed`, `pending`.
        attempts:
          type: integer
          description: Number of delivery attempts recorded.
        payload:
          type: object
          additionalProperties: true
          description: The request body sent, projected to a fixed, always-visible field set. Custom `headers` configured on the webhook are never included in this response.
        responses:
          type: array
          description: One entry per delivery attempt.
          items:
            type: object
            properties:
              status:
                type: integer
                description: The receiving endpoint's HTTP status for this attempt.
              body:
                type: string
                description: The receiving endpoint's response body for this attempt.
              date:
                type: string
                format: date-time
        isServerWebhook:
          type: boolean
          description: "`true` if this delivery went to a per-session webhook rather than a configured webhook."
        isTest:
          type: boolean
          description: "`true` if this record came from Test a webhook rather than a real delivery."
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    WebhookEvent:
      type: string
      description: |
        A single event type a webhook can be subscribed to. Six are transaction events
        (`pay`, `authorize`, `capture`, `refund`, `void`, `reversal`) and four are transfer
        status events (`INITIATED`, `IN_TRANSIT`, `TRANSFERRED`, `FAILED`). The casing is
        significant — the values are matched literally against the transaction operation or
        the transfer status that produced the event, so send them exactly as listed.
      enum:
        - pay
        - authorize
        - capture
        - refund
        - void
        - reversal
        - INITIATED
        - IN_TRANSIT
        - TRANSFERRED
        - FAILED
    WebhookEventList:
      type: array
      description: The event types a webhook is subscribed to.
      items:
        $ref: "#/components/schemas/WebhookEvent"
    MerchantApiKey:
      type: object
      description: A Payment API key on the merchant account. Only fields Kashier documents are listed; the response carries more.
      additionalProperties: true
      properties:
        merchantId:
          type: string
          description: The merchant the key belongs to.
          example: MID-123-456
        mode:
          type: string
          description: The environment the key works in. A key only ever works in its own mode.
          enum:
            - test
            - live
        isInternal:
          type: boolean
          description: Always `false` on keys returned to you — Kashier's internal keys are filtered out of the list.
    CredentialToValidate:
      type: object
      description: One credential to check, paired with the environment you believe it belongs to.
      required:
        - mode
        - key
      properties:
        mode:
          type: string
          enum:
            - test
            - live
        key:
          type: string
          description: The credential value.
    AllowedIpAddressRequest:
      type: object
      description: An entry on the secret-key IP allow-list.
      required:
        - name
        - ipAddress
        - userId
      properties:
        name:
          type: string
          description: Your label for the address, e.g. `Production API server`.
        ipAddress:
          type: string
          description: A valid IPv4 or IPv6 address. `0.0.0.0` is rejected.
        userId:
          type: string
          description: The dashboard user the entry applies to. The allow-list is checked per user as well as per merchant, so the entry must name the user whose secret key does the calling.
    WebhookEventCatalogEntry:
      type: object
      description: One entry in the subscribable-event catalog.
      properties:
        value:
          allOf:
            - $ref: "#/components/schemas/WebhookEvent"
          description: The literal value to put in a webhook's `events` array.
        label:
          type: string
          description: A human-readable name for the event, suitable for a settings UI.
        resource:
          type: string
          description: Which resource emits the event.
          enum:
            - transaction
            - transfer
