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

# EUR virtual accounts (Eurozone)

> Issue EUR bank details for your customers and receive payments by SEPA.

| | |
| - | - |
| Country | Eurozone |
| Payment rail | SEPA |
| Account types | dedicated |
| Customers | Individuals and businesses |
| When it is ready | The customer verifies first, then the account goes through an extra review, so it can show `pending` for a while after verification. |

## 1. Check availability

Ask what EUR needs for your account. The answer lists the required fields per customer type and account type.

```bash theme={null}
curl "https://pay-api.pagoramp.com/api/v1/virtual-accounts/availability?currency=EUR" \
  -H "x-api-key: YOUR_API_KEY"
```

## 2. Create the customer

Required for an individual: `firstname`, `lastname`, `email`. See [Virtual account requirements](https://dev-docs.pagoramp.com/virtual-accounts-requirements#eur) for every combination.

```bash theme={null}
curl -X POST https://pay-api.pagoramp.com/api/v1/customers \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"firstname":"Ada","lastname":"Okafor","email":"ada@example.com"}'
```

The customer is created with `kycStatus` `incomplete` or `pending`. Anything missing for EUR can be added later with `PATCH /customers/{uuid}` before you request the account.

## 3. Request the account

```bash theme={null}
curl -X POST https://pay-api.pagoramp.com/api/v1/virtual-accounts \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"customerId":"224ca5c5-f2a6-419b-bf36-73997434d945","currency":"EUR","type":"dedicated","reference":"va_1001","redirectUrl":"https://app.example.com/verification-complete"}'
```

You must have a webhook secret set up first, or the request returns `400` with `webhook_secret_required`.

The response depends on the currency. For EUR, expect `requires_action` then `pending` then `active`:

**`requires_action`**: The customer has to verify first. Send them `nextStep.url`.

```json theme={null}
{
  "status": "success",
  "message": "Virtual account created successfully",
  "data": {
    "uuid": "9a1c1c52-7b8e-4a52-9f0e-3e6b0a8d6c11",
    "reference": "va_1001",
    "status": "requires_action",
    "currency": "EUR",
    "type": "dedicated",
    "bankDetails": null,
    "customer": {
      "uuid": "224ca5c5-f2a6-419b-bf36-73997434d945",
      "email": "ada@example.com"
    },
    "expectedAmount": null,
    "expiresAt": null,
    "nextStep": {
      "type": "verification_link",
      "url": "https://verify.example.com/abc"
    },
    "statusReason": null,
    "metadata": {
      "orderId": "12345"
    },
    "createdAt": "2026-10-16T09:31:00.000Z"
  }
}
```

**`pending`**: The account is still being issued or approved. Wait for `virtual_account.created`.

```json theme={null}
{
  "status": "success",
  "message": "Virtual account created successfully",
  "data": {
    "uuid": "9a1c1c52-7b8e-4a52-9f0e-3e6b0a8d6c11",
    "reference": "va_1001",
    "status": "pending",
    "currency": "EUR",
    "type": "dedicated",
    "bankDetails": null,
    "customer": {
      "uuid": "224ca5c5-f2a6-419b-bf36-73997434d945",
      "email": "ada@example.com"
    },
    "expectedAmount": null,
    "expiresAt": null,
    "nextStep": null,
    "statusReason": null,
    "metadata": {
      "orderId": "12345"
    },
    "createdAt": "2026-10-16T09:31:00.000Z"
  }
}
```

**`active`**: Ready. Show the bank details to your payer.

```json theme={null}
{
  "status": "success",
  "message": "Virtual account created successfully",
  "data": {
    "uuid": "9a1c1c52-7b8e-4a52-9f0e-3e6b0a8d6c11",
    "reference": "va_1001",
    "status": "active",
    "currency": "EUR",
    "type": "dedicated",
    "bankDetails": {
      "rail": "sepa",
      "accountName": "Acme Pay",
      "iban": "LU784080000026699429",
      "bic": "BCIRLULL",
      "bankName": "Banking Circle S.A.",
      "extra": {
        "beneficiaryAddress": "100 Test Street, San Francisco 94105, US",
        "paymentRails": [
          "sepa"
        ]
      }
    },
    "customer": {
      "uuid": "224ca5c5-f2a6-419b-bf36-73997434d945",
      "email": "ada@example.com"
    },
    "expectedAmount": null,
    "expiresAt": null,
    "nextStep": null,
    "statusReason": null,
    "metadata": {
      "orderId": "12345"
    },
    "createdAt": "2026-10-16T09:31:00.000Z"
  }
}
```

If the request is rejected straight away you get `422` with the reason in `errors[0].reason` and no account is created. If it is rejected later you receive `virtual_account.failed` with a `reason`. See [Webhooks](https://dev-docs.pagoramp.com/webhooks#account-status-events).

## 4. Show the details to your payer

Show these fields from `bankDetails`:

| Label | Field |
| - | - |
| Account holder | `accountName` |
| IBAN | `iban` |
| BIC | `bic` |
| Bank | `bankName` |

How your payer sends the money:

1. Add the IBAN as a beneficiary in their bank.
2. Send a SEPA transfer in euro.

## 5. Receive the payment

When the payment arrives you receive `virtual_account.payment.received`. Amounts are decimal strings in EUR; `destinationAmount` is in USD, after any fees.

```json theme={null}
{
  "event": "virtual_account.payment.received",
  "data": {
    "transaction": {
      "reference": "va-17912345678901234",
      "status": "Success",
      "sourceAmount": "200.00",
      "sourceCurrency": "EUR",
      "destinationAmount": "231.40",
      "destinationCurrency": "USD",
      "fees": {
        "sourceTotalFee": "0.00"
      }
    },
    "virtualAccount": {
      "uuid": "9a1c1c52-7b8e-4a52-9f0e-3e6b0a8d6c11",
      "reference": "va_1001",
      "currency": "EUR",
      "type": "dedicated"
    },
    "customer": {
      "uuid": "224ca5c5-f2a6-419b-bf36-73997434d945",
      "email": "ada@example.com",
      "externalReference": null
    },
    "sender": {
      "name": "ADA OKAFOR",
      "bank": "Deutsche Bank",
      "accountNumber": "******6789"
    },
    "occurredAt": "2026-10-16T10:02:00.000Z"
  }
}
```

Verify the signature before you trust it, and use `data.transaction.reference` to ignore repeats. See [Webhooks](https://dev-docs.pagoramp.com/webhooks).

## Things to handle

* EUR needs extra approval for the customer, on top of the identity check. The create call returns a verification link for it. Business customers are asked for more detail about the business.
* Payments are converted to USD when they arrive, at the rate in force at that moment. `destinationAmount` is what you are settled.
* A payment can be held for review. You receive `virtual_account.payment.manual_review` with a `review.reason`, then `received` or `rejected` after a decision.
* `GET /virtual-accounts/{uuid}` returns the current status at any time, and `POST /virtual-accounts/{uuid}/deactivate` stops the account accepting payments.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.