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

# Legacy: Create an offramp

> Legacy route for creating a crypto receive flow

## Overview

Create an offramp through the legacy compatibility route. New integrations should use [`POST /v1/funding-accounts`](/api-reference/funding-accounts/create-funding-account) with `rail: CRYPTO_ADDRESS`, `asset`, and `chain`.

## Authentication

<ParamField header="X-Api-Key" type="string" required>
  Your merchant API key
</ParamField>

<ParamField header="X-Idempotency-Key" type="string" required>
  Unique idempotency key to prevent duplicate offramp creation
</ParamField>

## Request Body

<ParamField body="type" type="string" required>
  Offramp type

  **Allowed values:** `TEMPORARY`, `PERMANENT`

  * `TEMPORARY`: Short-lived deposit address, locked to `rate_id`. Must use `NGN_PAYOUT` settlement.
  * `PERMANENT`: Long-lived deposit address, uses current rate at settlement. Supports both `INTERNAL_BALANCE` and `NGN_PAYOUT` settlement.
</ParamField>

<ParamField body="customer" type="object" required>
  Customer information. Either `customer_id` or `email` must be provided.

  <Expandable title="customer properties">
    <ParamField body="customer.customer_id" type="string">
      UUID of an existing customer. Either this or `customer.email` is required.

      **Example:** `650e8400-e29b-41d4-a716-446655440000`
    </ParamField>

    <ParamField body="customer.email" type="string">
      Email for auto-creating a customer. Either this or `customer.customer_id` is required.

      **Example:** `user@example.com`
    </ParamField>

    <ParamField body="customer.first_name" type="string">
      Customer first name
    </ParamField>

    <ParamField body="customer.last_name" type="string">
      Customer last name
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="chain" type="string" required>
  Blockchain network for the deposit address

  **Allowed values:** `APTOS`, `BASE`, `CELO`, `ETHEREUM`, `POLYGON`, `SOLANA`, `TRON`

  See [Supported Chains](/concepts/supported-chains) for details on which assets are available on each chain.
</ParamField>

<ParamField body="asset" type="string" required>
  Stablecoin asset to receive

  **Allowed values:** `USDC`, `USDT`
</ParamField>

<ParamField body="developer_fee" type="object">
  Optional fee that your merchant account keeps from each offramp deposit. Omit to use `0%`.

  <Expandable title="developer_fee properties">
    <ParamField body="developer_fee.percentage" type="string" required>
      Percentage of each received deposit that your merchant account keeps. Use a decimal string from `0` to `50`. This is a percentage value, not basis points: `0.5` means `0.5%`, `2` means `2%`, and `50` means `50%`.

      **Example:** `"2.5"`
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="settlement" type="object" required>
  Settlement configuration

  <Expandable title="settlement properties">
    <ParamField body="settlement.mode" type="string" required>
      Settlement mode

      **Allowed values:**

      * `INTERNAL_BALANCE` - Credit merchant USD balance (only valid when `type` is `PERMANENT`)
      * `NGN_PAYOUT` - Settle as NGN to a bank account
    </ParamField>

    <ParamField body="settlement.rate_id" type="string">
      Rate identifier from `GET /v1/rates`

      **Example:** `rate_8x7k2mq9p`

      <Note>
        **Required** for `NGN_PAYOUT` mode. Not used for `INTERNAL_BALANCE`.
      </Note>
    </ParamField>

    <ParamField body="settlement.destination_bank" type="object">
      Bank account for NGN payout. Required for `NGN_PAYOUT` mode.

      <Expandable title="destination_bank properties">
        <ParamField body="settlement.destination_bank.account_name" type="string" required>
          Bank account holder name

          **Example:** `John Doe`
        </ParamField>

        <ParamField body="settlement.destination_bank.account_number" type="string" required>
          Bank account number (6-32 characters)

          **Example:** `0123456789`
        </ParamField>

        <ParamField body="settlement.destination_bank.bank_code" type="string" required>
          Bank code (3-16 characters)

          **Example:** `058`
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

## Request Examples

