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

# Create a transfer

> Initiate a transfer between accounts. Supports single-provider and inter-platform transfers.
Fields provider, currency, payment_method.type are case-insensitive.




## OpenAPI

````yaml /api-specs/v1/crowdsplits.yaml post /api/v1/transfer
openapi: 3.1.0
info:
  title: CrowdSplit API
  version: 1.0.0
  description: |
    CrowdSplit is a payment-orchestration API that routes payment,
    payout, transfer, buy/sell, KYC, and wallet operations across
    multiple upstream providers (Stripe, Bridge, and others) behind a
    single merchant-facing contract.

    ## Authentication

    Three auth schemes are in use:

    - **`bearerAuth`** — a JWT issued via `POST /api/v1/merchant/token/grant`
      using your `client_id` + `client_secret`. Pass as
      `Authorization: Bearer <token>`. This is the default for every
      merchant-facing operation unless an operation documents otherwise.
    - **`accessTokenAuth`** — user-scoped JWT (obtained via
      `POST /api/auth/signin`) passed in the `x-access-token` header.
      Used for admin/internal operations.
    - **`refAppKeyAuth`** — subscription-service shared key passed in
      the `Ref-App-Key` header, combined with `Payment-Type: recurring_payment`.
      Used only for recurring-payment flows.

    ## Webhooks

    CrowdSplit delivers webhooks as `POST` requests to merchant-registered
    URLs. Every delivery carries the envelope
    `{ id, event, category, data }` and two HTTP headers:

    - `CrowdSplit-Signature` — HMAC-SHA256 over the raw body, formatted
      as `t={unix-ts},v1={hex-hmac}`. Verify with the secret returned at
      webhook registration.
    - `CrowdSplit-Timestamp` — seconds since epoch at dispatch. Reject
      if the skew exceeds 5 minutes.

    Use the envelope's `id` for idempotency — the same `id` is used for
    all retry attempts of a given notification.

    Failed deliveries are retried on a linear schedule controlled by the
    `WEBHOOK_MAXIMUM_RETRY_COUNT` and `WEBHOOK_RETRY_INTERVAL` deployment
    settings. The *n*-th retry is scheduled
    `n × WEBHOOK_RETRY_INTERVAL × 60` seconds after the previous failed
    attempt, and retries stop once `n × WEBHOOK_RETRY_INTERVAL` exceeds
    `WEBHOOK_MAXIMUM_RETRY_COUNT`. Total delivery attempts equal
    `floor(WEBHOOK_MAXIMUM_RETRY_COUNT / WEBHOOK_RETRY_INTERVAL) + 1`.

    With the reference configuration
    (`WEBHOOK_MAXIMUM_RETRY_COUNT=15`, `WEBHOOK_RETRY_INTERVAL=5`) this
    yields **4 total delivery attempts**, with retries scheduled 5, 10,
    and 15 minutes after each preceding failure. After the final attempt
    the notification is left un-acknowledged and no further attempts are
    made.

    ## Pagination

    List endpoints accept `limit` and `offset` query parameters. The
    response envelope is `{ count, <resource>_list }`. Default and
    maximum `limit` values vary per resource; see each endpoint.

    ## Errors

    Every 4xx/5xx response uses the shared `ApiErrorResponse` schema:
    `{ msg, data: null, provider_message? }`. `provider_message` is
    present only when the failure originated from an upstream provider,
    and forwards the provider's own error text verbatim.

    ## Environments

    The `servers` list below describes production, sandbox, and local
    environments. Override the server URL in your client or via the
    generated Postman / Bruno collections.
  contact:
    name: CrowdSplit Engineering
    url: https://github.com/oak-network/crowdsplit
  license:
    name: ISC
servers:
  - url: https://payments.oaknetwork.org
    description: Production
  - url: https://sandbox-payments.oaknetwork.org
    description: Sandbox
  - url: '{baseUrl}'
    description: Local development / self-hosted
    variables:
      baseUrl:
        default: http://localhost:3000
        description: Base URL of a locally running CrowdSplit instance
security:
  - bearerAuth: []
tags:
  - name: Auth
    description: |
      Sign up, sign in, token refresh, password reset, and email
      verification. Obtain user-scoped `accessTokenAuth` JWTs here.
  - name: Merchants
    description: |
      Merchant profile, API-key management, merchant-token grant/refresh,
      and merchant-webhook registration/listing/toggling.
  - name: Customers
    description: |
      Create, update, list, and sync end-customers (subjects).
      Covers customer-level files and balances.
  - name: Payment Methods
    description: |
      Add, list, retrieve, and archive payment methods on a customer
      (card, PIX, bank account, wallet, etc.).
  - name: Provider Registration
    description: |
      KYC / provider-registration flow for a customer on each upstream
      provider, plus fetching the field schema and polling status.
  - name: Payments
    description: |
      Create payments, confirm / capture / cancel / refund. Supports
      card, PIX, and installment payments across providers.
  - name: Payouts
    description: Create outbound fiat payments to customer-owned accounts.
  - name: Transfers
    description: Move value between internal wallets.
  - name: Buy / Sell
    description: Stablecoin / fiat buy and sell flows.
  - name: Wallets
    description: Read wallet balances and trigger wallet trades.
  - name: Transactions
    description: Read transaction history, single transactions, and settle.
  - name: Disputes
    description: |
      Manage provider-originated disputes — upload evidence, submit,
      and close.
  - name: Subscriptions
    description: |
      Subscription plans and subscriber lifecycle, including recurring
      payment initiation (uses `refAppKeyAuth`).
  - name: Tax
    description: Calculate taxes for a given transaction shape.
  - name: Files
    description: Upload, list, retrieve, and delete merchant/customer files.
  - name: Generic
    description: |
      Proxy endpoint that forwards provider-specific calls whose shape
      varies by upstream provider.
  - name: System
    description: Health check and service-metadata endpoints.
  - name: Webhooks
    description: |
      Manage the webhook URLs registered on a merchant (create, update,
      delete, toggle, and list).
  - name: Webhook Events
    description: |
      Reference list of every webhook event CrowdSplit can deliver to a
      merchant URL. See the root-level `Webhooks` section above for the
      envelope shape, delivery headers, retry policy, and signing scheme.
