Skip to content
Merged
Show file tree
Hide file tree
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
10 changes: 4 additions & 6 deletions api-reference/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ This section contains the **Gateway API** endpoints needed for an **API-first (n

## WalletConnect Pay (Gateway)

- **Get payment options**
- **Fetch an action**
- **Confirm a payment**

If you’re looking for the integration overview, start with **[API-first integration (Non-SDK wallets)](/payments/wallets/api-first)**.

- **Get payment options** — list available options for the user's accounts
- **Fetch an action** — resolve build actions into executable wallet RPC actions
- **Confirm a payment** — submit signatures and complete the payment

If you're looking for the integration overview, start with **[API-first integration (Non-SDK wallets)](/payments/wallets/api-first)**.
81 changes: 30 additions & 51 deletions api/walletconnect-pay-gateway.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,9 @@ paths:
required: true
schema:
type: string
- name: Sdk-Name
- name: App-Id
in: header
required: true
schema:
type: string
- name: Sdk-Version
in: header
required: true
schema:
type: string
- name: Sdk-Platform
in: header
required: true
required: false
schema:
type: string
- name: id
Expand Down Expand Up @@ -97,19 +87,9 @@ paths:
required: true
schema:
type: string
- name: Sdk-Name
in: header
required: true
schema:
type: string
- name: Sdk-Version
- name: App-Id
in: header
required: true
schema:
type: string
- name: Sdk-Platform
in: header
required: true
required: false
schema:
type: string
- name: id
Expand Down Expand Up @@ -172,27 +152,17 @@ paths:
tags:
- Gateway
summary: Confirm a payment
description: This endpoint confirms a payment and submits it to the blockchain for processing.
description: "This endpoint confirms a payment and submits it to the blockchain for processing."
operationId: confirm_payment_handler
parameters:
- name: Api-Key
in: header
required: true
schema:
type: string
- name: Sdk-Name
- name: App-Id
in: header
required: true
schema:
type: string
- name: Sdk-Version
in: header
required: true
schema:
type: string
- name: Sdk-Platform
in: header
required: true
required: false
schema:
type: string
- name: id
Expand Down Expand Up @@ -223,6 +193,8 @@ paths:
value: John Smith
- id: dob
value: "1990-01-01"
- id: tosConfirmed
value: "true"
optionId: opt_123
results:
- data:
Expand Down Expand Up @@ -331,10 +303,21 @@ components:
type: string
nullable: true
description: URL of the icon of the asset (if token)
networkIconUrl:
type: string
nullable: true
description: URL of the icon of the network
networkName:
type: string
nullable: true
description: Name of the network of the asset (if token)
Build:
type: object
required:
- data
properties:
data:
type: string
BuyerInfo:
type: object
required:
Expand All @@ -351,18 +334,16 @@ components:
accountProviderName:
type: string
description: Account provider name
Build:
type: object
required:
- data
properties:
data:
type: string
CollectData:
type: object
required:
- fields
properties:
url:
type: string
description: WebView URL for data collection
schema:
type: object
nullable: true
description: JSON schema describing the required fields
fields:
type: array
items:
Expand Down Expand Up @@ -476,9 +457,6 @@ components:
- missing_api_key
- missing_merchant_api_key
- missing_merchant_id
- missing_sdk_name
- missing_sdk_version
- missing_sdk_platform
- header_not_ascii
- not_sandbox_api_key
- merchant_not_found
Expand Down Expand Up @@ -596,6 +574,9 @@ components:
- etaS
- actions
properties:
account:
type: string
description: CAIP-10 account identifier for this option
actions:
type: array
items:
Expand Down Expand Up @@ -642,5 +623,3 @@ components:
name: Api-Key
security:
- API Key: []


130 changes: 115 additions & 15 deletions payments/wallets/api-first.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,27 @@ sidebarTitle: "API-first (No SDK)"
description: "Integrate WalletConnect Pay in a wallet without an SDK, using the Gateway API."
---

If youre integrating WalletConnect Pay into a wallet **without using the Wallet Pay SDK**, you can use an API-first approach via the **Gateway API**.
If you're integrating WalletConnect Pay into a wallet **without using the Wallet Pay SDK**, you can use an API-first approach via the **Gateway API**.

This flow is centered around **three Gateway calls**:

- **Get payment options**: list options the user can complete with their wallet/accounts
- **Fetch an action**: resolve build actions into wallet RPC actions when needed
- **Fetch an action**: resolve "build" actions into wallet RPC actions when needed
- **Confirm a payment**: submit the selected option and the executed action results

## Prerequisites

- **API key**: request access from WalletConnect
- You can do this by filling out [**this form**](https://share.hsforms.com/19Dpp4ayYR9uriB3xNAh0JAnxw6s) and getting in touch with our team.
- **Wallet identity headers** (required on each request):
- `Sdk-Name`
- `Sdk-Version`
- `Sdk-Platform`
- **Required headers** on each request:
- `Api-Key` — your API key


## Payment flow

The payment flow mirrors the SDK flow, but you call the Gateway API directly:

**Get Options → (Fetch Actions) → Execute Wallet RPC → (Collect Data) → Confirm Payment**
**Get Options → (Collect Data) → (Fetch Actions) → Execute Wallet RPC → Confirm Payment**

```mermaid
sequenceDiagram
Expand All @@ -39,6 +38,11 @@ sequenceDiagram
Gateway-->>Wallet: options[] (+ optional info/collectData)
Wallet->>User: Display payment options

alt Data collection required
Wallet->>User: Request additional info (WebView)
User->>Wallet: Complete form
end

User->>Wallet: Select payment option

alt Option includes a build action
Expand All @@ -51,11 +55,6 @@ sequenceDiagram
Wallet->>Chain: Execute wallet RPC actions (in order)
Chain-->>Wallet: Results (e.g., signature(s) / tx hash(es))

alt Data collection required
Wallet->>User: Request additional info
User->>Wallet: Provide data
end

Wallet->>Gateway: POST /v1/gateway/payment/{id}/confirm (optionId, results, collectedData?)
Gateway-->>Wallet: status + isFinal (+ pollInMs)
Wallet->>User: Show result / status
Expand Down Expand Up @@ -97,15 +96,116 @@ If an option contains an action of type **`build`**, call **Fetch an action** wi
After your wallet executes the required `walletRpc` actions (sign/submit), call **Confirm a payment** with:

- the selected `optionId`
- `results[]`: the output from each executed action (in the same spirit/order you performed them)
- `results[]`: the output from each executed action (in the same order you performed them)
- optional `collectedData` if the options response requested additional user info

<Info>
If you used the **WebView-based data collection** flow (i.e., displayed `collectData.url` in a WebView), there is no need to send `collectedData` in the confirm request — the WebView submits user data directly to the backend.
</Info>

<Note>
If `isFinal` is `false`, the response may include `pollInMs`. Use it to decide when to check again (see the API Reference for status/polling behavior).
</Note>

## API Reference
<Info>
The WalletConnect Pay SDKs support **WebView-based data collection**. When `collectData.url` is present in the payment options response, wallets can display this URL in a WebView instead of building native forms. The WebView handles form rendering, validation, and T&C acceptance, and submits data directly to the backend. See the [platform-specific SDK documentation](/payments/wallets/overview) for implementation details.
</Info>

For request/response schemas and examples for each Gateway endpoint, see the **[API Reference](/api-reference)**.
## Integration guidelines

These guidelines reflect the patterns used internally by the WalletConnect Pay SDK. Following them ensures a smooth, reliable UX.

### Payment link detection

Payment links can arrive in several formats. Your wallet should detect and extract the `paymentId` from:

| Format | Example |
|--------|---------|
| WC Pay URL (path) | `https://pay.walletconnect.com/pay_123` |
| WC Pay URL (query) | `https://pay.walletconnect.com/?pid=pay_123` |
| `wc:` URI with `pay=` param | `wc:abc@2?pay=https%3A%2F%2Fpay.walletconnect.com%2F%3Fpid%3Dpay_123` |
| Bare payment ID | `pay_123` |

<Warning>
Only trust `pay.walletconnect.com` and `*.pay.walletconnect.com` as valid WC Pay hosts. Always validate the domain before extracting a payment ID.
</Warning>

<Note>
Check for payment links **before** handling generic URLs or WalletConnect pairing URIs. Payment links are HTTPS URLs that would otherwise open in a browser.
</Note>

### Providing accounts

Pass all of the user's accounts in **CAIP-10 format** (`eip155:{chainId}:{address}`) when calling **Get payment options**. Include accounts for every supported chain to maximize the number of payment options returned.

### Resolving `build` actions

When an option's `actions[]` contains a `build` action, it cannot be executed directly. Call **Fetch an action** (`POST /v1/gateway/payment/{id}/fetch`) with the `optionId` and the build action's `data` string. The response will contain one or more `walletRpc` actions that your wallet can execute.

<Note>
A single `build` action may resolve into multiple `walletRpc` actions. Always iterate over the full response.
</Note>

### Executing wallet RPC actions

Each `walletRpc` action contains:
- `chain_id` — the chain to execute on (CAIP-2 format, e.g., `eip155:8453`)
- `method` — the RPC method (e.g., `eth_signTypedData_v4`, `personal_sign`)
- `params` — JSON-encoded parameters

Execute each action in order using your wallet's signing implementation, and collect the result (e.g., signature hex string) for each.

### Submitting results

When calling **Confirm a payment**, wrap each signature as a `walletRpc` result:

```json
{
"optionId": "opt_123",
"results": [
{ "type": "walletRpc", "data": ["0x<signature_1>"] },
{ "type": "walletRpc", "data": ["0x<signature_2>"] }
]
}
```

<Warning>
The `results[]` array **must** match the `actions[]` array in both length and order. Misalignment causes payment failures.
</Warning>

### Polling for final status

After **Confirm a payment** returns, check the `isFinal` field:

- **`isFinal: true`** — the payment has reached a terminal state (`succeeded`, `failed`, or `expired`). No further action needed.
- **`isFinal: false`** — the payment is still processing. Use the `pollInMs` value from the response as the delay before your next confirm call.

Use the `maxPollMs` query parameter on the confirm request to enable **server-side long-polling** — the server will hold the connection and return as soon as the status changes or the timeout expires, reducing the number of round-trips.

```
POST /v1/gateway/payment/{id}/confirm?maxPollMs=30000
```

### Retry strategy

Implement retries with **exponential backoff and jitter** for resilience:

- **Retry only on** server errors (5xx) and network failures (connection refused, timeout)
- **Do not retry** client errors (4xx) — these indicate invalid input and won't succeed on retry
- **Recommended**: 3 retries with 100ms initial backoff, doubling each attempt, plus random jitter

### Data collection

If the **Get payment options** response includes a `collectData` object with a `url` field, display it in a WebView before confirming. The WebView handles form rendering, validation, and T&C acceptance. When the WebView signals completion (`IC_COMPLETE` via JS bridge), proceed to confirm — no need to include `collectedData` in the request.

If you choose not to use the WebView and instead build your own form, use the `collectData.schema` JSON schema to determine the required fields, collect the values, and pass them as `collectedData` in the confirm request.

### Expiration handling

Payments have an expiration timestamp (`expiresAt` in the payment info). Display a countdown or warning to the user when time is running low, and prevent submission after expiry.

If a payment or route expires mid-flow, the API returns a `410` (payment expired) or `409` (route expired) error. Handle these gracefully by informing the user and offering to start over if a new payment link is available.

## API Reference

For request/response schemas and examples for each Gateway endpoint, see the **[API Reference](/api-reference)**.
Loading