> ## Documentation Index
> Fetch the complete documentation index at: https://docs.yourflexpay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Initiate a tag-to-tag payment

> Creates a new cross-application payment from a tag owned by the calling application
to any tag on any application.  The transaction starts in `AWAITING_ACCEPTANCE` state.

The receiving application is notified via webhook and must call
`POST /v1/transactions/{reference}/accept` or `.../reject`.

**Idempotency**: Supply a unique `Idempotency-Key` header; duplicate calls within
24 hours return the original response without creating a new transaction.

**Rate limited to 60 requests per minute per application.**




## OpenAPI

````yaml /openapi/idaas.openapi.json post /v1/transactions
openapi: 3.0.3
info:
  title: IDaaS – Identity as a Service API
  description: >
    ## Overview

    IDaaS provides globally unique, portable identity **tags** that travel with
    users across applications.  Each tag is a short handle (e.g. `@alice`) that
    can carry verified claims, participate in cross-application payments, and be
    federated to external identity providers.


    ## Key Capabilities

    - **Tags** – create, transfer, disable, and attach claims to identity
    handles.

    - **Cross-application payments** – send money from any tag on Application
    A   to any tag on Application B; each application has a single escrow
    wallet   tracked for end-of-day settlement.

    - **Ledger** – every completed payment produces an immutable double-entry  
    `DEBIT` / `CREDIT` pair recorded against application wallets.

    - **Webhooks** – real-time callbacks with HMAC-SHA256 signatures and  
    automatic retry (up to 3 attempts with exponential back-off).

    - **Settlement** – a scheduled end-of-day job aggregates daily wallet  
    movements and emits `SETTLEMENT_BATCH` Kafka events.


    ## Authentication

    1. Register an application: `POST /v1/applications`

    2. Exchange credentials for a JWT: `POST /v1/auth/token`

    3. Include the JWT as `Authorization: Bearer <token>` on all protected
    calls.


    ## Rate Limits

    | Endpoint | Limit |

    |---|---|

    | `POST /v1/auth/token` | 10 req / min per IP |

    | `POST /v1/transactions` | 60 req / min per application |

    | All other | 300 req / min per IP |
  contact:
    name: ReflexPay Platform Team
    url: https://yourflexpay.com
    email: integration@yourflexpay.com
  license:
    name: Proprietary
    url: https://yourflexpay.com/terms
  version: 1.0.0
servers:
  - url: https://staging-idaas.yourflexpay.com/api
    description: Staging
  - url: https://idaas.yourflexpay.com/api
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Authentication
    description: Exchange client credentials for a JWT access token.
  - name: Encryption
    description: >
      JWE payload encryption – end-to-end security for API request bodies and
      webhook payloads.

      Each application receives an EC P-256 keypair at registration:

      - IDaaS encrypts **outbound webhooks** with the application's public key.

      - Applications encrypt **inbound request bodies** with the IDaaS public
      key.

      Algorithm: ECDH-ES+A256KW + A256GCM (JSON Web Encryption, RFC 7516).

      Use `GET /v1/keys/idaas` to fetch the IDaaS public key.

      Use `POST /v1/applications/keys/rotate` to rotate your application
      keypair.
  - name: Wallet
    description: View application escrow wallet balance and paginated ledger statement.
  - name: Subjects
    description: Manage the real-world entities (users / organisations) behind tags.
  - name: Tags
    description: Create, transfer, disable and resolve globally unique identity tags.
  - name: Claims
    description: Attach and revoke verifiable claims on tags.
  - name: Consent
    description: Issue and manage user consent tokens for claim federation.
  - name: Transactions
    description: Initiate, accept/reject, and query cross-application tag-to-tag payments.
  - name: Settlement
    description: Query end-of-day settlement batches and per-application net positions.
  - name: Webhooks
    description: >-
      Inspect outbound webhook delivery records for transactions. Each
      transaction has at most two webhook records: one RECEIVER (sent on
      initiation) and one SENDER (sent on acceptance/rejection/expiry).
