# Crypto-to-fiat Payments

Crypto-to-fiat payments allow a Payer to pay a Request in cryptocurrency, while the Payee receives fiat currency directly in their bank account. This is achieved by combining the Request Network crypto payment with [Request Tech](https://www.request.finance/tech) offramp infrastructure. This requires prerequisite compliance (KYC/Agreement) and bank account registration (payment detail) flows.

[EasyInvoice](https://docs.request.network/request-network-api/easyinvoice-api-demo-app) includes a reference implementation for this flow.

{% hint style="info" %}
Crypto-to-fiat payments are only available in version 2 of the Request Network API.
{% endhint %}

## Getting Started with Crypto-to-fiat Payments

### Sandbox Access - Get Started Today

All developers can immediately access the **Crypto-to-fiat Sandbox** to build and test their integration:

1. **Create an account** on the [Request Network API Portal](https://portal.request.network/)
2. **Generate a Sandbox API key** with crypto-to-fiat sandbox access
3. **Start building** with Sepolia testnet USDC, simulated KYC, and mock bank accounts

The sandbox provides a complete testing environment where you can:

* Test the full crypto-to-fiat flow without real funds
* Simulate payer KYC verification using [mock documents](https://docs.sumsub.com/docs/verification-document-templates)
* Work with mock bank account data and fiat payment status

{% hint style="warning" %}
I**mportant: Other Payment Types Use Real Funds**

The "Crypto-to-fiat Sandbox" setting for API keys only affects crypto-to-fiat payments. Other payment types can process *real* funds with any API key, even Sandbox API keys.
{% endhint %}

### Production Access - Launch When Ready

When you're ready to go live with real transactions:

1. [**Get in touch**](https://2deywy.share-eu1.hsforms.com/2b92phs9LR_eJdeZoxzmoMA?utm_source=request.network\&utm_medium=docs\&utm_campaign=evergreen\&utm_content=get_in_touch) to request production access
2. **Discuss your use case** with our team to ensure the best integration approach
3. **Complete the approval process** - we'll work with you to get everything set up
4. **Generate Production API keys** once approved

Production access includes:

* Real USDC transactions on mainnet
* Actual KYC verification for payers
* Live bank account validation
* Fiat deposits to real bank accounts

### Crypto-to-fiat Supported Chains and Currencies

For Crypto-to-fiat Payments, the Request Network API supports USDC on Ethereum, Polygon, Arbitrum One, and Sepolia.

{% hint style="info" %}
**Crypto-to-fiat Payment with non-USDC currencies:**

While crypto-to-fiat requests must be created in USDC, users can pay in alternative currencies through a four-step process, using [crosschain-payments](https://docs.request.network/request-network-api/crosschain-payments "mention"):

1. **Create Crosschain Request**: Create a request to swap the payer's currency (e.g., ETH on Ethereum) to USDC on the target chain (e.g., USDC on Polygon). Note: Don't specify a payer address during request creation to allow flexibility in who can pay.
2. **Pay Crosschain Request**: Execute the crosschain payment to fulfill the first request
3. **Create Crypto-to-Fiat Request**: Create a separate request for the USDC offramp to fiat and bank deposit
4. **Pay Crypto-to-Fiat Request**: Execute the crypto-to-fiat payment to complete the flow

This four-step approach is required due to current API limitations - more streamlined flows are not yet implemented.
{% endhint %}

## Understanding `clientUserId`

Many `/payer` endpoints in the Request Network API require a `clientUserId` as a path parameter. This value is an **arbitrary identifier** chosen by your platform to represent a user (the payer) in your own system.

* **You control the format:** The `clientUserId` can be any unique string that makes sense for your application. It can be a UUID, email address, database ID, or anything unique per user on your platform.
* **EasyInvoice Example:** In the EasyInvoice demo app, `clientUserId` is set to the user's email address.
* **Why is this useful?** This approach allows you to integrate the Request Network API without having to change your existing user management logic. You simply pass your own identifier to the API, and all payer-related compliance, agreement, and payment detail records will be associated with that value.

**Example usage:**

```
GET /v2/payer/{clientUserId}
PATCH /v2/payer/{clientUserId}
POST /v2/payer/{clientUserId}/payment-details
GET  /v2/payer/{clientUserId}/payment-details
```

In each case, replace `{clientUserId}` with your chosen identifier for the user.

## Compliance & Payer Onboarding

Before a payer can use crypto-to-fiat, they must complete compliance steps:

* **KYC**: The payer must submit a KYC application.
* **Agreement**: The payer must sign a compliance agreement (via an iframe flow).
* **Bank Account**: The payee's bank account must be associated with a payer for compliance reasons, even though the payee owns the account.

### **Compliance Flow Diagram**

{% @mermaid/diagram content="---
config:
fontSize: 10
sequence:
wrap: true
actorMargin: 90
width: 100
height: 30
----------

sequenceDiagram
participant Payer
participant Platform
participant RequestAPI
participant RequestTech

```
Payer->>Platform: Submit KYC data via KYC Form
Platform->>RequestAPI: POST /payer (KYC data)
RequestAPI->>RequestTech: Forward KYC
RequestTech-->>RequestAPI: KYC status update (webhook)
Note over Platform: Wait for KYC "approved"
RequestAPI-->>Platform: webhook: compliance.updated (kycStatus: pending/approved/rejected/failed)
Platform->>Payer: Show iframe for agreement signature
Payer->>Platform: Completes signature
Platform->>RequestAPI: PATCH /payer/{payerId} (agreement_status: completed)
RequestAPI-->>Platform: webhook: compliance.updated (agreementStatus: completed)" %}
```

### **Flow Explanation**

1. **Submit KYC**: The platform collects KYC information from the payer and submits it to the API.
2. **KYC Review**: The platform receives webhook updates as the KYC is processed (`compliance.updated` with `kycStatus`).
3. **Agreement Signature**: The platform displays an iframe for the payer to sign the compliance agreement. Once signed, the platform calls the API to update the agreement status.
4. **Agreement Confirmation**: The platform receives a webhook update when the agreement is completed (`compliance.updated` with `agreementStatus`).

### Relevant Endpoints

* `POST /payer`: Submit KYC application.
* `GET /payer/{clientUserId}`: Get compliance status for a payer.
* `PATCH /payer/{clientUserId}`: Update agreement status after signature.

## Create compliance data for a user

> Checks compliance status and returns necessary URLs for completing compliance.

```json
{"openapi":"3.0.0","info":{"title":"Request Network API","version":"0.18.1"},"tags":[{"name":"V2/Payer","description":"Crypto-to-fiat payer management operations (V2)"}],"servers":[{"url":"https://api.request.network","description":"Production server"},{"url":"https://api.stage.request.network","description":"Staging server"},{"url":"http://127.0.0.1:8080","description":"Local development server"}],"paths":{"/v2/payer":{"post":{"description":"Checks compliance status and returns necessary URLs for completing compliance.","operationId":"PayerV2Controller_getComplianceData_v2","parameters":[{"name":"x-api-key","in":"header","description":"API key for authentication","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"clientUserId":{"type":"string","minLength":1,"description":"Client User ID"},"email":{"type":"string","format":"email","description":"Email"},"firstName":{"type":"string","minLength":1,"description":"First Name"},"lastName":{"type":"string","minLength":1,"description":"Last Name"},"beneficiaryType":{"type":"string","enum":["individual","business"]},"companyName":{"type":"string","description":"Company Name"},"dateOfBirth":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Date of birth in YYYY-MM-DD format"},"addressLine1":{"type":"string","minLength":1,"description":"Address Line 1"},"addressLine2":{"type":"string","description":"Address Line 2"},"city":{"type":"string","minLength":1,"description":"City"},"state":{"type":"string","minLength":1,"description":"State"},"postcode":{"type":"string","minLength":1,"description":"Postcode"},"country":{"type":"string","minLength":2,"maxLength":2,"description":"Country"},"nationality":{"type":"string","minLength":2,"maxLength":2,"description":"Nationality"},"phone":{"type":"string","pattern":"^\\+?[1-9]\\d{1,14}$","description":"Phone in E.164 format"},"ssn":{"type":"string","minLength":1,"description":"Social Security Number"},"sourceOfFunds":{"type":"string","description":"Source of Funds"},"businessActivity":{"type":"string","description":"Business Activity"}},"required":["clientUserId","email","firstName","lastName","beneficiaryType","dateOfBirth","addressLine1","city","state","postcode","country","nationality","phone","ssn"]}}}},"responses":{"200":{"description":"Compliance data retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"agreementUrl":{"type":"string","format":"uri"},"kycUrl":{"type":"string","format":"uri"},"status":{"type":"object","properties":{"agreementStatus":{"type":"string","enum":["not_started","completed"]},"kycStatus":{"type":"string","enum":["not_started","completed"]}},"required":["agreementStatus","kycStatus"]},"userId":{"type":"string","format":"uuid"}},"required":["status"]}}}},"400":{"description":"Invalid request data","content":{"application/json":{"schema":{"properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Request not found","content":{"application/json":{"schema":{"properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}}}}}},"429":{"description":"Too Many Requests"}},"summary":"Create compliance data for a user","tags":["Payer","V2/Payer"]}}}}
```

## Get compliance status for a user

> Retrieves the comprehensive compliance status for a specific user, including KYC and agreement status.

```json
{"openapi":"3.0.0","info":{"title":"Request Network API","version":"0.18.1"},"tags":[{"name":"V2/Payer","description":"Crypto-to-fiat payer management operations (V2)"}],"servers":[{"url":"https://api.request.network","description":"Production server"},{"url":"https://api.stage.request.network","description":"Staging server"},{"url":"http://127.0.0.1:8080","description":"Local development server"}],"paths":{"/v2/payer/{clientUserId}":{"get":{"description":"Retrieves the comprehensive compliance status for a specific user, including KYC and agreement status.","operationId":"PayerV2Controller_getComplianceStatus_v2","parameters":[{"name":"clientUserId","required":true,"in":"path","description":"The client user ID to check compliance status for","schema":{"type":"string"}},{"name":"x-api-key","in":"header","description":"API key for authentication","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Compliance status retrieved successfully","content":{"application/json":{"schema":{"properties":{"kycStatus":{"type":"string"},"agreementStatus":{"type":"string"},"isCompliant":{"type":"boolean"},"userId":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"User not found","content":{"application/json":{"schema":{"properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}}}}}},"429":{"description":"Too Many Requests"}},"summary":"Get compliance status for a user","tags":["Payer","V2/Payer"]}}}}
```

## Update agreement status

> Update the agreement completion status for a user.

```json
{"openapi":"3.0.0","info":{"title":"Request Network API","version":"0.18.1"},"tags":[{"name":"V2/Payer","description":"Crypto-to-fiat payer management operations (V2)"}],"servers":[{"url":"https://api.request.network","description":"Production server"},{"url":"https://api.stage.request.network","description":"Staging server"},{"url":"http://127.0.0.1:8080","description":"Local development server"}],"paths":{"/v2/payer/{clientUserId}":{"patch":{"description":"Update the agreement completion status for a user.","operationId":"PayerV2Controller_updateComplianceStatus_v2","parameters":[{"name":"clientUserId","required":true,"in":"path","description":"The client user ID to update","schema":{"type":"string"}},{"name":"x-api-key","in":"header","description":"API key for authentication","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"agreementCompleted":{"type":"boolean"}},"required":["agreementCompleted"]}}}},"responses":{"200":{"description":"Compliance status updated successfully","content":{"application/json":{"schema":{"properties":{"success":{"type":"boolean"}}}}}},"400":{"description":"Invalid request data","content":{"application/json":{"schema":{"properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"User not found","content":{"application/json":{"schema":{"properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}}}}}},"429":{"description":"Too Many Requests"}},"summary":"Update agreement status","tags":["Payer","V2/Payer"]}}}}
```

## Setting Up a Crypto-to-Fiat Request (Payee Flow)

Before a payer can pay in crypto and the payee can receive fiat, the platform must:

* **Submit the payee’s bank account details** (associated with a payer for compliance).
* **Wait for approval** of those payment details (usually less than 60 seconds, confirmed via webhook).
* **Create a new request** with `isCryptoToFiatAllowed = true`.

### **Payment Details Flow Diagram**

{% @mermaid/diagram content="---
config:
fontSize: 10
sequence:
wrap: true
actorMargin: 90
width: 100
height: 30
----------

sequenceDiagram
participant Payee
participant Platform
participant RequestAPI
participant RequestTech

```
Payee->>Platform: Submit bank info via Bank Account Form
Platform->>RequestAPI: POST /payer/{payerId}/payment-details (bank info)
RequestAPI->>RequestTech: Forward payment details
RequestTech-->>RequestAPI: payment_detail_update (webhook)
Note over Platform: Wait for payment detail "approved"
RequestAPI-->>Platform: webhook event: payment_detail.updated (status: approved/failed/pending)
Platform->>RequestAPI: POST /request (isCryptoToFiatAllowed = true)
RequestAPI-->>Platform: Request created" fullWidth="false" %}
```

### **Flow Explanation**

1. **Submit Bank Account**: The platform submits the payee’s bank account details, associating them with a payer. The Request Network API forwards these details to the offramp provider (Request Tech).
2. **Approval**: The platform receives a webhook (`payment_detail.updated`) indicating if the payment details are approved, failed, or pending.
3. **Create Request**: Once approved, the platform creates a new request as usual, but with the `isCryptoToFiatAllowed` flag set to `true`. This signals that the request is eligible for crypto-to-fiat payment.

### **Design Rationale & UX Constraints**

While it is technically possible to create a crypto-to-fiat request before the payer has completed KYC, EasyInvoice intentionally requires the payer to complete KYC first. This decision is based on several practical and UX considerations:

* **Bank Account Association:** The payee’s bank account ("payment details") must be linked to a specific payer, which can only be done after the payer completes KYC. This ensures compliance and accurate association of payment details.
* **Validation Complexity:** Although the payee could submit their bank account details in advance, the platform cannot validate or approve these details until the payer’s KYC is complete. This would introduce additional communication steps and potential confusion.
* **UI Simplicity:** EasyInvoice integrates payee bank account registration directly into the Create Invoice form. If the user clicks "Create" before the bank account is approved, a loading indicator appears until approval is granted. This avoids the need for a separate bank account management page and keeps the user experience straightforward.
* **Protocol Fit**: The crypto-to-fiat feature is integrated at the API level, not at the Request Network protocol level. Creating a request on the protocol does not require bank account details, because the protocol itself only handles crypto payments. The additional bank account and offramp logic is layered on top via the API, which transfers crypto to Request Tech, who then executes the offramp and sends fiat to the payee’s bank account. This separation adds some complexity, so the UI is intentionally kept simple.
* **Future Flexibility:** While some clients may want to allow payees to create requests before payer KYC, this is not currently supported in EasyInvoice to avoid increased complexity. We may revisit this if there is sufficient market demand.

This approach ensures a smooth, compliant, and user-friendly experience, even if it means some technical possibilities are not exposed in the current UI.

### Relevant Endpoints

* `POST /payer/{clientUserId}/payment-details`: Create payment details (register bank account) for a payee.
* `GET /payer/{clientUserId}/payment-details`: Get payment details (bank accounts) for a payee.
* `POST /v2/request` with `isCryptoToFiatAllowed = true`: Create a new crypto-to-fiat request

## Create payment details

> Create payment details for a user

```json
{"openapi":"3.0.0","info":{"title":"Request Network API","version":"0.18.1"},"tags":[{"name":"V2/Payer","description":"Crypto-to-fiat payer management operations (V2)"}],"servers":[{"url":"https://api.request.network","description":"Production server"},{"url":"https://api.stage.request.network","description":"Staging server"},{"url":"http://127.0.0.1:8080","description":"Local development server"}],"paths":{"/v2/payer/{clientUserId}/payment-details":{"post":{"description":"Create payment details for a user","operationId":"PayerV2Controller_createPaymentDetails_v2","parameters":[{"name":"clientUserId","required":true,"in":"path","description":"The client user ID","schema":{"type":"string"}},{"name":"x-api-key","in":"header","description":"API key for authentication","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"bankName":{"type":"string","minLength":1,"description":"Name of the bank"},"accountName":{"type":"string","minLength":1,"description":"Name of the account holder"},"accountNumber":{"type":"string","description":"Bank account number"},"routingNumber":{"type":"string","description":"Bank routing number (US)"},"beneficiaryType":{"type":"string","enum":["individual","business"],"description":"Type of beneficiary"},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"Three-letter currency code (ISO 4217)"},"addressLine1":{"type":"string","minLength":1,"description":"Primary address line"},"addressLine2":{"type":"string","description":"Secondary address line"},"city":{"type":"string","minLength":1,"description":"City name"},"state":{"type":"string","description":"State or province code"},"country":{"type":"string","minLength":2,"maxLength":2,"description":"Two-letter country code (ISO 3166-1 alpha-2)"},"dateOfBirth":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Date of birth in YYYY-MM-DD format"},"postalCode":{"type":"string","minLength":1,"description":"Postal or ZIP code"},"rails":{"type":"string","enum":["local","swift","wire"],"default":"local","description":"Payment rail type"},"sortCode":{"type":"string","description":"UK bank sort code"},"iban":{"type":"string","description":"International Bank Account Number"},"swiftBic":{"type":"string","description":"SWIFT/BIC code"},"documentNumber":{"type":"string","description":"Government-issued ID number"},"documentType":{"type":"string","description":"Type of government-issued ID (e.g., passport, driver's license)"},"accountType":{"type":"string","enum":["checking","savings"],"description":"Type of bank account"},"ribNumber":{"type":"string","description":"French RIB number"},"bsbNumber":{"type":"string","description":"Australian BSB number"},"ncc":{"type":"string","description":"New Zealand NCC number"},"branchCode":{"type":"string","description":"Bank branch code"},"bankCode":{"type":"string","description":"Bank code"},"ifsc":{"type":"string","description":"Indian Financial System Code"}},"required":["bankName","accountName","beneficiaryType","currency","addressLine1","city","country","dateOfBirth","postalCode"]}}}},"responses":{"201":{"description":"Payment details created successfully","content":{"application/json":{"schema":{"properties":{"payment_detail":{"type":"object","properties":{"id":{"type":"string"},"clientUserId":{"type":"string"},"bankName":{"type":"string"},"accountName":{"type":"string"},"currency":{"type":"string"},"beneficiaryType":{"type":"string","enum":["individual","business"]}}}}}}}},"400":{"description":"Invalid request data","content":{"application/json":{"schema":{"properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"User not found","content":{"application/json":{"schema":{"properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}}}}}},"429":{"description":"Too Many Requests"}},"summary":"Create payment details","tags":["Payer","V2/Payer"]}}}}
```

## Get payment details for a user

> Retrieves the registered bank account details for a user. Optionally filter by payment details ID.

```json
{"openapi":"3.0.0","info":{"title":"Request Network API","version":"0.18.1"},"tags":[{"name":"V2/Payer","description":"Crypto-to-fiat payer management operations (V2)"}],"servers":[{"url":"https://api.request.network","description":"Production server"},{"url":"https://api.stage.request.network","description":"Staging server"},{"url":"http://127.0.0.1:8080","description":"Local development server"}],"paths":{"/v2/payer/{clientUserId}/payment-details":{"get":{"description":"Retrieves the registered bank account details for a user. Optionally filter by payment details ID.","operationId":"PayerV2Controller_getPaymentDetails_v2","parameters":[{"name":"clientUserId","required":true,"in":"path","description":"The client user ID to get payment details for","schema":{"type":"string"}},{"name":"paymentDetailsId","required":false,"in":"query","description":"Optional ID of specific payment details to retrieve","schema":{"type":"string"}},{"name":"x-api-key","in":"header","description":"API key for authentication","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Payment details retrieved successfully","content":{"application/json":{"schema":{"properties":{"paymentDetails":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"bankName":{"type":"string"},"accountName":{"type":"string"},"beneficiaryType":{"type":"string"},"accountNumber":{"type":"string"},"routingNumber":{"type":"string"},"currency":{"type":"string"},"status":{"type":"string"},"rails":{"type":"string"}}}}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"User or payment details not found","content":{"application/json":{"schema":{"properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}}}}}},"429":{"description":"Too Many Requests"}},"summary":"Get payment details for a user","tags":["Payer","V2/Payer"]}}}}
```

## Create a new request

> Create a new payment request

```json
{"openapi":"3.0.0","info":{"title":"Request Network API","version":"0.18.1"},"tags":[{"name":"V2/Request","description":"Core payment request operations (V2)"}],"servers":[{"url":"https://api.request.network","description":"Production server"},{"url":"https://api.stage.request.network","description":"Staging server"},{"url":"http://127.0.0.1:8080","description":"Local development server"}],"paths":{"/v2/request":{"post":{"description":"Create a new payment request","operationId":"RequestControllerV2_createRequest_v2","parameters":[{"name":"x-api-key","in":"header","description":"API key for authentication (optional if using Client ID)","required":false,"schema":{"type":"string"}},{"name":"x-client-id","in":"header","description":"Client ID for frontend authentication (optional if using API key)","required":false,"schema":{"type":"string"}},{"name":"Origin","in":"header","description":"Origin header (required for Client ID auth, automatically set by browser)","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"payer":{"type":"string","description":"The wallet address of the payer"},"payee":{"type":"string","description":"The wallet address of the payee (Ethereum 0x... or TRON T...). Optional when using client ID authentication with a configured payee destination."},"amount":{"type":"string","description":"The payable amount of the invoice, in human readable format"},"invoiceCurrency":{"type":"string","description":"Invoice Currency ID, from the [Request Network Token List](https://docs.request.network/general/request-network-token-list) e.g: USD"},"paymentCurrency":{"type":"string","description":"Payment currency ID, from the [Request Network Token List](https://docs.request.network/general/request-network-token-list) e.g: ETH-sepolia-sepolia"},"recurrence":{"type":"object","properties":{"startDate":{"type":"string","description":"The start date of the invoice, cannot be in the past"},"frequency":{"type":"string","enum":["DAILY","WEEKLY","MONTHLY","YEARLY"],"description":"The frequency of the invoice"}},"required":["startDate","frequency"],"description":"The recurrence of the invoice"},"isCryptoToFiatAvailable":{"type":"boolean","description":"Whether crypto-to-fiat payment is available for this request"},"customerInfo":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100,"description":"Customer's first name"},"lastName":{"type":"string","minLength":1,"maxLength":100,"description":"Customer's last name"},"email":{"type":"string","maxLength":255,"format":"email","description":"Customer's email address"},"address":{"type":"object","properties":{"street":{"type":"string","maxLength":255,"description":"Street address"},"city":{"type":"string","maxLength":100,"description":"City"},"state":{"type":"string","maxLength":100,"description":"State or province"},"postalCode":{"type":"string","maxLength":20,"description":"Postal or ZIP code"},"country":{"type":"string","minLength":2,"maxLength":2,"description":"Country code (ISO 3166-1 alpha-2)"}},"description":"Customer's address"}},"description":"Optional customer information for merchant receipt tracking"},"reference":{"type":"string","minLength":1,"maxLength":255,"description":"Merchant reference for receipt tracking and identification"},"originalRequestId":{"type":"string","minLength":1,"description":"ID of the original request for recurring payments"},"originalRequestPaymentReference":{"type":"string","minLength":1,"description":"Payment reference of the original request for recurring payments"}},"required":["amount","invoiceCurrency","paymentCurrency"]}}}},"responses":{"201":{"description":"Request created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"paymentReference":{"type":"string","description":"Unique identifier of the request, used to pay the request as well as check the status of the request"},"requestId":{"type":"string","description":"Unique identifier of the request, commonly used to look up a request in Request Scan"}}}}}},"400":{"description":"Validation failed or no active payee destination for client ID"},"403":{"description":"Client ID has been revoked"},"429":{"description":"Too Many Requests"}},"summary":"Create a new request","tags":["Request","V2/Request"]}}}}
```

## Paying a Crypto-to-Fiat Request

The payer pays in crypto; Request Tech handles offramping and fiat payout.

### **Payment Flow Diagram**

{% @mermaid/diagram content="---
config:
fontSize: 10
sequence:
wrap: true
actorMargin: 50
width: 70
height: 30
----------

sequenceDiagram
participant Payer
participant Platform
participant RequestAPI
participant RequestTech
participant Blockchain

```
Platform->>RequestAPI: GET payment calldata for request/{requestId}/pay
Platform->>Payer: Prompt to sign and send transaction
Payer->>Blockchain: Send crypto to Request Tech
Blockchain-->>RequestTech: Payment received
RequestTech-->>RequestAPI: offramp_update (webhook)
RequestAPI-->>Platform: webhook: payment.processing/payment.failed (subStatus: initiated, ongoing_checks, sending_fiat, fiat_sent, failed, etc.)
RequestTech->>Payee Bank: Offramp and deposit fiat
RequestTech-->>RequestAPI: offramp_update (fiat sent)
RequestAPI-->>Platform: webhook: payment.processing (subStatus: fiat_sent)
RequestAPI-->>Platform: webhook: payment.confirmed (fiat delivered)" %}
```

**Flow Explanation**

1. **Get Payment Calldata**: The platform fetches payment calldata for the request.
2. **User Pays**: The payer signs and submits the transaction, sending crypto to Request Tech.
3. **Offramp Processing**: Request Tech receives the crypto and begins the offramp process.
4. **Status Updates**: The platform receives webhook events as the offramp progresses ([payment.processing](https://vscode-file/vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html), [payment.failed](https://vscode-file/vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html)), with [subStatus](https://vscode-file/vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html) indicating the current offramp stage.
5. **Fiat Delivered**: When the offramp is complete, the platform receives a final webhook ([payment.processing](https://vscode-file/vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html) with [subStatus: fiat\_sent](https://vscode-file/vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html)), and then a [payment.confirmed](https://vscode-file/vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html) event.

## Crypto-to-fiat Webhook Event Reference

|                          |                                        |                                                                                                                                                                                                                                                                                                         |
| ------------------------ | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Event                    | Description                            | subStatus values (if any)                                                                                                                                                                                                                                                                               |
| `compliance.updated`     | KYC/Agreement status updates           | <p><code>kycStatus</code>: <code>initiated</code>, <code>pending</code>, <code>approved</code>, <code>rejected</code>, <code>failed</code><br><br><code>agreementStatus</code>: <code>not\_started</code>, <code>pending</code>, <code>completed</code>, <code>rejected</code>, <code>failed</code></p> |
| `payment_detail.updated` | Payment detail (bank account) status   | `approved`, `failed`, `pending`                                                                                                                                                                                                                                                                         |
| `payment.processing`     | Offramp in progress                    | `initiated`, `pending_internal_assessment`, `ongoing_checks`, `sending_fiat`, `fiat_sent`, `bounced`, `retry_required`                                                                                                                                                                                  |
| `payment.failed`         | Offramp or payment failed              | `failed`, `bounced`                                                                                                                                                                                                                                                                                     |
| `payment.confirmed`      | Payment fully settled (fiat delivered) |                                                                                                                                                                                                                                                                                                         |

\\