<CodeGroup>
  ```json Temporary - NGN Payout theme={null}
  {
    "type": "TEMPORARY",
    "customer": {
      "customer_id": "650e8400-e29b-41d4-a716-446655440000"
    },
    "chain": "BASE",
    "asset": "USDC",
    "developer_fee": {
      "percentage": "2.5"
    },
    "settlement": {
      "mode": "NGN_PAYOUT",
      "rate_id": "rate_8x7k2mq9p",
      "destination_bank": {
        "account_name": "John Doe",
        "account_number": "0123456789",
        "bank_code": "058"
      }
    }
  }
  ```

  ```json Permanent - Internal Balance theme={null}
  {
    "type": "PERMANENT",
    "customer": {
      "email": "user@example.com",
      "first_name": "John",
      "last_name": "Doe"
    },
    "chain": "SOLANA",
    "asset": "USDT",
    "settlement": {
      "mode": "INTERNAL_BALANCE"
    }
  }
  ```

  ```json Permanent - NGN Payout theme={null}
  {
    "type": "PERMANENT",
    "customer": {
      "customer_id": "650e8400-e29b-41d4-a716-446655440000"
    },
    "chain": "TRON",
    "asset": "USDT",
    "settlement": {
      "mode": "NGN_PAYOUT",
      "rate_id": "rate_8x7k2mq9p",
      "destination_bank": {
        "account_name": "John Doe",
        "account_number": "0123456789",
        "bank_code": "058"
      }
    }
  }
  ```

  ```bash cURL - Permanent with NGN Payout theme={null}
  curl --request POST \
    --url https://api.daya.co/v1/offramps \
    --header 'X-Api-Key: YOUR_API_KEY' \
    --header 'X-Idempotency-Key: unique-key-456' \
    --header 'Content-Type: application/json' \
    --data '{
      "type": "PERMANENT",
      "customer": {
        "customer_id": "650e8400-e29b-41d4-a716-446655440000"
      },
      "chain": "TRON",
      "asset": "USDT",
      "settlement": {
        "mode": "NGN_PAYOUT",
        "rate_id": "rate_8x7k2mq9p",
        "destination_bank": {
          "account_name": "John Doe",
          "account_number": "0123456789",
          "bank_code": "058"
        }
      }
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.daya.co/v1/offramps', {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_API_KEY',
      'X-Idempotency-Key': 'unique-key-123',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      type: 'PERMANENT',
      customer: {
        email: 'user@example.com'
      },
      chain: 'ETHEREUM',
      asset: 'USDC',
      settlement: {
        mode: 'INTERNAL_BALANCE'
      }
    })
  });
  const offramp = await response.json();
  ```
</CodeGroup>

## Response

<ResponseField name="id" type="string" required>
  Unique offramp identifier (UUID)
</ResponseField>

<ResponseField name="type" type="string" required>
  Offramp type: `TEMPORARY` or `PERMANENT`
</ResponseField>

<ResponseField name="customer_id" type="string" required>
  Associated customer ID (UUID)
</ResponseField>

<ResponseField name="address" type="string" required>
  Generated crypto deposit address
</ResponseField>

<ResponseField name="chain" type="string" required>
  Blockchain network: `APTOS`, `BASE`, `CELO`, `ETHEREUM`, `POLYGON`, `SOLANA`, or `TRON`
</ResponseField>

<ResponseField name="asset" type="string" required>
  Stablecoin asset: `USDC` or `USDT`
</ResponseField>

<ResponseField name="status" type="string" required>
  Current offramp status. New offramps start as `ACTIVE`.
</ResponseField>