paths:
  /api/v1/transfer:
    post:
      tags:
        - Transfers
      summary: Create a transfer
      description: >
        Initiate a transfer between accounts. Supports single-provider and
        inter-platform transfers.

        Fields provider, currency, payment_method.type are case-insensitive.
      operationId: createTransfer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - source
                - destination
              properties:
                provider:
                  type: string
                  description: Provider for single-provider transfers (case-insensitive)
                source:
                  type: object
                  description: Source account details
                  properties:
                    provider:
                      type: string
                      description: Source provider (for inter-platform transfers)
                    currency:
                      type: string
                    customer:
                      type: object
                      properties:
                        id:
                          type: string
                          format: uuid
                    amount:
                      type: integer
                      minimum: 1
                destination:
                  type: object
                  description: Destination account details
                  properties:
                    provider:
                      type: string
                      description: Destination provider (for inter-platform transfers)
                    customer:
                      type: object
                      properties:
                        id:
                          type: string
                          format: uuid
                    payment_method:
                      type: object
                      properties:
                        type:
                          type: string
                        id:
                          type: string
                          format: uuid
                        currency:
                          type: string
                        chain:
                          type: string
                metadata:
                  type: object
                  description: Custom metadata
                  additionalProperties: true
      responses:
        '200':
          description: Transfer initiated
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ApiResponse'
                  - type: object
                    properties:
                      data:
                        $ref: '#/components/schemas/TransactionResponse'
        '400':
          description: Invalid request or platform error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '422':
          $ref: '#/components/responses/ValidationError'
      security:
        - bearerAuth: []
components:
  schemas:
    ApiResponse:
      type: object
      properties:
        msg:
          type: string
          description: Human-readable message describing the result
        data:
          description: Response payload (null on error)
      required:
        - msg
        - data
    TransactionResponse:
      type: object
      description: >-
        Transaction object (field casing in response is lowercased for status,
        type, provider, currency)
      properties:
        id:
          type: string
          format: uuid
        status:
          type: string
          description: Transaction status (lowercased)
        type:
          type: string
          description: Transaction type (lowercased)
        provider:
          type: string
          description: Provider name (lowercased)
        source:
          type: object
          description: Source details (amount + currency + customer + payment method).
          properties:
            amount:
              type: integer
              description: Amount in minor units (cents).
            currency:
              type: string
              description: ISO 4217 currency code (lowercased).
            customer:
              type: object
              properties:
                id:
                  type: string
                  format: uuid
                  description: Customer (subject) unique ID.
            payment_method:
              type: object
              description: Payment method used on the source leg.
              properties:
                id:
                  type: string
                  format: uuid
                type:
                  type: string
                  description: Payment method type (lowercased).
                chain:
                  type: string
                  description: Blockchain network (lowercased).
              additionalProperties: true
        destination:
          type: object
          description: >-
            Destination details (when applicable — e.g. for transfers, buy/sell,
            refunds).
          nullable: true
          properties:
            amount:
              type: integer
              description: Amount in minor units (cents).
            currency:
              type: string
              description: ISO 4217 currency code (lowercased).
            customer:
              type: object
              properties:
                id:
                  type: string
                  format: uuid
                  description: Destination customer (subject) unique ID.
            payment_method:
              type: object
              description: Payment method used on the destination leg.
              properties:
                id:
                  type: string
                  format: uuid
                type:
                  type: string
                  description: Payment method type (lowercased).
                chain:
                  type: string
                  description: Blockchain network (lowercased).
              additionalProperties: true
        metadata:
          type: object
          nullable: true
          description: |
            Merchant-supplied arbitrary metadata, echoed back unchanged.
            Shape is defined by the merchant at request time.
          additionalProperties: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        settlement_date:
          type:
            - string
            - 'null'
          format: date-time
    ApiErrorResponse:
      type: object
      properties:
        msg:
          type: string
          description: Human-readable error message
        data:
          type: 'null'
          description: Always null for errors
        provider_message:
          type: string
          description: Optional error message from the underlying payment provider
      required:
        - msg
        - data
  responses:
    UnauthorizedError:
      description: Authentication credentials are missing or invalid
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
          example:
            msg: Unauthorized
            data: null
    ForbiddenError:
      description: Authenticated but not authorized for this resource
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
          example:
            msg: Forbidden
            data: null
    NotFoundError:
      description: Requested resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
          example:
            msg: Resource not found
            data: null
    ValidationError:
      description: Request validation failed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
          example:
            msg: Validation error message
            data: null
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >
        Merchant authentication token. Obtained via POST
        /api/v1/merchant/token/grant.

        Pass as: Authorization: Bearer <token>

````