Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 136 additions & 55 deletions docs/API_REQUIREMENTS.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,64 @@
# Edge Exchange Provider API Requirements

This document defines the **technical API requirements** for third-party exchange providers seeking to integrate with the Edge wallet platform. It establishes standards for both **crypto-to-crypto swap providers** and **fiat on/off ramp providers**.

Key requirements include:
1. [**Asset identification**](#1-chain-and-token-identification) using chain network identifiers and token contract addresses (not just ticker symbols)
2. [**Order tracking**](#2-order-identification-and-status-page) via unique order IDs with unauthenticated status pages
3. [**Structured error handling**](#3-error-handling) that returns all applicable errors (region restrictions, limits, unsupported assets) in a single response
4. [**Bi-directional quoting**](#4-quoting-requirements) allowing users to specify either source or destination amounts
5. [**Transaction status API**](#5-transaction-status-api) for querying order status
6. [**Reporting APIs**](#6-reporting-api) for affiliate revenue tracking
7. [**Account activation**](#7-account-activation) for assets like XRP and HBAR
8. [**Affiliate revenue withdrawal**](#8-affiliate-revenue-withdrawal) with automated monthly payouts

For fiat on/off ramp providers specifically, the document adds requirements around:

9. [**User authentication**](#9-user-authentication) using cryptographic auth keys
10. [**Regional and fiat currency support**](#10-regional-and-fiat-currency-support) with proper error handling
11. [**KYC information**](#11-kyc-information) submission via API (not widget)
12. [**Bank information**](#12-bank-information) submission for wire/SEPA transfers
13. [**Verification**](#13-verification) code handling for phone and email
14. [**Widget return URIs**](#14-widgets) for seamless app integration
15. [**Off-ramp flow**](#15-off-ramp-flow) supporting no-widget transactions

## Requirements for both Swap and On/Off Ramp providers
Technical API requirements for third-party exchange providers integrating with the Edge wallet platform, covering **crypto-to-crypto swap providers** and **fiat on/off ramp providers**.

**All requirements are mandatory** unless explicitly stated otherwise.

### Table of Contents

**General principles:**

- [Amount Representation](#amount-representation)

**Requirements for all providers:**

1. [Chain and Token Identification](#1-chain-and-token-identification)
2. [Order Identification and Status Page](#2-order-identification-and-status-page)
3. [Error Handling](#3-error-handling)
4. [Quoting Requirements](#4-quoting-requirements)
5. [Transaction Status API](#5-transaction-status-api)
6. [Reporting API](#6-reporting-api)
7. [Account Activation](#7-account-activation)
8. [Affiliate Revenue Withdrawal](#8-affiliate-revenue-withdrawal)

**Additional requirements for fiat on/off ramp providers:**

9. [User Authentication](#9-user-authentication)
10. [Regional and Fiat Currency Support](#10-regional-and-fiat-currency-support)
11. [KYC Information](#11-kyc-information)
12. [Bank Information](#12-bank-information)
13. [Verification](#13-verification)
14. [Widget Return URIs](#14-widgets)
15. [Off-Ramp Flow](#15-off-ramp-flow)

---

## General Principles

### Amount Representation

Amounts **should** be expressed in the asset's **native (smallest indivisible) units** rather than display units:

| Asset | Native unit | Example: 1.5 display units |
|---|---|---|
| BTC | satoshis | `150000000` |
| ETH | wei | `1500000000000000000` |
| SOL | lamports | `1500000000` |
| USDC (6 decimals) | micro-units | `1500000` |

If native units are not feasible, the API **must** clearly document which unit convention is used for every amount field.

---

## Requirements for All Providers

### 1. Chain and Token Identification

API must allow requesting quotes and orders using a unique chain identifier and token identifier such as the contract address. This is to prevent confusion on which token is being referenced as well as to prevent the need to map provider tickers to tokens supported by Edge. Note that it is NOT sufficient to provide a separate endpoint to list all assets as this would require too many API calls to get a quote. This example shows how assets should be specified for a quote. The Edge exchange plugins will map the provider's chain network identifiers to edge specific chain network identifiers so they need not match exactly.
The API **must** accept a unique chain identifier and token identifier (such as the contract address) when requesting quotes and creating orders. It is **not** sufficient to only provide a separate "list all assets" endpoint — the exact asset must be specifiable in the quote/order request itself.

Edge exchange plugins will map the provider's chain network identifiers to Edge-specific identifiers, so they do not need to match exactly.

**Example — non-EVM asset:**

```json
{
Expand All @@ -35,37 +67,45 @@ API must allow requesting quotes and orders using a unique chain identifier and
}
```

For EVM chains, API must allow requesting quotes using the universally accepted EVM `chainId` to specify the chain in addition to the token identifier. This allows automatic support of new EVMs with no need to add a mapping of provider chain identifiers to Edge chain identifiers. I.e.
**Example — EVM asset:**

For EVM chains, the API **must** also accept the standard EVM `chainId` (e.g. `1` for Ethereum, `56` for BNB Smart Chain).

```json
{
"chainNetwork": "evmGeneric",
"chainId": 56 // BNB Smart Chain
"chainId": 56, // BNB Smart Chain
"tokenId": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d"
}
```

### 2. Order Identification and Status Page

- Order requests must provide a unique `orderId` identifier that can be used to query status of the order via an unauthenticated API as well as connect the order with completed swaps reported via a reporting API.
- Provider must provide an un-authenticated status page that uses the `orderId` to provide status on the swap. I.e. [`https://status.provider.com/orderStatus/{orderId}`](https://status.provider.com/orderStatus/{orderId)
- Every order response **must** include a unique `orderId` usable to query order status via an **unauthenticated** API endpoint and correlate with transactions in the Reporting API (section 6).
- The provider **must** host an unauthenticated, user-facing status page accessible by `orderId`. Example: `https://status.provider.com/orderStatus/{orderId}`

### 3. Error Handling

Quote request errors must return all the following possible errors at once with all the mentioned details. This is to ensure that Edge can surface the most relevant error to the user. This prevents irrelevant errors like below limit errors from being surfaced to the user when the user would also be region restricted.
When a quote request fails, the API **must** return **all** applicable errors in a **single response** as structured JSON objects with machine-readable error codes. Edge has business logic to determine which error takes priority.

#### Required error types

- Region restricted error
- Asset unsupported error
- Above or below limit errors with min/max amounts specified in both the source and destination asset
| Error Type | Required Fields |
|---|---|
| **Region restricted** | Error code |
| **Asset not supported** | Error code, which asset(s) are unsupported |
| **Over limit** | Error code, `sourceAmountLimit`, `destinationAmountLimit` |
| **Under limit** | Error code, `sourceAmountLimit`, `destinationAmountLimit` |

Limit errors need to be specified with a hardened error code and not using an arbitrary string. I.e. for swap from BTC to USDT
#### Structured error format

```json
{
"errors": [
{
"error": "OverLimitError",
"sourceAmountLimit": 9.789, // BTC
"destinationAmountLimit": 1000000 // USDT
"sourceAmountLimit": 978900000, // 0.009789 BTC, when quoting with the "from/source" side
"destinationAmountLimit": 1000000000000 // $1M USDT, when quoting with the "to/destination" side (if supported)
},
{
"error": "RegionRestricted"
Expand All @@ -74,13 +114,33 @@ Limit errors need to be specified with a hardened error code and not using an ar
}
```

**Incorrect — unstructured string message (will not be accepted):**

```json
{
"error": "Amount is below the minimum of 0.0001 BTC"
}
```

#### Limit error field definitions

| Field | Type | Description |
|---|---|---|
| `error` | `string` (enum) | Machine-readable error code, e.g. `"OverLimitError"`, `"UnderLimitError"` |
| `sourceAmountLimit` | `number` | The limit in the source asset |
| `destinationAmountLimit` | `number` | The limit in the destination asset |

Both `sourceAmountLimit` and `destinationAmountLimit` are required. Limit amounts should use [native units](#amount-representation) where possible.

### 4. Quoting Requirements

- Provider must allow bi-directional quoting such that the user can specify either the source asset amount or destination asset amount.
The API **must** support bi-directional quoting: the user can specify either the source amount or the destination amount, and the API returns the corresponding counterpart.

Quoted amounts should use [native units](#amount-representation) where possible.

### 5. Transaction Status API

Provider must provide a transaction status API that allows querying of transaction status by `orderId`. This allows the Edge UI to show an updated transaction status to the user when they view the outgoing transaction.
The provider **must** expose a transaction status endpoint that accepts an `orderId` and returns the current status.

```
GET /api/status/{orderId}
Expand All @@ -97,71 +157,92 @@ GET /api/status/{orderId}

### 6. Reporting API

Provider must provide an authenticated reporting API that allows querying of all transactions created using Edge. The reporting API must provide at minimum the following information for each transaction. Actual values are only examples. Similar values that can be mapped to the below are sufficient. API must allow paginated queries with start date, end date, and number of transactions.
The provider **must** expose an authenticated reporting API that returns all transactions created through Edge, supporting paginated queries with `startDate`, `endDate`, and `limit` parameters.

Each transaction record **must** include the fields below (names do not need to match exactly). Amount fields should use [native units](#amount-representation) where possible.

```json
{
"orderId": "pr39dhg2409ryhgei39r", // Must match the orderId from quoting API
"status": "pending" | "processing" | "infoNeeded" | "expired" | "refunded" | "completed",
"orderId": "pr39dhg2409ryhgei39r",
"status": "completed",
"createdDate": "2025-07-10T17:24:25.997Z",
"completedDate": "2025-07-10T17:28:00.997Z",
"sourceNetwork": "solana",
"sourceTokenId": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"sourceCurrencyCode": "USDC",
"sourceAmount": 118123,
"sourceEvmChainId": null, // source not an EVM chain
"sourceEvmChainId": null,
"destinationNetwork": "bitcoin",
"destinationTokenId": null, // signified no token but primary gas token asset BTC
"destinationTokenId": null,
"destinationCurrencyCode": "BTC",
"destinationAmount": 1.01,
"destinationEvmChainId": null, // destination not an EVM chain
"destinationEvmChainId": null,
"payinAddress": "B8kGR7GpPh7GUsTgDgzjQYoJEFbpPr6q2V4iLEDeF6AD",
"payoutAddress": "bc1q05wqn9nffg874fc6mp23lagfutawtwljx8udwy",
"payinTxid": "wtpqAqCJj2iNte6iA6UUPtc5xgaRNGdjFuPk9B9VYFxkqxtSkSiC99gPU8MnGCEstbRTX3gQY5ErQn1475iuhFD",
"payoutTxid": "2f6fbb24058e578d0a51842dfd8e79935df1702130c0a7ba3e8ef442bfc0f41c"
}
```

| Field | Description |
|---|---|
| `orderId` | Must match the `orderId` from the quoting/order API |
| `status` | One of: `pending`, `processing`, `infoNeeded`, `expired`, `refunded`, `completed` |
| `sourceNetwork` / `destinationNetwork` | Chain identifier (e.g. `"solana"`, `"bitcoin"`) |
| `sourceTokenId` / `destinationTokenId` | Contract address, or `null` for the chain's native asset |
| `sourceEvmChainId` / `destinationEvmChainId` | EVM chain ID if applicable, otherwise `null` |
| `payinAddress` / `payoutAddress` | Deposit and withdrawal addresses |
| `payinTxid` / `payoutTxid` | On-chain transaction IDs |

### 7. Account Activation

When a user requests an exchange into assets like XRP and HBAR, the provider should detect that the withdrawal address is not activated and send an activation transaction as part of the withdrawal.
Some blockchain assets (e.g. XRP, HBAR) require account activation before they can receive funds. The provider **must** detect unactivated destination addresses and include the activation transaction as part of the withdrawal — without requiring any additional action from the user or from Edge.

### 8. Affiliate Revenue Withdrawal

Providers must automatically withdraw affiliate revenue funds in a single asset no later than 24 hours after the month close GMT time. Funds withdrawal should be allowed in at least BTC, ETH, and USDC to a fixed address verified by Edge. Edge should not be required to initiate withdrawal via an API or dashboard. Any changes to the withdrawal address should be verified with additional authentication such as 2FA codes and/or email verification.
- The provider **must** automatically withdraw affiliate revenue no later than **24 hours after each month-end (GMT)**. Edge should **not** be required to initiate withdrawals.
- Withdrawal must be supported in at least **BTC, ETH, and USDC** to a fixed address verified by Edge.
- Any changes to the withdrawal address **must** require additional authentication (e.g. 2FA and/or email verification).

---

## Additional requirements for fiat on/off ramp providers
## Additional Requirements for Fiat On/Off Ramp Providers

### 9. User Authentication

Provider API should allow the Edge application to authenticate a user via cryptographically random authKey. The authKey should be created by Edge and passed into any quoting or order execution endpoint. If the authKey does not exist on the Provider system, the Provider's API should allow for account creation by receiving KYC info (if necessary) via API.
The provider API **must** allow Edge to authenticate users via a cryptographically random `authKey` generated by Edge, passed with every quoting or order execution request.

If the `authKey` does not yet exist on the provider's system, the API **must** support account creation by accepting KYC information via API — without requiring an external registration page.

### 10. Regional and Fiat Currency Support

Provider quoting API should allow specifying not just the crypto asset but also the region (country/province) and fiat currency to receive a quote. Proper errors should be returned for unsupported regions and unsupported fiat currencies.
The quoting API **must** accept the user's region (country and, where applicable, province/state) and fiat currency. The API must return structured errors (see [section 3](#3-error-handling)) for unsupported regions and unsupported fiat currencies.

### 11. KYC Information

Provider API should allow the Edge application to provide basic KYC information and verification via API (not widget). Basic KYC information includes
The provider API **must** allow Edge to submit KYC information **via API** (not via a widget or redirect):

- Name
- Full name
- Address
- Phone number
- Email address

### 12. Bank Information

For basic bank transfers (i.e. wire, SEPA) and any payment methods that do not have opposing regulatory requirements, Provider must have an API that allows Edge to submit bank information. I.e. account number, IBAN, and routing number.
For payment methods without conflicting regulatory requirements (e.g. wire transfers, SEPA), the provider **must** expose an API for Edge to submit bank account details (account number, IBAN, routing number, etc.).

### 13. Verification

- API should allow the Edge application to send KYC verification codes for phone and email verification. Verification codes are still generated by the provider servers, not Edge. Users enter verification codes into the Edge UI and are sent to provider via API.
- An API should let Edge know when a specific piece of KYC information is missing or out of date to allow the Edge application to collect such info to send to the Provider's API.
- The API **must** allow Edge to submit provider-generated verification codes for phone and email verification.
- The API **must** indicate when specific KYC information is missing or outdated, so Edge can prompt the user.

### 14. Widgets

Any required widgets (ie for submitting credit card info or facial scan) must allow Edge to specify return URIs once the widget is complete. This allows Edge to close any webviews and continue with the application flow.
Any required widgets (e.g. for credit card entry or facial biometric scans) **must** accept a return URI parameter from Edge to allow closing the webview and resuming the application flow.

### 15. Off-Ramp Flow

For off-ramp transactions that have already had a payment method linked to the user's account, the provider must allow for a full "no-widget" flow by simply providing a crypto address that must receive funds and an expiration time (if necessary).
For off-ramp transactions where the user has already linked a payment method, the provider **must** support a **fully no-widget flow** by returning:

- A crypto deposit address where Edge sends the funds
- An expiration time for the deposit address (if applicable)
Loading