<ResponseField name="developer_fee" type="object" required>
  Developer fee percentage used for deposits received through this offramp.

  <Expandable title="developer_fee properties">
    <ResponseField name="developer_fee.percentage" type="string">
      Configured percentage as a decimal string.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="settlement" type="object" required>
  Settlement configuration

  <Expandable title="settlement properties">
    <ResponseField name="settlement.mode" type="string">
      Settlement mode: `INTERNAL_BALANCE` or `NGN_PAYOUT`
    </ResponseField>

    <ResponseField name="settlement.rate_id" type="string">
      Associated rate identifier (nullable, present for `NGN_PAYOUT`)
    </ResponseField>

    <ResponseField name="settlement.destination_bank" type="object">
      Bank account details (present for `NGN_PAYOUT`)

      <Expandable title="destination_bank properties">
        <ResponseField name="settlement.destination_bank.account_name" type="string">
          Bank account holder name
        </ResponseField>

        <ResponseField name="settlement.destination_bank.account_number" type="string">
          Bank account number
        </ResponseField>

        <ResponseField name="settlement.destination_bank.bank_code" type="string">
          Bank code
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="created_at" type="string" required>
  When the offramp was created (ISO 8601 timestamp)
</ResponseField>

<ResponseField name="updated_at" type="string" required>
  When the offramp was last updated (ISO 8601 timestamp)
</ResponseField>

### Success Responses

<ResponseExample>
  ```json 201 Created - Internal Balance theme={null}
  {
    "id": "a50e8400-e29b-41d4-a716-446655440000",
    "type": "PERMANENT",
    "customer_id": "650e8400-e29b-41d4-a716-446655440000",
    "address": "0x1a2b3c4d5e6f7890abcdef1234567890abcdef12",
    "chain": "ETHEREUM",
    "asset": "USDC",
    "status": "ACTIVE",
    "developer_fee": {
      "percentage": "2.5"
    },
    "settlement": {
      "mode": "INTERNAL_BALANCE",
      "rate_id": null,
      "destination_bank": null
    },
    "created_at": "2026-01-05T15:04:05Z",
    "updated_at": "2026-01-05T15:04:05Z"
  }
  ```

  ```json 201 Created - NGN Payout theme={null}
  {
    "id": "b60e8400-e29b-41d4-a716-446655440000",
    "type": "PERMANENT",
    "customer_id": "650e8400-e29b-41d4-a716-446655440000",
    "address": "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9",
    "chain": "TRON",
    "asset": "USDT",
    "status": "ACTIVE",
    "settlement": {
      "mode": "NGN_PAYOUT",
      "rate_id": "rate_8x7k2mq9p",
      "destination_bank": {
        "account_name": "John Doe",
        "account_number": "0123456789",
        "bank_code": "058"
      }
    },
    "created_at": "2026-01-05T15:04:05Z",
    "updated_at": "2026-01-05T15:04:05Z"
  }
  ```
</ResponseExample>

## Error Responses

<ResponseExample>
  ```json 400 Bad Request - Missing customer theme={null}
  {
    "error": {
      "code": "VALIDATION_FAILED",
      "message": "either customer.customer_id or customer.email is required",
      "request_id": "550e8400-e29b-41d4-a716-446655440000",
      "validation": "customer.customer_id or customer.email is required"
    }
  }
  ```

  ```json 400 Bad Request - Invalid chain theme={null}
  {
    "error": {
      "code": "VALIDATION_FAILED",
      "message": "Validation failed",
      "request_id": "550e8400-e29b-41d4-a716-446655440000",
      "validation": "chain must be one of APTOS, BASE, CELO, ETHEREUM, POLYGON, SOLANA, TRON"
    }
  }
  ```

  ```json 400 Bad Request - Missing rate for NGN payout theme={null}
  {
    "error": {
      "code": "VALIDATION_FAILED",
      "message": "Validation failed",
      "request_id": "550e8400-e29b-41d4-a716-446655440000",
      "validation": "rate_id is required for NGN_PAYOUT settlement mode"
    }
  }
  ```

  ```json 400 Bad Request - Rate expired theme={null}
  {
    "error": {
      "code": "RATE_EXPIRED",
      "message": "The specified rate_id has expired. Request a new rate via GET /v1/rates",
      "request_id": "550e8400-e29b-41d4-a716-446655440000"
    }
  }
  ```

  ```json 400 Bad Request - Invalid bank details theme={null}
  {
    "error": {
      "code": "VALIDATION_FAILED",
      "message": "Validation failed",
      "request_id": "550e8400-e29b-41d4-a716-446655440000",
      "validation": "destination_bank is required for NGN_PAYOUT settlement mode"
    }
  }
  ```

  ```json 400 Bad Request - Invalid account number theme={null}
  {
    "error": {
      "code": "VALIDATION_FAILED",
      "message": "Validation failed",
      "request_id": "550e8400-e29b-41d4-a716-446655440000",
      "validation": "account_number must be between 6 and 32 characters"
    }
  }
  ```

  ```json 401 Unauthorized theme={null}
  {
    "error": {
      "code": "UNAUTHORIZED",
      "message": "Unauthorized",
      "request_id": "550e8400-e29b-41d4-a716-446655440000"
    }
  }
  ```

  ```json 429 Too Many Requests theme={null}
  {
    "error": {
      "code": "RATE_LIMITED",
      "message": "Merchant has exceeded daily offramp creation limit",
      "request_id": "550e8400-e29b-41d4-a716-446655440000"
    }
  }
  ```