externalDocs:
  description: IDaaS GitHub Repository
  url: https://github.com/reflexpay/idaas
paths:
  /v1/transactions:
    post:
      tags:
        - Transactions
      summary: Initiate a tag-to-tag payment
      description: >
        Creates a new cross-application payment from a tag owned by the calling
        application

        to any tag on any application.  The transaction starts in
        `AWAITING_ACCEPTANCE` state.


        The receiving application is notified via webhook and must call

        `POST /v1/transactions/{reference}/accept` or `.../reject`.


        **Idempotency**: Supply a unique `Idempotency-Key` header; duplicate
        calls within

        24 hours return the original response without creating a new
        transaction.


        **Rate limited to 60 requests per minute per application.**
      operationId: initiate
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Optional idempotency key (UUID or any unique string, max 128 chars).
            Duplicate calls with the same key within 24 hours return the
            original response.
          required: false
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InitiateTransactionRequest'
        required: true
      responses:
        '201':
          description: Transaction initiated successfully
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ApiResponseTransactionResponse'
        '400':
          description: Validation error (invalid tags, zero amount, etc.)
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '401':
          description: Missing or invalid bearer token
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ApiResponseTransactionResponse'
        '403':
          description: Sender tag does not belong to the calling application
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ApiResponseTransactionResponse'
        '429':
          description: Rate limit exceeded
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ApiResponseTransactionResponse'
components:
  schemas:
    InitiateTransactionRequest:
      required:
        - amount
        - receiverTag
        - senderTag
      type: object
      properties:
        senderTag:
          type: string
          description: The sender's tag handle (must belong to the calling application)
          example: '@alice'
        receiverTag:
          type: string
          description: The recipient's tag handle (can belong to any application)
          example: '@bob'
        amount:
          minimum: 0.0001
          exclusiveMinimum: false
          type: number
          description: Positive payment amount with up to 4 decimal places
          example: 1500
        currency:
          pattern: ^[A-Z]{3}$
          type: string
          description: ISO 4217 currency code (defaults to NGN)
          example: NGN
        narration:
          maxLength: 500
          minLength: 0
          type: string
          description: Optional human-readable payment note
          example: School fees payment
        callbackUrl:
          maxLength: 500
          minLength: 0
          type: string
          description: >-
            Optional HTTPS URL that IDaaS will POST the final transaction status
            to once accepted or rejected
          example: https://my-app.example.com/webhooks/transactions
        idempotencyKey:
          maxLength: 64
          minLength: 0
          type: string
          description: >-
            Client-supplied idempotency key (UUID v4 recommended). Duplicate
            calls within 24 hours return the original response.
          example: 550e8400-e29b-41d4-a716-446655440000
      description: Request body for initiating a cross-application tag-to-tag payment
    ApiResponseTransactionResponse:
      type: object
      properties:
        success:
          type: boolean
        message:
          type: string
        errorCode:
          type: string
        data:
          $ref: '#/components/schemas/TransactionResponse'
        errors:
          type: array
          items:
            type: string
        timestamp:
          type: string
          format: date-time
    ApiResponse:
      type: object
      properties:
        success:
          type: boolean
        message:
          type: string
        errorCode:
          type: string
        data:
          type: object
        errors:
          type: array
          items:
            type: string
        timestamp:
          type: string
          format: date-time
    TransactionResponse:
      type: object
      properties:
        id:
          type: string
          description: Unique transaction ID
          format: uuid
          example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        reference:
          type: string
          description: Human-readable unique reference for the transaction
          example: TXN-16820000-AB1C2D3E
        senderTag:
          type: string
          description: Sender tag handle
          example: '@alice'
        senderAppName:
          type: string
          description: Name of the sender's application
          example: WalletApp
        senderAppId:
          type: string
          description: UUID of the sender's application
          format: uuid
        receiverTag:
          type: string
          description: Receiver tag handle
          example: '@bob'
        receiverAppName:
          type: string
          description: Name of the receiver's application
          example: PaymentsApp
        receiverAppId:
          type: string
          description: UUID of the receiver's application
          format: uuid
        amount:
          type: number
          description: Payment amount (DECIMAL 19,4)
          example: 1500
        currency:
          type: string
          description: ISO 4217 currency code
          example: NGN
        status:
          type: string
          description: Transaction lifecycle status
          example: AWAITING_ACCEPTANCE
          enum:
            - AWAITING_ACCEPTANCE
            - COMPLETED
            - REJECTED
            - EXPIRED
        narration:
          type: string
          description: Human-readable payment note
          example: School fees payment
        expiresAt:
          type: string
          description: >-
            ISO-8601 timestamp after which the transaction auto-expires if not
            accepted
          format: date-time
        acceptedAt:
          type: string
          description: >-
            ISO-8601 timestamp when the transaction was accepted (null until
            COMPLETED)
          format: date-time
        rejectedAt:
          type: string
          description: >-
            ISO-8601 timestamp when the transaction was rejected (null unless
            REJECTED)
          format: date-time
        rejectionReason:
          type: string
          description: >-
            Rejection reason supplied by the receiving application (null unless
            REJECTED)
        createdAt:
          type: string
          description: ISO-8601 creation timestamp
          format: date-time
        updatedAt:
          type: string
          description: ISO-8601 last-update timestamp
          format: date-time
        webhooks:
          type: array
          description: >-
            Outbound webhook delivery records (RECEIVER and/or SENDER). Included
            in single-transaction GET; omitted in list responses.
          items:
            $ref: '#/components/schemas/TransactionWebhookResponse'
      description: Full details of a cross-application tag-to-tag payment transaction
    TransactionWebhookResponse:
      type: object
      properties:
        id:
          type: string
          description: Unique webhook record ID
          format: uuid
        transactionId:
          type: string
          description: UUID of the parent transaction
          format: uuid
        transactionReference:
          type: string
          description: Transaction reference
          example: TXN-16820000-AB1C2D3E
        applicationId:
          type: string
          description: UUID of the target application (receiver or sender)
          format: uuid
        applicationName:
          type: string
          description: Name of the target application
        direction:
          type: string
          description: Which side this webhook notifies
          enum:
            - RECEIVER
            - SENDER
        targetUrl:
          type: string
          description: HTTP endpoint that was (or will be) called
          example: https://app-b.example.com/webhooks/transactions
        eventType:
          type: string
          description: Event name included in the webhook body
          example: TRANSACTION_INITIATED
          enum:
            - TRANSACTION_INITIATED
            - TRANSACTION_COMPLETED
            - TRANSACTION_REJECTED
            - TRANSACTION_EXPIRED
        status:
          type: string
          description: Current delivery status
          enum:
            - PENDING
            - DELIVERED
            - FAILED
        attempts:
          type: integer
          description: Total number of HTTP delivery attempts made (max 3)
          format: int32
        lastError:
          type: string
          description: HTTP status code or exception message from the most recent attempt
        lastAttemptAt:
          type: string
          description: ISO-8601 timestamp of the most recent delivery attempt
          format: date-time
        deliveredAt:
          type: string
          description: >-
            ISO-8601 timestamp when delivery was confirmed (HTTP 2xx). Null
            until delivered.
          format: date-time
        createdAt:
          type: string
          description: ISO-8601 creation timestamp (when the webhook was first queued)
          format: date-time
        updatedAt:
          type: string
          description: ISO-8601 last-update timestamp
          format: date-time
      description: Outbound webhook delivery record for a transaction
  securitySchemes:
    bearerAuth:
      type: http
      description: >
        Obtain a token from `POST /v1/auth/token` using your `client_id` and
        `client_secret`, then enter `Bearer <token>` here.
      scheme: bearer
      bearerFormat: JWT

````