---
url: /docs/fiat/quickstart.md
description: >-
  Accept your first bank transfer and have BlindPay settle it to your customer
  automatically on a development instance.
---

This guide walks through the minimum steps to receive a fiat payment: accept the terms of service, create a customer, give that customer a stablecoin delivery target, quote the payin, and create it. On a development instance the deposit settles automatically about 30 seconds after you create the payin.

## Before you begin

You need a BlindPay account and an API key for a development instance. See [Instances](/learn/instances) and [API keys](/learn/api-keys).

### Accept terms of service

Every instance requires a terms of service acceptance before you can create customers. For testing, you can accept on behalf of the customer; in production, your customer should accept the terms themselves.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/e/instances/in_000000000000/tos \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "idempotency_key": "<your_uuid>"
  }'
```

Open the URL from the response in your browser, accept the terms, and copy the `tos_id` shown on the confirmation screen. You will pass this `tos_id` when you create the customer in the next step.

### Create a customer

Every payment flows through a customer that has completed KYC. This example creates an individual customer with standard KYC.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/customers \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "tos_id": "to_000000000000",
    "type": "individual",
    "kyc_type": "standard",
    "email": "email@example.com",
    "tax_id": "12345678",
    "address_line_1": "8 The Green",
    "address_line_2": "#12345",
    "city": "Dover",
    "state_province_region": "DE",
    "country": "US",
    "postal_code": "02050",
    "ip_address": "127.0.0.1",
    "phone_number": "+13022006100",
    "proof_of_address_doc_type": "UTILITY_BILL",
    "proof_of_address_doc_file": "https://example.com/proof-of-address.jpg",
    "first_name": "John",
    "last_name": "Doe",
    "date_of_birth": "1998-01-01T00:00:00Z",
    "id_doc_country": "US",
    "id_doc_type": "PASSPORT",
    "id_doc_front_file": "https://example.com/passport-front.jpg",
    "selfie_file": "https://example.com/selfie.jpg"
  }'
```

Save the `id` from the response: this is your customer ID (`re_...`).

### Add a blockchain wallet

A payin needs somewhere to deliver the stablecoins once the fiat arrives, so it asks for a wallet ID rather than a bank detail. This example registers an existing wallet on Polygon as the delivery target.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/customers/re_000000000000/blockchain-wallets \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "Wallet Display Name",
    "network": "polygon",
    "address": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C",
    "is_account_abstraction": true
  }'
```

Save the `id` from the response: this is your blockchain wallet ID (`bw_...`).

This wallet is settlement plumbing, not the part you build a UI around. If you would rather hold the balance inside BlindPay instead of pushing it to an external wallet, create a [virtual account](/fiat/virtual-accounts) for the customer and use its `blockchain_wallet_id` as the destination instead. For the full crypto-native mechanics (managed wallets, external wallets, chains, tokens), see [Store: stablecoin flavor](/stablecoin/store).

### Create a payin quote

A payin quote locks in how much fiat the sender sends and how much the customer receives before you create the payin. This example quotes an ACH payin with the sender covering the fee, so `request_amount` is the amount the sender sends.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/payin-quotes \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "blockchain_wallet_id": "bw_000000000000",
    "currency_type": "sender",
    "cover_fees": true,
    "request_amount": 10000,
    "payment_method": "ach",
    "token": "USDC"
  }'
```

`request_amount` is an integer in minor units, so `10000` here means $100.00. Save the `id` from the response: this is your payin quote ID (`pq_...`). You have 5 minutes to create the payin before the quote expires.

### Create the payin

Create the payin from the quote ID. This is what generates the bank details your end user pays into.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/payins/evm \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "payin_quote_id": "pq_000000000000"
  }'
```

The response includes `memo_code` and `blindpay_bank_details`. Share these with the end user so they know where to send the ACH transfer and how to reference it.

```json [Response]
{
  // ...
  "memo_code": "12345678",
  "blindpay_bank_details": {
    "routing_number": "121145349",
    "account_number": "621327727210181",
    "account_type": "Business checking",
    "beneficiary": {
      "name": "BlindPay, Inc.",
      "address_line_1": "8 The Green, #19364",
      "address_line_2": "Dover, DE 19901"
    },
    "receiving_bank": {
      "name": "Example Bank, N.A.",
      "address_line_1": "1 Example Plaza",
      "address_line_2": "San Francisco, CA 94129"
    }
  }
  // ...
}
```

## What happens next

On a development instance, the payin settles automatically about 30 seconds after you create it. Check for the `payin.complete` webhook to confirm. In production, BlindPay waits up to 5 business days for an ACH or wire deposit to arrive before cancelling the payin if nothing shows up.

## Related

* [Bank transfer in](/fiat/receive): full reference for every payment method, including Pix, SPEI, and PSE
* [Virtual accounts](/fiat/virtual-accounts): a dedicated deposit account whose deposits settle to the linked wallet
* [Pay out to bank](/fiat/send): send funds back out to a bank account
* [Webhooks](/learn/webhooks): handle payin and customer events in real time