</ResponseExample>

## Validation Rules

<AccordionGroup>
  <Accordion title="Customer identification">
    Either `customer.customer_id` or `customer.email` must be provided (not both optional, at least one required).
  </Accordion>

  <Accordion title="Temporary offramp rules">
    * Generates a short-lived crypto deposit address
    * Settlement mode **must** be `NGN_PAYOUT` — `INTERNAL_BALANCE` is not supported on temporary offramps
    * `settlement.rate_id` and `settlement.destination_bank` are required
  </Accordion>

  <Accordion title="Permanent offramp rules">
    * Generates a long-lived crypto deposit address
    * Uses the current rate at the time of deposit settlement
    * Supports both `INTERNAL_BALANCE` and `NGN_PAYOUT` settlement modes
    * For `NGN_PAYOUT`: `settlement.rate_id` and `settlement.destination_bank` are required
    * For `INTERNAL_BALANCE`: `settlement.rate_id` and `settlement.destination_bank` must NOT be set
  </Accordion>

  <Accordion title="NGN payout bank details">
    When `settlement.mode` is `NGN_PAYOUT`:

    * `destination_bank.account_name` is required
    * `destination_bank.account_number` must be 6-32 characters
    * `destination_bank.bank_code` must be 3-16 characters

    <Warning>
      Always resolve the bank account first using [`POST /v1/banks/resolve`](/api-reference/banks/resolve-bank-account) before creating the offramp. Invalid bank accounts will be rejected.
    </Warning>
  </Accordion>
</AccordionGroup>

## Best Practices

<Steps>
  <Step title="Resolve bank account before creation (NGN payout)">
    Always call [`POST /v1/banks/resolve`](/api-reference/banks/resolve-bank-account) to verify the account number and get the account holder's name before creating an offramp with `NGN_PAYOUT`. Invalid accounts will be rejected.
  </Step>

  <Step title="Get fresh rate before creation (NGN payout)">
    Call `GET /v1/rates?side=SELL` immediately before creating an offramp with `NGN_PAYOUT` to ensure maximum validity window.
  </Step>

  <Step title="Use customer_id for returning customers">
    Create customers once via `POST /v1/customers`, then reference them by `customer_id` in subsequent offramp requests.
  </Step>

  <Step title="Use idempotency keys">
    Always include a unique `X-Idempotency-Key` header to prevent duplicate offramp creation on retries.
  </Step>

  <Step title="Choose the right chain">
    Consider transaction fees and confirmation times when selecting a chain. See [Supported Chains](/concepts/supported-chains) for details.
  </Step>
</Steps>

## Next Steps

<CardGroup cols={2}>
  <Card title="List Offramps" icon="list" href="/api-reference/offramps/list-offramps">
    Query offramps with filters
  </Card>

  <Card title="Get Rates" icon="chart-line" href="/api-reference/rates/get-rates">
    Fetch current exchange rates before creating an offramp
  </Card>

  <Card title="Customer API" icon="users" href="/api-reference/customers/create-customer">
    Pre-create customers before offramp requests
  </Card>

  <Card title="Webhooks" icon="bell" href="/api-reference/webhooks/overview">
    Listen for deposit and settlement events
  </Card>
</CardGroup>
