`.
## Request Body
```json theme={"system"}
{
"network": "base-sepolia",
"tokenAddress": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"owner": "0x742d35Cc6634C0532925a3b8D0c4E5e6C2aE7A3e",
"spender": "0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A",
"value": "1000000",
"deadline": "1893456000",
"v": 27,
"r": "0x...",
"s": "0x...",
"recipient": "0x742d35Cc6634C0532925a3b8D0c4E5e6C2aE7A3e"
}
```
| Field | Required | Notes |
| -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `network` | yes | EVM network identifier (e.g. `base`, `avalanche`, `arbitrum`, `bsc`, `bot-chain`, `base-sepolia`, `arc-testnet`, `bot-chain-testnet`, `optimism`, `polygon`, `unichain`, `ink`, `sei`, `tempo`, `monad`, `robinhood`) |
| `tokenAddress` | yes | ERC-20 token contract address |
| `owner` | yes | Token owner address; must have signed the EIP-2612 permit |
| `spender` | yes | Spender address authorized in the permit signature |
| `value` | yes | Amount in the token's smallest unit as a decimal string (`1000000` = 1 USDC) |
| `deadline` | yes | Unix timestamp after which the permit expires, as a decimal string |
| `v` | yes\* | Signature recovery byte (27 or 28). Provide `v/r/s` OR `signature`, not both. |
| `r` | yes\* | 32-byte hex signature component |
| `s` | yes\* | 32-byte hex signature component |
| `recipient` | yes | Address that receives the transferred tokens |
## Facilitator contract addresses
| Network | Contract |
| ------------------- | -------------------------------------------- |
| `arc-testnet` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `bot-chain-testnet` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `bot-chain` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `base` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `bsc` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `base-sepolia` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `ethereum` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `avalanche` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `optimism` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `optimism-sepolia` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `arbitrum` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `polygon` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `unichain` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `ink` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `sonic` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `worldchain` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `sei` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `hyperevm` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `megaeth` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `tempo` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `monad` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `robinhood` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `fluent-testnet` | `0xB3Ac1B7871942bCdCD0bD6C65765272bBE70B8Da` |
## Response
### Success
```json theme={"system"}
{
"success": true,
"transaction": "0x1234567890abcdef...",
"network": "base-sepolia"
}
```
### Error
```json theme={"system"}
{
"success": false,
"transaction": "",
"network": "base-sepolia",
"errorReason": "invalid_request"
}
```
## Error Codes
| `errorReason` | HTTP | Description |
| ------------------------- | ---- | ----------------------------------------------------------------- |
| `invalid_request` | 400 | Missing or malformed fields in the request body |
| `unsupported_network` | 400 | `network` is not a supported EVM network |
| `network_not_configured` | 400 | The facilitator has no private key configured for this network |
| `invalid_signature` | 400 | Could not resolve a valid `v`, `r`, `s` from the provided inputs |
| `permit_execution_failed` | 500 | On-chain transaction failed (RPC error, revert, bad permit, etc.) |
# Settle x402 Payment
Source: https://docs.mrdn.finance/api-reference/endpoint/settle-payment
POST /v1/settle
Settle an x402 payment with organization-specific authentication. This endpoint supports standard exact EIP-3009 EVM payloads, Circle Gateway batched payloads, and the Permit2 payload used on non-EIP-3009 EVM networks.
Settle an x402 payment on-chain after verification. This endpoint executes the actual blockchain transaction to transfer funds according to the x402 payment authorization.
When `paymentRequirements.extra.name === "GatewayWalletBatched"`, this
endpoint forwards the request to Circle's Gateway API instead of settling
on-chain. See [Circle Gateway
(Batched)](/api-reference/payment-types/circle-gateway) for the batched
payment type and [Payment Types](/api-reference/payment-types/overview) for an
overview of all routing paths.
## Authentication
Requires API key authentication with organization context.
## Recipient
For standard merchant integrations, the wallet that receives settled funds is
configured in your organization settings and tied to your API key. Keep
`paymentRequirements.payTo` set to the Meridian facilitator contract for the
network; do not use `payTo` for your merchant wallet.
Platform and marketplace integrations can route the end payout with
`paymentRequirements.extra.creditedRecipient`. See [Marketplace
Fees](/command-centre/marketplace) for that flow.
## Standard Request Body
```json theme={"system"}
{
"paymentPayload": {
"x402Version": 1,
"scheme": "exact",
"network": "base-sepolia",
"payload": {
"signature": "0x...",
"authorization": {
"from": "0x742d35Cc6634C0532925a3b8D0c4E5e6C2aE7A3e",
"to": "0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A",
"value": "1000000",
"validAfter": "1234567890",
"validBefore": "1234567899",
"nonce": "0x..."
}
}
},
"paymentRequirements": {
"scheme": "exact",
"network": "base-sepolia",
"maxAmountRequired": "1000000",
"resource": "https://example.com/resource",
"description": "Payment for resource access",
"mimeType": "application/json",
"payTo": "0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A",
"maxTimeoutSeconds": 3600,
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
}
}
```
For EIP-3009 payloads, both `authorization.to` and `payTo` must be set to the
facilitator contract address for the network. For Permit2 payloads, keep
`payTo` and `witness.to` bound to the facilitator.
## Cross-Chain EIP-3009 Request Body
Cross-chain USDC settlement uses the same `POST /v1/settle` endpoint and the
same EIP-3009 payload shape. The payment payload is signed on the source chain
where the buyer has USDC. Set `paymentRequirements.network`, `asset`, and
`payTo` for that source chain, then set `paymentRequirements.extra.destinationChainId`
to the destination chain where Meridian should settle after Across fills the
bridge.
For example, a buyer paying from Ink USDC to a seller receiving on Base uses
`network: "ink"` and `destinationChainId: 8453`:
```json theme={"system"}
{
"paymentPayload": {
"x402Version": 1,
"scheme": "exact",
"network": "ink",
"payload": {
"signature": "0x...",
"authorization": {
"from": "0x2222222222222222222222222222222222222222",
"to": "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
"value": "1000000",
"validAfter": "1234567890",
"validBefore": "1234568190",
"nonce": "0x..."
}
}
},
"paymentRequirements": {
"scheme": "exact",
"network": "ink",
"maxAmountRequired": "1000000",
"resource": "https://seller.example/api/tool",
"description": "Payment for resource access",
"mimeType": "application/json",
"payTo": "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
"maxTimeoutSeconds": 300,
"asset": "0x2D270e6886d130D724215A266106e6832161EAEd",
"extra": {
"name": "USD Coin",
"version": "2",
"creditedRecipient": "0x1111111111111111111111111111111111111111",
"destinationChainId": 8453
}
}
}
```
The settlement response transaction hash is the source-chain transaction that
started the Across bridge. The seller receives the destination-chain output
after Across fill and Meridian destination-side settlement.
A seller that accepts payments from multiple source chains should expose one
`paymentRequirements` object per route in the x402 `accepts` array. A
Base-source requirement cannot be paid by a buyer who only has USDC on Ink.
Return an Ink-source requirement with `extra.destinationChainId: 8453` for
that route.
Cross-chain EIP-3009 currently uses Across exact-input routing. If the seller
needs to receive an exact destination-chain amount, quote the route and set
`maxAmountRequired` to include bridge fees.
## Permit2 Request Body
There is no separate `POST /v1/permit2` endpoint. Permit2 payments are settled
through `POST /v1/settle` with the Permit2 payload shape below.
```json theme={"system"}
{
"paymentPayload": {
"x402Version": 1,
"scheme": "exact",
"network": "exampleNetwork",
"payload": {
"signature": "0x...",
"owner": "0x...",
"permit": {
"permitted": {
"token": "0x...",
"amount": "12345"
},
"nonce": "123",
"deadline": "12345678"
},
"witness": {
"to": "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
"validAfter": "0"
}
}
},
"paymentRequirements": {
"scheme": "exact",
"network": "exampleNetwork",
"maxAmountRequired": "12345",
"resource": "https://example.com/resource",
"description": "Payment for resource access",
"mimeType": "application/json",
"payTo": "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
"maxTimeoutSeconds": 3600,
"asset": "0x...."
}
}
```
Permit2 payloads are accepted on every supported network. On `megaeth`, `bsc`,
`bot-chain`, `bot-chain-testnet`, and `tempo` it is the only settlement path,
since their payment tokens do not expose EIP-3009. If the buyer has not already
approved Permit2 for the token, include the optional
`paymentPayload.payload.permit2612` object for tokens that support ERC-2612:
```json theme={"system"}
{
"permit2612": {
"value": "1000000",
"deadline": "1893456000",
"r": "0x0000000000000000000000000000000000000000000000000000000000000000",
"s": "0x0000000000000000000000000000000000000000000000000000000000000000",
"v": 27
}
}
```
On chains where the payment token does not expose EIP-3009, use Permit2
through `x402ExactPermit2Proxy` `0x402085c248EeA27D92E8b30b2C58ed07f9E20001`.
This is the canonical exact Permit2 proxy from the official [x402
repository](https://github.com/x402-foundation/x402/tree/main), deployed at
the same address on supported EVM chains. This includes MegaETH, BSC, and BOT
chain testnet and mainnet. New integrations should keep `payTo` pointed at the
facilitator, set `paymentRequirements.asset` to the ERC-20 token address,
approve Permit2 `0x000000000022D473030F116dDEE9F6B43aC78BA3`, and sign the
Permit2 witness with the proxy as spender. Your backend should still call
Meridian `POST /v1/settle`.
### Upto scheme
For usage-based pricing, set `scheme` to `"upto"` in both the payment payload
and the payment requirements. The buyer signs the Permit2 witness for the
maximum chargeable amount with `x402UptoPermit2Proxy`
`0x402015c795ecb48A360bDC6e35a2EaEb313a0002` as the spender (same address on
every chain), and the witness gains a `facilitator` field:
```json theme={"system"}
{
"witness": {
"to": "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
"facilitator": "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
"validAfter": "0"
}
}
```
At settle time, pass the actual usage amount in
`paymentRequirements.extra.settleAmount` (base units). It must satisfy
`0 < settleAmount ≤ permit.permitted.amount`; if omitted, the full signed
maximum is settled. Fees are computed on the settled amount only.
| Network | Facilitator Contract |
| ------------------- | -------------------------------------------- |
| `arc-testnet` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `bot-chain-testnet` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `bot-chain` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `base` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `bsc` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `base-sepolia` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `avalanche` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `optimism` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `arbitrum` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `optimism-sepolia` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `polygon` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `unichain` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `ink` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `worldchain` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `sei` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `hyperevm` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `megaeth` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `tempo` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `monad` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `robinhood` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
## Response
### Success Response
```json theme={"system"}
{
"success": true,
"transaction": "0x1234567890abcdef...",
"network": "base-sepolia"
}
```
### Error Response
```json theme={"system"}
{
"success": false,
"errorReason": "insufficient_funds",
"transaction": "",
"network": "base-sepolia"
}
```
## Error Codes
* `invalid_payload` - Payment payload format is invalid
* `invalid_payment_requirements` - Payment requirements format is invalid
* `insufficient_funds` - Insufficient balance for settlement
* `unexpected_settle_error` - Unhandled exception during settlement
* `invalid_transaction_state` - On-chain transaction failed
# Get Supported Payment Kinds
Source: https://docs.mrdn.finance/api-reference/endpoint/supported-payments
GET /v1/supported
Get list of supported payment types and networks
Get the list of supported payment types and networks for x402 payments.
## Response
```json theme={"system"}
{
"kinds": [
{
"x402Version": 1,
"scheme": "exact",
"network": "avalanche"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "base"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "bsc"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "bot-chain"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "base-sepolia"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "arc-testnet"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "bot-chain-testnet"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "fluent-testnet"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "optimism"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "arbitrum"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "optimism-sepolia"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "polygon"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "unichain"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "ink"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "worldchain"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "sei"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "hyperevm"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "megaeth"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "tempo"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "monad"
},
{
"x402Version": 1,
"scheme": "exact",
"network": "robinhood"
}
]
}
```
## Payment Kinds
Each payment kind specifies:
* **x402Version**: Version of the x402 protocol (currently 1)
* **scheme**: Payment scheme type (currently "exact")
* **network**: Supported blockchain network
## Supported Networks
Currently supported networks:
### Mainnet
| Network ID | Chain |
| ------------ | --------------- |
| `avalanche` | Avalanche |
| `base` | Base |
| `bsc` | BNB Smart Chain |
| `bot-chain` | BOT Chain |
| `optimism` | Optimism |
| `arbitrum` | Arbitrum One |
| `polygon` | Polygon |
| `unichain` | Unichain |
| `ink` | Ink |
| `worldchain` | World Chain |
| `sei` | Sei |
| `hyperevm` | HyperEVM |
| `megaeth` | MegaETH |
| `tempo` | Tempo |
| `monad` | Monad |
| `robinhood` | Robinhood Chain |
### Testnet
| Network ID | Chain |
| ------------------- | ----------------- |
| `arc-testnet` | Arc Testnet |
| `bot-chain-testnet` | BOT Chain Testnet |
| `base-sepolia` | Base Sepolia |
| `fluent-testnet` | Fluent Testnet |
| `optimism-sepolia` | Optimism Sepolia |
## Usage
```javascript theme={"system"}
const response = await fetch("/v1/supported");
const data = await response.json();
console.log("Supported payment kinds:", data.kinds);
// Check if a specific network is supported
const isOptimismSupported = data.kinds.some(
(kind) => kind.network === "optimism",
);
```
# Verify x402 Payment (Deprecated)
Source: https://docs.mrdn.finance/api-reference/endpoint/verify-payment
POST /v1/verify
Deprecated legacy endpoint for verifying an x402 payment with organization-specific authentication
`POST /v1/verify` is deprecated and retained for legacy integrations only.
Verify an x402 payment with organization-specific authentication. This legacy endpoint validates payment signatures and authorization data according to the x402 protocol specification.
When `paymentRequirements.extra.name === "GatewayWalletBatched"`, verification
is forwarded to Circle's Gateway API. See [Circle Gateway
(Batched)](/api-reference/payment-types/circle-gateway) for that flow and
[Payment Types](/api-reference/payment-types/overview) for an overview.
## Features
* Organization-specific x402 authentication
* Automatic fallback to default authentication
* Authentication context in responses
* Comprehensive error handling
## Request Example
```json theme={"system"}
{
"paymentPayload": {
"x402Version": 1,
"scheme": "exact",
"network": "base-sepolia",
"payload": {
"signature": "0x...",
"authorization": {
"from": "0x742d35Cc6634C0532925a3b8D0c4E5e6C2aE7A3e",
"to": "0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A",
"value": "1000000",
"validAfter": "1234567890",
"validBefore": "1234567899",
"nonce": "0x..."
}
}
},
"paymentRequirements": {
"scheme": "exact",
"network": "base-sepolia",
"maxAmountRequired": "1000000",
"resource": "https://example.com/resource",
"description": "Payment for resource access",
"mimeType": "application/json",
"payTo": "0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A",
"maxTimeoutSeconds": 3600,
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
}
}
```
For EIP-3009 payloads, both `authorization.to` and `payTo` must be set to the
facilitator contract address for the network.
`POST /v1/verify` does not validate the Permit2 payload shape in the current
facilitator. Permit2 payments are settled directly through
[`POST /v1/settle`](/api-reference/endpoint/settle-payment).
| Network | Facilitator Contract |
| ------------------- | -------------------------------------------- |
| `arc-testnet` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `bot-chain-testnet` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `bot-chain` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `base` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `bsc` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `base-sepolia` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `avalanche` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `optimism` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `arbitrum` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `optimism-sepolia` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `polygon` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `unichain` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `ink` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `worldchain` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `sei` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `hyperevm` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `megaeth` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `tempo` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `monad` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `robinhood` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
## Response Example
```json theme={"system"}
{
"isValid": true,
"payer": "0x742d35Cc6634C0532925a3b8D0c4E5e6C2aE7A3e",
"authContext": {
"organizationId": "org_123",
"authMethod": "organization_specific",
"timestamp": "2024-01-01T00:00:00.000Z"
}
}
```
# Chat Completion
Source: https://docs.mrdn.finance/api-reference/inference/chat
POST https://api.mrdn.finance/v1/inference/chat
Paid chat completion, streamed as server-sent events
Runs one chat completion against the selected Dolphin model. This endpoint is x402-protected: unpaid requests receive `402 Payment Required`, and paid requests must include the `X-PAYMENT` header.
## Headers
Must be `application/json`.
Base64-encoded signed x402 payment payload. Omit on the first request to
receive the payment requirements via a 402 response.
## Body
Conversation history as an array of `{ role, content }` objects. Roles are
`user` and `assistant`. Must be non-empty.
Model ID. Must be one of the IDs returned by
[`GET /v1/inference/models`](/api-reference/inference/models). Invalid values return
`400` with the supported list.
Prompt template. Must be one of the names returned by
[`GET /v1/inference/templates`](/api-reference/inference/templates). Invalid values
return `400` with the supported list.
## Response
On success (`200`), the completion is streamed as `text/event-stream`. Each event is an OpenAI-style chunk; concatenate `choices[0].delta.content` across chunks to build the full reply. Settlement details (including the transaction hash) are returned in the `X-PAYMENT-RESPONSE` header.
```bash Unpaid (get quote) theme={"system"}
curl -X POST https://api.mrdn.finance/v1/inference/chat \
-H "Content-Type: application/json" \
-d '{
"messages": [{ "role": "user", "content": "hey" }],
"model": "dolphinserver:24B",
"template": "logical"
}'
```
```typescript x402-fetch (auto-pays) theme={"system"}
import { privateKeyToAccount } from "viem/accounts";
import { wrapFetchWithPayment } from "@meridian/x402-fetch";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const fetchWithPayment = wrapFetchWithPayment(fetch, account);
const response = await fetchWithPayment("https://api.mrdn.finance/v1/inference/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
messages: [{ role: "user", content: "hey" }],
model: "dolphinserver:24B",
template: "logical",
}),
});
for await (const chunk of response.body) {
process.stdout.write(new TextDecoder().decode(chunk));
}
```
```json 402 Payment Required theme={"system"}
{
"x402Version": 1,
"error": {},
"accepts": [
{
"scheme": "exact",
"network": "base",
"maxAmountRequired": "10000",
"resource": "https://api.mrdn.finance/v1/inference/chat",
"description": "One chat completion from Dolphin AI",
"mimeType": "text/event-stream",
"payTo": "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
"maxTimeoutSeconds": 60,
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"extra": { "name": "USD Coin", "version": "2" }
}
]
}
```
```text 200 OK (SSE stream) theme={"system"}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"24B","choices":[{"index":0,"delta":{"role":"assistant","content":"Hey"},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"24B","choices":[{"index":0,"delta":{"content":" there!"},"finish_reason":null}]}
data: [DONE]
```
```json 400 Bad Request theme={"system"}
{
"error": "Unknown model \"gpt-4\"",
"supported": ["dolphinserver:24B", "dolphinserver2:6b"]
}
```
# List Models
Source: https://docs.mrdn.finance/api-reference/inference/models
GET https://api.mrdn.finance/v1/inference/models
Get the available inference models
Returns the models currently available for chat completions. Free — no payment required. Results are cached server-side for 5 minutes.
## Response
List of available models.
Model ID to pass as `model` in [`POST /v1/inference/chat`](/api-reference/inference/chat).
Human-readable model name.
Whether the model accepts image input.
```bash cURL theme={"system"}
curl https://api.mrdn.finance/v1/inference/models
```
```json 200 OK theme={"system"}
{
"data": [
{ "id": "dolphinserver:24B", "label": "Dolphin 24B", "vision": false },
{ "id": "dolphinserver2:6b", "label": "Dolphin X1 Nano", "vision": false }
]
}
```
# Overview
Source: https://docs.mrdn.finance/api-reference/inference/overview
Pay-per-request AI inference over x402
The x402 Inference API exposes Dolphin AI chat completions behind an x402 paywall. There are no API keys and no subscriptions — each chat request is paid for with a single USDC micropayment, authorized by a wallet signature.
## Base URL
The inference API is served by the Meridian facilitator:
```
https://api.mrdn.finance
```
## Endpoints
`POST /v1/inference/chat` — paid, streams SSE
`GET /v1/inference/models` — free
`GET /v1/inference/templates` — free
## How payment works
`POST /v1/inference/chat` is protected by the standard x402 flow:
1. Call the endpoint with no payment — you receive `402 Payment Required` with the accepted payment options (price, network, asset, receiver).
2. Sign an EIP-3009 `TransferWithAuthorization` for the quoted amount (a gasless signature — no transaction, no gas needed).
3. Retry the same request with the signed payment base64-encoded in the `X-PAYMENT` header.
4. The server verifies and settles the payment through the Meridian facilitator, then streams the completion.
Any x402 client handles this automatically — see [Programmatic API Access](/api-reference/programmatic-access) for `x402-fetch` / `x402-axios` examples that work against this API unchanged.
## Models
| ID | Name |
| ------------------- | --------------- |
| `dolphinserver:24B` | Dolphin 24B |
| `dolphinserver2:6b` | Dolphin X1 Nano |
## Templates
| Name | Label |
| --------------- | ------------- |
| `logical` | Logical |
| `creative` | Creative |
| `summary` | Summarize |
| `code-beginner` | Code Beginner |
| `code-advanced` | Code Advanced |
Models and templates are sourced live from the upstream provider — always
fetch the current lists from `GET /v1/inference/models` and `GET /v1/inference/templates`
rather than hardcoding them.
# List Templates
Source: https://docs.mrdn.finance/api-reference/inference/templates
GET https://api.mrdn.finance/v1/inference/templates
Get the available prompt templates
Returns the prompt templates that shape the model's response style. Free — no payment required. Results are cached server-side for 5 minutes.
## Response
List of available templates.
Template name to pass as `template` in [`POST /v1/inference/chat`](/api-reference/inference/chat).
Human-readable template name.
```bash cURL theme={"system"}
curl https://api.mrdn.finance/v1/inference/templates
```
```json 200 OK theme={"system"}
{
"data": [
{ "name": "logical", "label": "Logical" },
{ "name": "creative", "label": "Creative" },
{ "name": "summary", "label": "Summarize" },
{ "name": "code-beginner", "label": "Code Beginner" },
{ "name": "code-advanced", "label": "Code Advanced" }
]
}
```
# Overview
Source: https://docs.mrdn.finance/api-reference/introduction
Complete API documentation for Meridian x402 payments
Welcome to the Meridian API documentation. This guide covers all endpoints for x402 payments, facilitator-backed settlement, and related organization features.
## Base URL
All API requests are made to the following base URL:
```
https://api.mrdn.finance/v1
```
## Authentication
Meridian Protocol supports API key authentication for server-to-server & client-to-server integrations:
```bash theme={"system"}
curl -X POST https://api.mrdn.finance/v1/settle \
-H "Authorization: Bearer pk_..." \
-H "Content-Type: application/json" \
-d '{
"paymentPayload": { "...": "..." },
"paymentRequirements": { "...": "..." }
}'
```
## Core Endpoints
### x402 Payments
`POST /v1/verify` is deprecated and should only be used by existing legacy
integrations.
`POST /v1/verify` - Legacy x402 payment verification endpoint
`POST /v1/settle` - Settle verified payment
`POST /v1/permit` - Execute an ERC-2612 permit-backed token transfer
`GET /v1/supported` - Get supported payment types
## Error Handling
All endpoints return consistent error responses with the HTTP status code mirrored in the body:
```json theme={"system"}
{
"type": "api_error",
"code": 401,
"message": "You are not authorized to access this resource."
}
```
### Common Error Codes
* `400 Bad Request` - The request is unacceptable
* `401 Not Authorized` - Missing or invalid authentication
* `403 Forbidden` - You do not have permission to perform the request
* `404 Not Found` - This object was not found
* `409 Conflict` - There was an issue adding or updating this resource
## Examples
### Node.js (Backend)
```javascript theme={"system"}
const response = await fetch("https://api.mrdn.finance/v1/settle", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.MERIDIAN_API_KEY}`,
},
body: JSON.stringify({
paymentPayload: {
/* ... */
},
paymentRequirements: {
/* ... */
},
}),
});
```
## Webhooks (Coming Soon)
Meridian supports webhooks for payment events:
* `payment.verified` - Payment successfully verified
* `payment.failed` - Payment verification failed
* `payment.settled` - Payment successfully settled
Configure webhooks in your developer dashboard or via API.
# Manual Integration
Source: https://docs.mrdn.finance/api-reference/manual-integration
Integrate x402 payments into your frontend with viem — no SDK required
This guide shows the full x402 payment flow from a custom frontend using only
`viem`. Your resource server owns pricing, builds the `accepts` challenge, and
calls Meridian to settle the signed payment. The browser requests the resource,
signs the selected payment requirement, and resubmits the signed payload.
If you only need the shortest possible path on one network, start with the
[Quickstart](/quickstart). This guide adds multi-chain challenges, requirement
selection, and error handling on top of it.
## Prerequisites
* A frontend with wallet connection (MetaMask, WalletConnect, etc.)
* A protected resource endpoint that returns an x402 `402 Payment Required` challenge
* A server-side Meridian API key for the resource server
## Installation
```bash theme={"system"}
npm install viem
```
## Environment Setup
Keep the Meridian API key on your server. The browser only needs to know your
resource URL.
```bash theme={"system"}
# Browser-exposed client config
NEXT_PUBLIC_RESOURCE_URL=https://your-api.example.com/api/premium
# Server-side resource server config
MERIDIAN_API_KEY=pk_test_...
```
## Client Implementation
### 1. Wallet Connection
```typescript theme={"system"}
import { createWalletClient, custom, type WalletClient } from "viem";
// Import the chain(s) your app supports, e.g. base, optimism, ink, ...
import { base } from "viem/chains";
const connectWallet = async () => {
const ethereum = (window as any).ethereum;
if (!ethereum) {
throw new Error("Please install MetaMask or another wallet extension");
}
const accounts = (await ethereum.request({
method: "eth_requestAccounts",
})) as `0x${string}`[];
if (accounts.length === 0) {
throw new Error("No wallet account selected");
}
const account = accounts[0];
const walletClient = createWalletClient({
account,
transport: custom(ethereum),
chain: base, // the chain the buyer pays from
});
return { account, walletClient };
};
```
### 2. Request the Protected Resource
Request the resource without payment first. A `402` response carries the
challenge with one payment requirement per accepted source chain.
```typescript theme={"system"}
interface PaymentRequirements {
scheme: string;
network: string;
asset: string;
payTo: string;
maxAmountRequired: string;
resource: string;
description: string;
mimeType: string;
maxTimeoutSeconds: number;
extra?: {
name?: string;
version?: string;
creditedRecipient?: string;
destinationChainId?: number;
};
}
interface X402Challenge {
x402Version: number;
accepts: PaymentRequirements[];
error?: string;
}
const RESOURCE_URL = process.env.NEXT_PUBLIC_RESOURCE_URL!;
const requestResource = async (
walletClient: WalletClient,
account: `0x${string}`,
) => {
const response = await fetch(RESOURCE_URL);
if (response.status === 402) {
const challenge = (await response.json()) as X402Challenge;
return payAndRetry(challenge, walletClient, account);
}
if (!response.ok) {
throw new Error(`Resource request failed: ${response.status}`);
}
return response.json();
};
```
### 3. Select the Payment Requirement
Pick the `accepts` entry whose `network` matches the buyer's connected chain.
A requirement is source-chain specific — a Base entry cannot be paid from Ink,
because the EIP-712 signature domain includes the source chain id and source
token contract.
```typescript theme={"system"}
// Chain ids for the networks your app supports
const NETWORK_CHAIN_IDS: Record = {
"base-sepolia": 84532,
base: 8453,
ink: 57073,
optimism: 10,
};
const selectRequirement = (
accepts: PaymentRequirements[],
connectedChainId: number,
): PaymentRequirements => {
const match = accepts.find(
(entry) => NETWORK_CHAIN_IDS[entry.network] === connectedChainId,
);
if (!match) {
throw new Error("No payment route matches the connected wallet network");
}
return match;
};
```
### 4. Sign and Retry
Sign the EIP-3009 `TransferWithAuthorization` as typed data and resubmit the
request with the signed payload. The verifying contract is the token
(`requirement.asset`), not the facilitator, and `authorization.to` is the
facilitator (`requirement.payTo`).
```typescript theme={"system"}
import { bytesToHex } from "viem";
const payAndRetry = async (
challenge: X402Challenge,
walletClient: WalletClient,
account: `0x${string}`,
) => {
const chainId = walletClient.chain!.id;
const requirement = selectRequirement(challenge.accepts, chainId);
const now = BigInt(Math.floor(Date.now() / 1000));
const authorization = {
from: account,
to: requirement.payTo as `0x${string}`,
value: BigInt(requirement.maxAmountRequired),
validAfter: 0n,
validBefore: now + BigInt(requirement.maxTimeoutSeconds),
nonce: bytesToHex(crypto.getRandomValues(new Uint8Array(32))),
};
const signature = await walletClient.signTypedData({
account,
domain: {
name: requirement.extra?.name ?? "USD Coin",
version: requirement.extra?.version ?? "2",
chainId,
verifyingContract: requirement.asset as `0x${string}`,
},
types: {
TransferWithAuthorization: [
{ name: "from", type: "address" },
{ name: "to", type: "address" },
{ name: "value", type: "uint256" },
{ name: "validAfter", type: "uint256" },
{ name: "validBefore", type: "uint256" },
{ name: "nonce", type: "bytes32" },
],
},
primaryType: "TransferWithAuthorization",
message: authorization,
});
const paymentPayload = {
x402Version: 1,
scheme: "exact",
network: requirement.network,
payload: {
signature,
authorization: {
from: authorization.from,
to: authorization.to,
value: authorization.value.toString(),
validAfter: authorization.validAfter.toString(),
validBefore: authorization.validBefore.toString(),
nonce: authorization.nonce,
},
},
};
const response = await fetch(RESOURCE_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ paymentPayload }),
});
if (response.status === 402) {
const body = await response.json();
throw new Error(body?.error ?? "Payment was rejected");
}
if (!response.ok) {
throw new Error(`Paid resource request failed: ${response.status}`);
}
return response.json();
};
```
On chains whose payment token does not support EIP-3009 (MegaETH, BSC, BOT
chain, Tempo), the buyer signs a Permit2 witness instead of
`TransferWithAuthorization`. That is a separate payload shape and signing
flow, not a small variation of the code above. See the [non-EIP-3009
guide](/ai-skills/non-eip-3009) for the Permit2 implementation.
## Server Responsibilities
Your resource server must not trust buyer-supplied pricing, recipient, network,
or token data. Build or look up the matching `paymentRequirements` server-side,
validate that the signed payload is bound to that requirement, then settle the
buyer's `paymentPayload` through Meridian:
```typescript theme={"system"}
const paymentRequirements = lookupRequirementForAcceptedNetwork(
paymentPayload.network,
);
if (!paymentRequirements) {
throw new Error("Unsupported payment network");
}
if (paymentPayload.network !== paymentRequirements.network) {
throw new Error("Payment network does not match the server requirement");
}
if (
paymentPayload.payload.authorization.to.toLowerCase() !==
paymentRequirements.payTo.toLowerCase()
) {
throw new Error("Payment must authorize the Meridian facilitator");
}
if (
paymentPayload.payload.authorization.value !==
paymentRequirements.maxAmountRequired
) {
throw new Error("Payment amount does not match the server price");
}
```
```typescript theme={"system"}
const response = await fetch("https://api.mrdn.finance/v1/settle", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MERIDIAN_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ paymentPayload, paymentRequirements }),
});
const result = await response.json();
if (!response.ok || !result.success) {
throw new Error(result.errorReason ?? "Meridian settlement failed");
}
```
For multi-chain sellers, include one `paymentRequirements` object per source
chain in `accepts`. Set `network`, `asset`, and `payTo` for the source chain,
then set `extra.destinationChainId` to the destination chain where Meridian
should settle after Across fills. Add `extra.creditedRecipient` when the payout
should go to a specific merchant or marketplace recipient — see
[Marketplace Fees](/command-centre/marketplace).
The full request shape, including cross-chain and Permit2 payloads, is
documented in [Settle x402 Payment](/api-reference/endpoint/settle-payment).
# Overview
Source: https://docs.mrdn.finance/api-reference/payment-types/circle-gateway
Gas-free, batched USDC nanopayments routed through Circle's Gateway API
The Nanopayments Gateway is Meridian's integration of [Circle Gateway nanopayments](https://developers.circle.com/gateway/nanopayments). The buyer funds a unified USDC balance once on any supported chain, then makes many gas-free, sub-cent (\$0.000001 minimum) payments that Circle batches into a single onchain settlement. Each individual x402 payment is verified instantly by signature, while Circle's Gateway System aggregates the signed authorizations and settles net positions in bulk. The Meridian facilitator wraps Circle's `@circle-fin/x402-batching/server` SDK and exposes it through the standard `/v1/verify` and `/v1/settle` endpoints.
Deposit and withdraw USDC against the Gateway Wallet contract from a hosted UI.
## Endpoints
`POST /v1/settle` settles a batched payment via Circle Gateway.
`POST /v1/verify` verifies a batched payment without settling.
`GET /v1/batched-sample` reports Gateway connectivity for diagnostics.
The buyer never submits an on-chain transaction at payment time. Funds move from their pre-funded Gateway Wallet balance through Circle's batched settlement. Withdrawals from the Gateway Wallet are subject to a 7-day delay enforced by the Gateway Wallet contract.
## Detection
A payment is routed through the Nanopayments Gateway when **both** of these are present in `paymentRequirements.extra`:
```json theme={"system"}
{
"extra": {
"name": "GatewayWalletBatched",
"version": "1"
}
}
```
This check is performed by `isBatchPayment()` from `@circle-fin/x402-batching/server` inside the facilitator's `/v1/verify` and `/v1/settle` handlers. There are **no separate URLs** for batched flows. Clients call the same endpoints used for default x402 settlement, and the facilitator inspects `extra` to decide where to forward the request.
## Supported networks
`isGatewayEnabledForNetwork()` returns `true` for every network listed below. Testnets are always enabled, and mainnets are gated by the `GATEWAY_MAINNET_ENABLED` flag in the facilitator (currently `true`). The Meridian facilitator will accept requests for these networks and forward them to Circle.
Networks listed in the facilitator's CAIP-2 map are **not** currently supported
by Circle's Gateway API for nanopayments, including `bsc`, `fluent-testnet`,
`ink`, `megaeth`, and `tempo`. The facilitator will forward the request, but Circle will
reject it. See Circle's [Gateway Supported
Blockchains](https://developers.circle.com/gateway/references/supported-blockchains)
for the authoritative list (column `Nanopayments: Yes`). Networks marked
with `[!]` below are configured locally but not yet supported by Circle.
### Testnets
| Network | CAIP-2 chain ID | Circle domain | Gateway Wallet | USDC |
| ---------------------- | ----------------- | :-----------: | -------------------------------------------- | -------------------------------------------- |
| `arc-testnet` | `eip155:5042002` | 26 | `0x0077777d7EBA4688BDeF3E311b846F25870A19B9` | `0x3600000000000000000000000000000000000000` |
| `base-sepolia` | `eip155:84532` | 6 | `0x0077777d7EBA4688BDeF3E311b846F25870A19B9` | `0x036CbD53842c5426634e7929541eC2318f3dCF7e` |
| `optimism-sepolia` | `eip155:11155420` | 2 | `0x0077777d7EBA4688BDeF3E311b846F25870A19B9` | `0x5fd84259d66Cd46123540766Be93DFE6D43130D7` |
| `fluent-testnet` `[!]` | `eip155:20994` | n/a | `0x0077777d7EBA4688BDeF3E311b846F25870A19B9` | n/a |
### Mainnets
| Network | CAIP-2 chain ID | Circle domain | Gateway Wallet | USDC |
| --------------- | --------------- | :-----------: | -------------------------------------------- | -------------------------------------------- |
| `ethereum` | `eip155:1` | 0 | `0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE` | `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48` |
| `base` | `eip155:8453` | 6 | `0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE` | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |
| `optimism` | `eip155:10` | 2 | `0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE` | `0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85` |
| `arbitrum` | `eip155:42161` | 3 | `0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE` | `0xaf88d065e77c8cC2239327C5EDb3A432268e5831` |
| `avalanche` | `eip155:43114` | 1 | `0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE` | `0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E` |
| `bsc` `[!]` | `eip155:56` | n/a | `0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE` | `0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d` |
| `polygon` | `eip155:137` | 7 | `0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE` | `0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359` |
| `unichain` | `eip155:130` | 10 | `0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE` | `0x078d782b760474a361dda0af3839290b0ef57ad6` |
| `ink` `[!]` | `eip155:57073` | n/a | `0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE` | `0x2D270e6886d130D724215A266106e6832161EAEd` |
| `sonic` | `eip155:146` | 13 | `0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE` | `0x29219dd400f2Bf60E5a23d13Be72B486D4038894` |
| `worldchain` | `eip155:480` | 14 | `0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE` | `0x79A02482A880bCe3F13E09da970dC34dB4cD24D1` |
| `sei` | `eip155:1329` | 16 | `0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE` | `0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392` |
| `hyperevm` | `eip155:999` | 19 | `0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE` | `0xb88339CB7199b77E23DB6E890353E22632Ba630f` |
| `megaeth` `[!]` | `eip155:4326` | n/a | `0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE` | n/a |
The Gateway Wallet addresses are deployed by Circle at the same address on every supported EVM chain (verified against [Circle's contract addresses page](https://developers.circle.com/gateway/references/contract-addresses)).
The facilitator forwards batched requests to:
* **Testnet:** `https://gateway-api-testnet.circle.com` (explicit URL passed to `BatchFacilitatorClient`).
* **Mainnet:** the default URL baked into `@circle-fin/x402-batching/server`. The facilitator constructs `new BatchFacilitatorClient()` with no `url` override.
Both clients are lazy-initialized singletons.
## Funding the Gateway Wallet
Buyers fund the Gateway Wallet contract on each source chain they want to spend from. Available balance is unified across deposits, so a single signed payment can be settled from any chain that has been funded.
### Deposit flow
1. `USDC.approve(gatewayWallet, value)`. One-time per source chain.
2. `GatewayWallet.deposit(usdcAddress, value)`. Pulls USDC and credits the depositor's balance. Circle also exposes `depositFor`, `depositWithPermit`, and `depositWithAuthorization` on the wallet contract.
3. After the deposit transaction is finalized onchain, the credit becomes part of `availableBalance` and can be spent. **Time-to-finality is chain-specific**:
| Chain family | Confirmations | Approx. time |
| --------------------------------------------------- | --------------- | ----------------- |
| Ethereum, Arbitrum, Base, OP, Unichain, World Chain | \~65 ETH blocks | \~13 – 19 minutes |
| Avalanche, Sonic | \~1 | \~8 seconds |
| HyperEVM, Sei | \~1 | \~5 seconds |
| Polygon PoS | \~2 – 3 | \~8 seconds |
Source: Circle's [Required block confirmations](https://developers.circle.com/gateway/references/supported-blockchains#required-block-confirmations) table.
Sending USDC to the Gateway Wallet via a plain ERC-20 `transfer` instead of
one of the deposit methods will result in **loss of funds**. Always call a
`deposit*` method on the wallet contract.
### Withdrawal flow
Circle's Gateway Wallet supports two withdrawal paths:
* **Instant** (preferred): submit a same-chain transfer through the Gateway API. Funds round-trip through a burn on the source chain and a mint on the destination (same chain), so the withdrawal still requires a user-signed authorization. Pays only burn-tx gas.
* **Trustless** (fallback for when Circle's API is unavailable): on-chain only, with a 7-day delay enforced by the `withdrawalBlock` value on the Gateway Wallet contract.
The hosted [Nanopayments Gateway UI](https://nanopayments.mrdn.finance/) currently exposes the trustless path:
1. `GatewayWallet.initiateWithdrawal(usdc, value)`. Moves balance from `availableBalance` to `withdrawingBalance` and records `withdrawalBlock`.
2. After `block.number >= withdrawalBlock`, call `GatewayWallet.withdraw(usdc)`. Moves the unlocked amount from `withdrawableBalance` back to the buyer's wallet.
Source: Circle's [Withdrawal documentation](https://developers.circle.com/gateway/references/technical-guide#withdrawal).
### Balance views
The Gateway Wallet exposes per-token, per-depositor views the SDK reads:
| View | Meaning |
| --------------------- | ----------------------------------------------------------- |
| `availableBalance` | Spendable balance for nanopayments |
| `withdrawingBalance` | Amount in the 7-day delay window |
| `withdrawableBalance` | Amount past the delay, ready to claim |
| `totalBalance` | `available + withdrawing + withdrawable` |
| `withdrawalBlock` | Block at which a pending withdrawal becomes withdrawable |
| `isTokenSupported` | `true` if the Gateway Wallet accepts deposits of this token |
The hosted [Nanopayments Gateway UI](https://nanopayments.mrdn.finance/) wraps these calls so end users do not have to call the contract directly.
## `extra` field reference
In the Nanopayments Gateway path, only `extra.name` and `extra.version` are read by the Meridian facilitator. They are the routing trigger that `isBatchPayment()` checks. Everything else inside `extra` is **passed through** to Circle's Gateway API verbatim by `transformForGateway()`, which spreads `paymentRequirements` and overrides `network`, `asset`, and `amount` only.
| Field | Required | Read by Meridian? | Description |
| -------------------- | :------: | :---------------: | -------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | ✓ | Routing only | Must be the literal string `"GatewayWalletBatched"`. Together with `version`, it is the trigger for `isBatchPayment()`. |
| `version` | ✓ | Routing only | Must be the literal string `"1"`. |
| `verifyingContract` | | No (pass-through) | Gateway Wallet contract address used by the **client SDK** as the EIP-712 `verifyingContract` when signing. |
| `creditedRecipient` | | No (pass-through) | Forwarded to Circle. Note: in the **default x402 path** Meridian reads this field, but the batched path returns before that code runs. |
| `platform` | | No (pass-through) | Forwarded to Circle. The `platform` / `platformFeeBps` settlement logic in the facilitator is not executed in the batched path. |
| `platformFeeBps` | | No (pass-through) | Forwarded to Circle. Gateway batched payments do not currently charge a Meridian platform fee. |
| `destinationChainId` | | No (pass-through) | Forwarded to Circle. |
The buyer-side SDK sets `paymentRequirements.asset` to the Gateway Wallet contract so the EIP-712 domain has the correct `verifyingContract`. `transformForGateway()` swaps that back to the network's USDC address (from `NETWORK_USDC`) before forwarding to Circle, since Circle expects the actual token address.
## Implementation notes
* The facilitator-side glue lives in [`apps/facilitator/src/gateway/index.ts`](https://github.com/meridian-protocol/meridian-protocol/blob/main/apps/facilitator/src/gateway/index.ts). It owns the testnet/mainnet client routing, the Gateway Wallet ↔ USDC asset swap, and the CAIP-2 network mapping that Circle's API requires.
* The deposit/withdraw UI lives in [`apps/circle-gateway`](https://github.com/meridian-protocol/meridian-protocol/tree/main/apps/circle-gateway) and is also hosted at [`nanopayments.mrdn.finance`](https://nanopayments.mrdn.finance/).
* Circle recommends calling `settle()` directly for production batched flows rather than the legacy `verify()` + `settle()` two-step.
## See also
### Meridian
* [Payment Types](/api-reference/payment-types/overview)
* [Settle Batched Payment](/api-reference/endpoint/batched-settle)
* [Verify Batched Payment](/api-reference/endpoint/batched-verify)
* [Gateway Status](/api-reference/endpoint/batched-sample)
* [Roadmap: Circle Nanopayments](/roadmap)
### Circle (authoritative source for the upstream API and contracts)
* [Circle Nanopayments overview](https://developers.circle.com/gateway/nanopayments)
* [Circle Gateway technical guide](https://developers.circle.com/gateway/references/technical-guide)
* [Circle Gateway supported blockchains](https://developers.circle.com/gateway/references/supported-blockchains)
* [Circle Gateway contract addresses](https://developers.circle.com/gateway/references/contract-addresses)
# Payment Types
Source: https://docs.mrdn.finance/api-reference/payment-types/overview
Payment schemes and settlement paths supported by the Meridian facilitator
The Meridian facilitator accepts several payment payload types through `POST /v1/settle`. The facilitator inspects each settle request and routes it to the correct settlement path automatically; clients do not call a separate endpoint for Permit2, Circle Gateway, or Solana settlement.
## Supported types
Default scheme. Buyer signs an EIP-3009 `transferWithAuthorization` for USDC
and Meridian settles through `X402ProxyFacilitator` on the destination
chain. Use this path when the payment token natively exposes EIP-3009.
Current path on MegaETH, BSC, and BOT chain when the token does not expose
EIP-3009. Buyer approves Permit2 once, then signs a witness authorization
that Meridian settles through `x402ExactPermit2Proxy`.
Usage-based pricing on any supported network. Buyer signs a Permit2 witness
authorization for a maximum amount; Meridian settles the actual usage
amount (≤ the signed max) through `x402UptoPermit2Proxy`.
Gas-free, batched USDC nanopayments backed by Circle's Gateway Wallet.
Detected via `paymentRequirements.extra.name === "GatewayWalletBatched"`.
USDC payments on Solana settled through the `meridian_x402` program. The
buyer signs the settlement transaction and the facilitator co-signs as fee
payer. Detected via `network === "solana"` / `"solana-devnet"`.
## Comparison
| Capability | x402 (EIP-3009) | Permit2 fallback | Circle Gateway Batched |
| ----------------------- | --------------------------------------------- | ----------------------------------------- | -------------------------------------------------------------------- |
| Tokens | USDC | Any ERC-20 | USDC only |
| Minimum payment | Token-decimal granularity | Token-decimal granularity | \$0.000001 USDC |
| Settlement target | `X402ProxyFacilitator` | `x402ExactPermit2Proxy` (via facilitator) | Circle Gateway API |
| Buyer one-time setup | None | `approve(Permit2, ∞)` | Deposit USDC into Gateway Wallet |
| Per-payment signing | EIP-3009 typed data | Permit2 witness typed data | EIP-712 typed data over Gateway Wallet domain |
| Gas paid by buyer | None | None | None |
| Cross-chain | Same-chain or Across via `destinationChainId` | Same-chain | Unified balance across all funded chains |
| Buyer experience | \< 2s same-chain; Across fill for cross-chain | \< 2s on-chain settlement | Instant signature verification; onchain settlement batched by Circle |
| Platform fee / cashback | Supported | Supported | Not applied (Meridian fee logic is skipped on the batched path) |
## Upto scheme (usage-based pricing)
The `upto` scheme decouples the signed authorization from the settled amount:
the buyer signs a Permit2 witness authorization for a **maximum** amount before
consuming the resource, and the seller settles the **actual** usage amount
afterwards. It is available on every supported network, since it always settles
through Permit2 (`x402UptoPermit2Proxy` at
`0x402015c795ecb48A360bDC6e35a2EaEb313a0002`, the same address on every chain).
Differences from the exact Permit2 flow:
* `paymentRequirements.scheme` is `"upto"` and `maxAmountRequired` is the cap
the buyer signs, not the final price.
* The buyer signs with `x402UptoPermit2Proxy` as the Permit2 spender, and the
witness carries an extra `facilitator` field bound to the Meridian
facilitator contract: `{ to, facilitator, validAfter }`.
* At settle time the seller passes the final amount as
`paymentRequirements.extra.settleAmount` (base units, must be
`0 < settleAmount ≤ maxAmountRequired`). If omitted, the full signed maximum
is settled. Platform fees, treasury fees, and cashback all apply to the
settled amount only.
## Accepting payments from multiple chains
An x402 challenge can expose multiple payment routes in `accepts`. Each route
is a full `paymentRequirements` object for the source chain the buyer will pay
from. The buyer or SDK selects the requirement that matches the connected wallet
chain, then signs against that source chain's token contract.
For example, a seller that wants to receive settlement on Base while allowing
buyers to pay from Base, Ink, or Optimism would return one requirement per
source chain:
```json theme={"system"}
{
"x402Version": 1,
"accepts": [
{
"scheme": "exact",
"network": "base",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
"maxAmountRequired": "1000000",
"resource": "https://seller.example/api/tool",
"description": "Paid access",
"mimeType": "application/json",
"maxTimeoutSeconds": 300,
"extra": {
"name": "USD Coin",
"version": "2",
"creditedRecipient": "0x1111111111111111111111111111111111111111",
"destinationChainId": 8453
}
},
{
"scheme": "exact",
"network": "ink",
"asset": "0x2D270e6886d130D724215A266106e6832161EAEd",
"payTo": "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
"maxAmountRequired": "1000000",
"resource": "https://seller.example/api/tool",
"description": "Paid access",
"mimeType": "application/json",
"maxTimeoutSeconds": 300,
"extra": {
"name": "USD Coin",
"version": "2",
"creditedRecipient": "0x1111111111111111111111111111111111111111",
"destinationChainId": 8453
}
},
{
"scheme": "exact",
"network": "optimism",
"asset": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
"payTo": "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
"maxAmountRequired": "1000000",
"resource": "https://seller.example/api/tool",
"description": "Paid access",
"mimeType": "application/json",
"maxTimeoutSeconds": 300,
"extra": {
"name": "USD Coin",
"version": "2",
"creditedRecipient": "0x1111111111111111111111111111111111111111",
"destinationChainId": 8453
}
}
]
}
```
For a cross-chain EIP-3009 payment, `network`, `asset`, and `payTo` describe
the source chain. `extra.destinationChainId` describes the destination chain
where Meridian settles after Across fills the bridge. A Base-only requirement
cannot be paid from Ink; the seller must expose an Ink-source requirement for an
Ink-funded buyer.
Across uses exact-input routing in the current flow. If the seller must receive
an exact destination-chain amount, quote the route and set the source-chain
`maxAmountRequired` high enough to cover Across fees.
## How routing works
`POST /v1/settle` follows this decision tree. It distinguishes between EIP-3009 and Permit2 by trying the standard payment payload first and falling back to the Permit2 payload:
```mermaid theme={"system"}
flowchart TD
A[Incoming payment] --> S{isSupportedSolanaNetwork(network)?
network == "solana" or "solana-devnet"}
S -- Yes --> SV[Solana path
meridian_x402 program settlement]
S -- No --> B{isBatchPayment(paymentRequirements)
extra.name == "GatewayWalletBatched"
and extra.version == "1"?}
B -- Yes --> F{isGatewayEnabledForNetwork(network)?}
F -- Yes --> H[Forward to Circle Gateway API
via BatchFacilitatorClient]
F -- No --> G[HTTP 403
errorReason: gateway_not_enabled]
B -- No --> C{Payload parses as
Permit2 payload?}
C -- No --> D[Default x402 path
X402ProxyFacilitator on-chain]
C -- Yes --> E[Permit2 path
x402ExactPermit2Proxy]
```
The Solana branch is checked first, keyed off `paymentPayload.network`; a
`solana` / `solana-devnet` payment is routed to the `meridian_x402` program
settlement path (the payload carries a base64 `transaction` instead of an
EIP-3009 or Permit2 authorization). See [Solana Program](/payments/solana-program).
The "is this a batched payment?" check is implemented via [`isBatchPayment`](https://www.npmjs.com/package/@circle-fin/x402-batching) from `@circle-fin/x402-batching/server`. It looks at `paymentRequirements.extra` only; the rest of the request body keeps the same x402 v1 shape for EIP-3009 and Circle Gateway paths.
Inside the default EIP-3009 path, Meridian compares the source chain from
`paymentPayload.network` with `paymentRequirements.extra.destinationChainId`.
If they differ, the facilitator pulls source-chain USDC and routes the
destination-chain settlement through Across. If they match or
`destinationChainId` is omitted, settlement stays on the source chain.
## Choosing a payment type
* **Building a typical x402 paywall on Base, Optimism, Arbitrum, Polygon, etc.** → Exact (EIP-3009). Nothing extra to set up for native EIP-3009 tokens; follow the [Quickstart](/quickstart).
* **Accepting USDC from several source chains while settling to one destination chain** → Exact (EIP-3009) with one `accepts` entry per source chain and `extra.destinationChainId` set on routes that should settle elsewhere via Across.
* **Integrating Avalanche, Sei, or Arc Testnet on the [Instant demo](https://instant.mrdn.finance)** → Exact (EIP-3009), **same-chain only**. Use matching source and destination network ids; Across cross-chain is not used on these chains. See [Supported Networks](/api-reference/supported-networks).
* **Integrating MegaETH, BSC, or BOT chain testnet/mainnet when no EIP-3009 token is present** → Permit2 via `x402ExactPermit2Proxy` `0x402085c248EeA27D92E8b30b2C58ed07f9E20001`. Buyers approve Permit2 `0x000000000022D473030F116dDEE9F6B43aC78BA3`, sign with the proxy as spender, and keep facilitator fields bound to Meridian. See [Smart Contracts](/payments/smart-contracts) and [Supported Networks](/api-reference/supported-networks).
* **Usage-based pricing (metered APIs, per-token inference, pay-per-result) where the final price is only known after serving the request** → Upto via `x402UptoPermit2Proxy` `0x402015c795ecb48A360bDC6e35a2EaEb313a0002`, on any supported network. Buyer signs the maximum; seller settles the metered amount via `extra.settleAmount`.
* **High-frequency, sub-cent agent-to-agent payments where zero fees and unified balance matter more than per-tx settlement speed** → [Circle Gateway Batched](/api-reference/payment-types/circle-gateway).
* **Accepting USDC on Solana** → Solana (SVM) via the `meridian_x402` program, same-chain only. The buyer signs the settlement transaction and the facilitator co-signs as fee payer. See [Solana Program](/payments/solana-program) and the [Solana payments](/ai-skills/solana) guide.
Do not mix the signing flows. EIP-3009 routes use a
`TransferWithAuthorization` authorization under `paymentPayload.payload`.
Permit2 routes use `owner`, `permit`, and `witness` fields instead. Solana
routes carry a base64-encoded, payer-signed `transaction` under
`paymentPayload.payload`. All are submitted to `POST /v1/settle`, but the
signing code and payload shape are different.
## Reference
* [`POST /v1/verify`](/api-reference/endpoint/verify-payment): deprecated verification entrypoint for EIP-3009 and Circle Gateway payloads.
* [`POST /v1/settle`](/api-reference/endpoint/settle-payment): settlement entrypoint for EIP-3009, Permit2, and Circle Gateway payloads.
* [`GET /v1/supported`](/api-reference/endpoint/supported-payments): list of `{ x402Version, scheme, network }` triples the facilitator accepts.
# Programmatic API Access
Source: https://docs.mrdn.finance/api-reference/programmatic-access
Call x402-protected APIs from scripts, backends, and AI agents
## Overview
Any API protected by Meridian x402 can be consumed programmatically — no browser or manual wallet interaction required. Your client holds a funded wallet, and payments are authorized by signing an EIP-3009 message (a gasless signature, not a transaction). The flow is:
1. Call the endpoint normally.
2. Receive `402 Payment Required` with a list of accepted payment options.
3. Sign a payment authorization with your wallet.
4. Retry the request with the signed payment in the `X-PAYMENT` header.
The SDKs below handle steps 2–4 automatically.
## Prerequisites
* A wallet private key with USDC on a [supported network](/api-reference/supported-networks)
* The URL of an x402-protected endpoint
Payments are authorized via signature only — your client never submits a
transaction and does not need native gas tokens. The facilitator settles
on-chain on your behalf.
## Using fetch (`x402-fetch`)
Wrap the native `fetch` so 402 responses are paid and retried automatically:
```bash theme={"system"}
npm install @meridian/x402-fetch viem
```
```typescript theme={"system"}
import { privateKeyToAccount } from "viem/accounts";
import { wrapFetchWithPayment } from "@meridian/x402-fetch";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
// maxValue caps how much a single request may cost (base units, 6 decimals)
const fetchWithPayment = wrapFetchWithPayment(
fetch,
account,
BigInt(0.1 * 10 ** 6), // allow up to 0.10 USDC per request
);
const response = await fetchWithPayment("https://api.example.com/paid-endpoint", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: "hello" }),
});
const data = await response.json();
```
If the endpoint costs more than `maxValue`, the wrapper throws instead of paying.
## Using axios (`x402-axios`)
```bash theme={"system"}
npm install @meridian/x402-axios viem
```
```typescript theme={"system"}
import axios from "axios";
import { privateKeyToAccount } from "viem/accounts";
import { withPaymentInterceptor } from "@meridian/x402-axios";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const api = withPaymentInterceptor(
axios.create({ baseURL: "https://api.example.com" }),
account,
);
const { data } = await api.post("/paid-endpoint", { query: "hello" });
```
## Manual flow (any language)
If an SDK is not available for your stack, implement the flow directly.
### 1. Trigger the 402
```bash theme={"system"}
curl -X POST https://api.example.com/paid-endpoint \
-H "Content-Type: application/json" \
-d '{"query":"hello"}'
```
**Response (402):**
```json theme={"system"}
{
"x402Version": 1,
"accepts": [
{
"scheme": "exact",
"network": "base",
"maxAmountRequired": "10000",
"resource": "https://api.example.com/paid-endpoint",
"payTo": "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"maxTimeoutSeconds": 60,
"extra": { "name": "USD Coin", "version": "2" }
}
]
}
```
### 2. Sign the payment authorization
Pick an entry from `accepts` and sign an EIP-712 `TransferWithAuthorization` (EIP-3009) message with your wallet:
* **Domain**: `name` and `version` from `extra`, the network's `chainId`, and `asset` as `verifyingContract`
* **Message**: `from` (your address), `to` (`payTo`), `value` (`maxAmountRequired`), `validAfter` (now − 600), `validBefore` (now + `maxTimeoutSeconds`), and a random 32-byte `nonce`
### 3. Retry with the `X-PAYMENT` header
Base64-encode the signed payload and retry:
```json theme={"system"}
{
"x402Version": 1,
"scheme": "exact",
"network": "base",
"payload": {
"signature": "0x...",
"authorization": {
"from": "0xYourAddress",
"to": "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
"value": "10000",
"validAfter": "1750000000",
"validBefore": "1750000060",
"nonce": "0x..."
}
}
}
```
```bash theme={"system"}
curl -X POST https://api.example.com/paid-endpoint \
-H "Content-Type: application/json" \
-H "X-PAYMENT: " \
-d '{"query":"hello"}'
```
A successful response includes an `X-PAYMENT-RESPONSE` header with the settlement result (including the transaction hash).
## AI agents
Because the whole flow is signature-based and non-interactive, x402 works well for autonomous agents: give the agent a funded wallet key, wrap its HTTP client with `x402-fetch` or `x402-axios`, and set a conservative `maxValue` as a spending guardrail per request.
## Best practices
* **Cap spend** — always set `maxValue` explicitly rather than relying on defaults.
* **Protect keys** — load private keys from environment variables or a secrets manager; never commit them.
* **Use a dedicated wallet** — fund a purpose-specific wallet with only the USDC your integration needs.
* **Test first** — develop against a testnet (e.g. `base-sepolia`) before pointing at mainnet endpoints.
## Next steps
Networks and assets you can pay with
Protect your own endpoints with x402
Authenticate facilitator API calls
Facilitator settlement endpoint reference
# Supported Networks
Source: https://docs.mrdn.finance/api-reference/supported-networks
Networks supported by Meridian
## Overview
Meridian supports multiple EVM networks with different levels of functionality for each network. This page documents the current network support and capabilities.
## Contract Addresses
### Mainnet
| Network | Chain ID | Payment Token | Facilitator | Cross-chain |
| ------------ | -------- | -------------------------------------------- | -------------------------------------------- | ----------- |
| `avalanche` | `43114` | `0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | No |
| `base` | `8453` | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | Across |
| `bsc` | `56` | `0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | Across |
| `bot-chain` | `677` | `0xaBabc7Ddc03e501d190C676BF3d92ef0e6e87a3C` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | No |
| `optimism` | `10` | `0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | Across |
| `arbitrum` | `42161` | `0xaf88d065e77c8cC2239327C5EDb3A432268e5831` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | Across |
| `polygon` | `137` | `0x3c499c542cef5e3811e1192ce70d8cc03d5c3359` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | Across |
| `unichain` | `130` | `0x078d782b760474a361dda0af3839290b0ef57ad6` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | Across |
| `ink` | `57073` | `0x2D270e6886d130D724215A266106e6832161EAEd` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | Across |
| `worldchain` | `480` | `0x79A02482A880bCe3F13E09da970dC34dB4cD24D1` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | Across |
| `sei` | `1329` | `0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | No |
| `hyperevm` | `999` | `0xb88339CB7199b77E23DB6E890353E22632Ba630f` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | Across |
| `megaeth` | `4326` | `0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | No |
| `tempo` | `4217` | `0x20C000000000000000000000b9537d11c60E8b50` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | No |
| `monad` | `143` | `0x754704Bc059F8C67012fEd69BC8A327a5aafb603` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | Across |
| `robinhood` | `4663` | `0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168` | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` | Across |
#### Non-EIP-3009 Token Note
Chains whose payment token does not natively support EIP-3009 use Permit2 via
`x402ExactPermit2Proxy` `0x402085c248EeA27D92E8b30b2C58ed07f9E20001`. This is
the canonical exact Permit2 proxy from the official
[x402 repository](https://github.com/x402-foundation/x402/tree/main), deployed
at the same address on supported EVM chains. This includes MegaETH, BSC, and
BOT chain testnet and mainnet.
For these integrations:
* Keep `payTo` set to the facilitator `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6`
* Set `paymentRequirements.asset` to the ERC-20 token address the buyer will pay with
* Use Permit2 `0x000000000022D473030F116dDEE9F6B43aC78BA3` as the approval target
* Use `x402ExactPermit2Proxy` `0x402085c248EeA27D92E8b30b2C58ed07f9E20001` as the Permit2 spender
#### Upto Scheme Note
The `upto` scheme (usage-based pricing, buyer signs a maximum and the seller
settles the actual amount) is available on **every** supported network, since
it always settles via Permit2. Sign with `x402UptoPermit2Proxy`
`0x402015c795ecb48A360bDC6e35a2EaEb313a0002` as the Permit2 spender (same
address on every chain) and include the `facilitator` field in the witness. See
[Payment Types](/api-reference/payment-types/overview) for details.
#### Tempo Note
Tempo has no native gas token. Transaction fees are paid in TIP-20 stablecoins such as USDC.e. Meridian uses USDC.e at `0x20C000000000000000000000b9537d11c60E8b50` for payment flows. The public RPC is `https://rpc.tempo.xyz`, the WebSocket endpoint is `wss://rpc.tempo.xyz`, the explorer is `https://explore.tempo.xyz`, and Circle CCTP/Gateway is not currently supported.
### Testnet
| Network | Chain ID | Payment Token | Facilitator | Cross-chain |
| ------------------- | ---------- | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| `arc-testnet` | `5042002` | `0x3600000000000000000000000000000000000000` | [`0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A`](https://testnet.arcscan.app/address/0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A) | No |
| `bot-chain-testnet` | `968` | `0x75edC9335175Fc0552D51D48439F229c10420fe3` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` | No |
| `base-sepolia` | `84532` | `0x036CbD53842c5426634e7929541eC2318f3dCF7e` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` | Across |
| `fluent-testnet` | `20994` | `0xa5544e6DDe3d8927Bf3bD9556e84f49067E36bAf` | [`0xB3Ac1B7871942bCdCD0bD6C65765272bBE70B8Da`](https://testnet.fluentscan.xyz/address/0xB3Ac1B7871942bCdCD0bD6C65765272bBE70B8Da) | No |
| `optimism-sepolia` | `11155420` | `0x5fd84259d66Cd46123540766Be93DFE6D43130D7` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` | Across |
Fluent testnet currently uses a mock USDC deployment, including function `mint(to, amount)` to receive test USDC.
#### Arc Testnet Note
Arc Testnet uses USDC as the native gas token. Meridian uses the ERC-20 USDC interface at `0x3600000000000000000000000000000000000000` for payment flows. The public RPC is `https://rpc.testnet.arc.network`, the WebSocket endpoint is `wss://rpc.testnet.arc.network`, the explorer is `https://testnet.arcscan.app`, and the Circle CCTP/Gateway domain is `26`.
### Solana (SVM)
Meridian settles USDC payments on Solana through the `meridian_x402` program
rather than an EVM facilitator. Payments are same-chain only (no Across
cross-chain routing on Solana in this version).
| Network | Cluster | USDC Mint | Program ID |
| --------------- | ------------ | ---------------------------------------------- | --------------------------------------------- |
| `solana` | mainnet-beta | `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` | `Ro6hz1smrm5zDh73849eDqKna9dE1EkPsWekAB5rBWm` |
| `solana-devnet` | devnet | `4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU` | `Ro6hz1smrm5zDh73849eDqKna9dE1EkPsWekAB5rBWm` |
The program is live on both `solana` and `solana-devnet`. Do not
hardcode the program ID or the fee-payer pubkey — read everything at runtime
from `GET /v1/solana/facilitator?network=`, which returns
`{ network, facilitator, programId, configPda }` plus the on-chain program
config (`usdcMint`, `treasury`, `treasuryToken`, `treasuryFeeBps`, `paused`)
when the chain is reachable. Buyers need no Anchor, no IDL, and no on-chain
config reads — this one call plus `@solana/web3.js` / `@solana/spl-token` is
enough. For these integrations:
* Set `paymentRequirements.asset` to the **USDC mint** address
* Set `paymentRequirements.payTo` to the seller's **recipient wallet** (owner,
not a token account), matching the org's configured Solana recipient
* Set `paymentRequirements.extra.feePayer` to the facilitator pubkey; the buyer
signs the settlement transaction and the facilitator co-signs as fee payer
* Ensure all USDC associated token accounts exist before settlement
See [Solana Program](/payments/solana-program) and the
[Solana payments](/ai-skills/solana) integration guide.
## Network Monitoring
* Monitor network status via `/v1/supported` endpoint
* Implement fallback logic for network outages
* Cache network information with appropriate TTL
# Create Top-up
Source: https://docs.mrdn.finance/api-reference/topup/create-topup
POST https://api-antseed.mrdn.finance/v1/{merchant}/topups
Pay with x402 and credit the merchant-side balance
Creates (or resumes) a top-up. Unpaid requests receive `402 Payment Required` with the exact payment requirements to sign; paid requests settle the payment and perform the merchant deposit. Replaying the same `X-PAYMENT` returns the existing top-up idempotently.
## Path
Merchant id. Currently `antseed`. Unsupported merchant paths return `404`.
## Headers
Must be `application/json`.
Base64-encoded signed x402 payment payload. Omit on the first request to
receive the payment requirements via a 402 response.
## Body
Address to credit on the merchant contract. Required on an unpaid request;
on a paid request it defaults to the payment signer. It must equal the signer
(`authorization.from`) — anything else is rejected with `400 buyer_mismatch`.
Gross payment-token amount in 6-decimal base units (for example,
`"5000000"` = 5 tokens). When omitted, the gateway uses the buyer's maximum
available headroom. When paying, it must match `authorization.value` and be
within the bounds returned by the challenge or quote endpoint.
Signed x402 payment payload as JSON. Use either this field or the
base64-encoded `X-PAYMENT` header.
## Responses
| Status | Meaning |
| ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200` | Deposited. Body is the public top-up row (`state: "deposited"`, `grossAmount`, `netAmount`, source `settlementTx`, optional Base `fillTx`, and Base `depositTx`); settlement details are echoed base64-encoded in the `X-PAYMENT-RESPONSE` header. |
| `402` | Payment challenge or clean settlement failure. A clean failure can be retried with the same valid payment. The response also contains a fresh challenge. |
| `400` | Rejected before settlement: `invalid_request`, `buyer_mismatch`, `wrong_network`, `wrong_recipient`, `invalid_signature`, `authorization_not_yet_valid`, `authorization_expired`, `amount_mismatch`, `amount_too_low`, `amount_too_high`, … (`errorReason` names the cause). |
| `409` | `authorization_reused` (payment already used), `credit_limit_reached`, or `deposit_failed` (deposit impossible after settlement — the settled amount was refunded, see `refundTx`). |
| `503` | Settlement, bridging, deposit, or refund is pending. Poll the returned `topupId` or retry with the same `X-PAYMENT` after `Retry-After` seconds. |
| `500` | `needs_review` — an inconsistent, expired, or timed-out bridge state that requires operator attention. |
```bash Unpaid (get challenge) theme={"system"}
curl -X POST https://api-antseed.mrdn.finance/v1/antseed/topups \
-H "Content-Type: application/json" \
-d '{ "buyer": "0xYourAddress", "amount": "5000000" }'
```
```bash Paid theme={"system"}
curl -X POST https://api-antseed.mrdn.finance/v1/antseed/topups \
-H "Content-Type: application/json" \
-H "X-PAYMENT: " \
-d '{ "buyer": "0xYourAddress", "amount": "5000000" }'
```
The challenge below abbreviates the enabled source list for readability. The
live response contains one `accepts[]` and `topup.sources[]` entry per source
that can accept the requested amount.
```json 402 Challenge theme={"system"}
{
"x402Version": 1,
"error": "X-PAYMENT header required",
"accepts": [
{
"scheme": "exact",
"network": "base",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0x…facilitator",
"maxAmountRequired": "5000000",
"resource": "https://api-antseed.mrdn.finance/v1/antseed/topups?buyer=0xYourAddress",
"description": "Top up AntSeed buyer deposits for 0xYourAddress…",
"mimeType": "application/json",
"maxTimeoutSeconds": 300,
"extra": { "name": "USD Coin", "version": "2", "creditedRecipient": "0x…relayer" }
},
{
"scheme": "exact",
"network": "optimism",
"asset": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
"payTo": "0x…facilitator",
"maxAmountRequired": "5000000",
"extra": {
"name": "USD Coin",
"version": "2",
"creditedRecipient": "0x…relayer",
"destinationChainId": 8453
},
"…": "…"
},
{
"scheme": "exact",
"network": "ink",
"asset": "0x2D270e6886d130D724215A266106e6832161EAEd",
"extra": { "name": "USDC", "version": "2", "destinationChainId": 8453 },
"…": "…"
}
],
"topup": {
"buyer": "0xYourAddress",
"amount": "5000000",
"minAmount": "1250000",
"maxAmount": "10000000",
"note": "The credited deposit is the settled amount net of Meridian facilitator fees.",
"sources": [
{ "network": "base", "evmChainId": 8453, "minAmount": "1250000", "maxAmount": "10000000" },
{ "network": "optimism", "evmChainId": 10, "minAmount": "1750000", "maxAmount": "10000000" },
{ "network": "ink", "evmChainId": 57073, "minAmount": "1750000", "maxAmount": "10000000" }
]
}
}
```
```json 200 Deposited theme={"system"}
{
"success": true,
"topupId": "0xf6cd…d723",
"state": "deposited",
"buyer": "0xYourAddress",
"payer": "0xYourAddress",
"network": "optimism",
"sourceNetwork": "optimism",
"grossAmount": "5000000",
"netAmount": "4900000",
"settlementTx": "0xeb80…e5a8",
"fillTx": "0xa91c…44fe",
"depositTx": "0x8186…1234",
"refundTx": null,
"error": null,
"createdAt": 1783656257928,
"updatedAt": 1783656258080
}
```
# Gateway Health
Source: https://docs.mrdn.finance/api-reference/topup/health
GET https://api-antseed.mrdn.finance/healthz
Read the running gateway's merchant and network configuration
Returns the gateway's relayer, facilitator, merchant contracts, and enabled
payment sources.
## Response fields
| Field | Meaning |
| --------------------- | ---------------------------------------------------------------------- |
| `ok` | The gateway process completed startup and is serving requests. |
| `relayer` | Base wallet that submits merchant deposits and refunds. |
| `facilitator` | Meridian facilitator contract used for Base settlement. |
| `merchants` | Configured merchant runtimes and their settlement chains. |
| `merchants[].sources` | Enabled payment sources, token addresses, facilitators, and chain ids. |
```bash Request theme={"system"}
curl "https://api-antseed.mrdn.finance/healthz"
```
```json 200 theme={"system"}
{
"ok": true,
"relayer": "0x…relayer",
"facilitator": "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
"merchants": [
{
"id": "antseed",
"chainId": "base-mainnet",
"evmChainId": 8453,
"network": "base",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"contract": "0x0F7a3a8f4Da01637d1202bb5443fcF7F88F99fD2",
"relayer": "0x…relayer",
"sources": [
{
"network": "base",
"evmChainId": 8453,
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"facilitator": "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
"sameChain": true
}
]
}
]
}
```
# Overview
Source: https://docs.mrdn.finance/api-reference/topup/overview
Gasless merchant top-ups over x402
The Merchant Top-up Gateway turns an x402 payment into an onchain action on a merchant contract. The buyer signs a gasless EIP-3009 authorization on a supported source chain. Meridian settles the payment to a Base relayer wallet, using Across for cross-chain payments. The relayer then calls the merchant contract. The buyer does not need ETH.
The first supported merchant is **AntSeed**: topping up `AntseedDeposits` buyer balances on Base — the one gas-requiring step in AntSeed's otherwise gasless buyer flow. Once the deposit lands onchain, the balance appears in all AntSeed tooling automatically.
## Base URL
```
https://api-antseed.mrdn.finance
```
All endpoints are scoped by merchant id. The only merchant currently available
is `antseed`.
## Endpoints
`POST /v1/{merchant}/topups` — x402-paid
`GET /v1/{merchant}/topups/quote` — free
`GET /v1/{merchant}/topups/{id}` — free
`GET /healthz` — free
## How it works
1. Send `POST /v1/antseed/topups` with a `buyer` and no payment. The `402 Payment Required` response contains one entry per eligible source in `accepts[]` and source bounds in `topup.sources[]`. If `amount` is omitted, the gateway uses the buyer's full headroom.
2. Choose a source and sign an EIP-3009 `TransferWithAuthorization` using its chain id and token domain. Cross-chain entries include `extra.destinationChainId: 8453`.
3. Retry the same request with the signed payment base64-encoded in the `X-PAYMENT` header.
4. The gateway settles through Meridian. Payments from sources other than Base enter `bridging` while Across delivers to Base. The gateway measures the exact Base credit and calls the merchant contract (`deposit(buyer, net)` for AntSeed) from its relayer wallet.
5. The response (and `GET /v1/antseed/topups/{id}`) reports the source `settlementTx`, optional Base `fillTx`, Base `depositTx`, and exact credited amount.
## Payment sources
Most sources use USDC. Robinhood uses USDG. Cross-chain payments deliver USDC
on Base. Use the token address and EIP-712 domain returned in the payment
requirements.
| Source | Chain id | Payment token / EIP-712 name / version | Settlement |
| --------------- | -------: | -------------------------------------- | -------------- |
| Base | `8453` | USDC / `USD Coin` / `2` | Same-chain |
| Arbitrum | `42161` | USDC / `USD Coin` / `2` | Across to Base |
| BSC | `56` | USDC / `USD Coin` / `1` | Across to Base |
| HyperEVM | `999` | USDC / `USD Coin` / `2` | Across to Base |
| Ink | `57073` | USDC / `USDC` / `2` | Across to Base |
| Monad | `143` | USDC / `USD Coin` / `2` | Across to Base |
| Optimism | `10` | USDC / `USD Coin` / `2` | Across to Base |
| Polygon | `137` | USDC / `USD Coin` / `2` | Across to Base |
| Robinhood Chain | `4663` | USDG / `Global Dollar` / `1` | Across to Base |
| Unichain | `130` | USDC / `USD Coin` / `2` | Across to Base |
| World Chain | `480` | USDC / `USD Coin` / `2` | Across to Base |
## Trust assumptions
* **Signed payment.** The EIP-3009 authorization fixes the token, amount,
facilitator, validity window, payer, and nonce. The merchant and credited
recipient are settlement parameters supplied by the gateway. The gateway
enforces `buyer = payer` and requests the merchant relayer as the credited
recipient.
* **Facilitator contract.** Payments pass through the verified
[`X402ProxyFacilitator`](https://basescan.org/address/0x8E7769D440b3460b92159Dd9C6D17302b036e2d6#code)
contract.
* **Relayer.** The merchant relayer holds the settled funds until it completes
the merchant deposit or refunds the payer. Its transactions and the final
credited amount are recorded in the top-up status.
* **Cross-chain payments.** Payments from other chains use Across to deliver
funds to Base before merchant fulfillment.
## Rules worth knowing
* **Buyer = payer.** v1 only allows self top-ups: the `buyer` must equal the address that signed the payment. Requests with a different `buyer` are rejected (`buyer_mismatch`).
* **Fees.** The merchant receives the amount delivered on Base after Meridian and Across fees. Responses show `grossAmount` and `netAmount` in 6-decimal base units.
* **Idempotent.** Replaying the same `X-PAYMENT` returns the existing top-up. Each EIP-3009 authorization `(payer, nonce)` is accepted exactly once.
* **Pending requests.** A `503` means the payment is still being reconciled. Retry with the same `X-PAYMENT` or poll its `topupId`.
* **Refund path.** If the deposit can no longer succeed after settlement (e.g. credit limit lost to a concurrent deposit), the delivered amount is automatically refunded to the payer on Base. If an Across deposit itself expires, Meridian operations recover the source-proxy refund manually in v1.
The gateway temporarily holds funds between settlement and merchant
fulfillment. Merchant contracts remain public and can support other
gateways.
# Quote Bounds
Source: https://docs.mrdn.finance/api-reference/topup/quote
GET https://api-antseed.mrdn.finance/v1/{merchant}/topups/quote
Read the current top-up bounds and payment requirements for a buyer
Returns the buyer's merchant balance, credit limit, headroom, accepted amount
range, and x402 payment requirements. This endpoint does not move funds.
## Path
Merchant id. Currently `antseed`.
## Query
Address to quote for (checksummed or lowercase).
Gross payment-token amount in 6-decimal base units. Defaults to the maximum
available headroom. Invalid amounts return `400 amount_too_low`,
`400 amount_too_high`, or `409 credit_limit_reached`.
Optional payment source. Supported values are `base`, `arbitrum`, `bsc`,
`hyperevm`, `ink`, `monad`, `optimism`, `polygon`, `robinhood`, `unichain`,
and `worldchain`. Defaults to Base. Unknown sources return
`400 wrong_network`.
## Response fields
All amounts are 6-decimal base-unit strings. `amount`, `minAmount`, and
`maxAmount` use the selected source token. Merchant balance fields use Base
USDC.
| Field | Meaning |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `minAmount` / `maxAmount` | Accepted gross range for the selected source. Cross-chain minimums include a buffered Across fee quote (or the configured static fallback). |
| `balance` | Buyer's current merchant-side balance (available + reserved). |
| `creditLimit` | Merchant-side credit limit for the buyer. |
| `headroom` | Remaining credit capacity (`creditLimit − balance`). |
| `minBuyerDeposit` | Merchant-side minimum applying to this top-up (`"0"` once the buyer has a balance). |
| `requirements` | The x402 payment requirements for the selected source. It corresponds to that source's entry in a subsequent challenge. |
| `sources` | Sources that can accept the requested amount, as `{ network, evmChainId, minAmount, maxAmount }`. |
```bash Request theme={"system"}
curl "https://api-antseed.mrdn.finance/v1/antseed/topups/quote?buyer=0xYourAddress&amount=5000000&network=optimism"
```
The source list below is abbreviated; the live response includes every enabled
source that can accept the requested amount.
```json 200 theme={"system"}
{
"buyer": "0xYourAddress",
"amount": "5000000",
"minAmount": "1750000",
"maxAmount": "10000000",
"balance": "0",
"creditLimit": "10000000",
"headroom": "10000000",
"minBuyerDeposit": "1000000",
"requirements": {
"scheme": "exact",
"network": "optimism",
"extra": { "destinationChainId": 8453, "…": "…" },
"…": "…"
},
"sources": [
{ "network": "base", "evmChainId": 8453, "minAmount": "1250000", "maxAmount": "10000000" },
{ "network": "optimism", "evmChainId": 10, "minAmount": "1750000", "maxAmount": "10000000" },
{ "network": "ink", "evmChainId": 57073, "minAmount": "1750000", "maxAmount": "10000000" }
]
}
```
# Top-up Status
Source: https://docs.mrdn.finance/api-reference/topup/status
GET https://api-antseed.mrdn.finance/v1/{merchant}/topups/{id}
Poll the state of a top-up
Free, public status of a top-up. The `topupId` comes from the `POST` response. The row never exposes the payment signature.
## Path
Merchant id. Currently `antseed`. Returns `404` for ids that belong to a
different merchant.
Top-up id (`topupId` from the create response).
## States
```
same-chain: settling ───────────→ settled → depositing → deposited
cross-chain: settling → bridging → settled → depositing → deposited
└→ refunding → refunded
any → failed | needs_review terminal
```
Poll until the state is terminal: `deposited`, `refunded`, `failed`, or
`needs_review`. A status request advances non-terminal top-ups. The gateway also
resumes them in the background and after restarts. Use the `Retry-After` value
from a pending `POST` (currently 5 seconds).
A clean settlement failure appears as `failed`. It is terminal for status
polling, but the same `X-PAYMENT` can be resubmitted while its authorization is
still unused and unexpired. `bridge_expired`, `bridge_timeout`, or any
`needs_review` state requires Meridian operations review.
```bash Request theme={"system"}
curl "https://api-antseed.mrdn.finance/v1/antseed/topups/0xf6cd…d723"
```
```json 200 theme={"system"}
{
"topupId": "0xf6cd…d723",
"state": "deposited",
"buyer": "0xYourAddress",
"payer": "0xYourAddress",
"network": "optimism",
"sourceNetwork": "optimism",
"grossAmount": "5000000",
"netAmount": "4900000",
"settlementTx": "0xeb80…e5a8",
"fillTx": "0xa91c…44fe",
"depositTx": "0x8186…1234",
"refundTx": null,
"error": null,
"createdAt": 1783656257928,
"updatedAt": 1783656258080
}
```
# Brandkit
Source: https://docs.mrdn.finance/brandkit
Meridian brand assets and guidelines
## Colors
## Typography
[Funnel Display](https://fonts.google.com/specimen/Funnel+Display) from Google Fonts.
400 for logo.
Meridian
Larger font sizes prioritized for readability.
## Logos
# Bring Your Own Agent
Source: https://docs.mrdn.finance/byoa
The vision for integrating any EVM agent with Meridian's payment infrastructure
## Agents Un-chained
AI agents today face dual constraints: they're chained to specific networks **and** locked into the platforms that created them. Agent-to-agent interactions are limited to others built on the same platform, creating isolated silos.
**Meridian is actively building the infrastructure to remove these barriers.**
## The Current Problem
Agents restricted to single blockchain networks, limiting their reach and
functionality.
Agents can only interact with others from the same creation platform,
preventing cross-ecosystem collaboration.
Complex payment integrations required for each network and platform
combination.
No standardized way for agents to communicate and transact across different
infrastructures.
## Meridian's Agent-Ready Infrastructure
### Built for Agent Interoperability
Meridian's payment infrastructure was designed from the ground up to solve agent ecosystem fragmentation:
* **X402ProxyFacilitator Contract**: Proxy architecture that enables any agent to receive payments without direct wallet management
* **Multichain Foundation**: Live on Base with multi-network deployment ready
* **Organization Management**: API-driven system perfect for managing multiple agents under one umbrella
* **Transparent Fee Structure**: Platform and treasury fees are accounted for at settlement time
### Current Payment Flow
```
Agent/User → x402 Authorization → Meridian Facilitator → Settlement
```
## B.Y.O.A: The Next Layer
### Building on Proven Infrastructure
Our payment architecture already handles the core challenge: enabling any address to receive payments through relayed facilitator settlement without requiring the recipient to submit every transaction themselves.
The organization management system provides the framework for grouping multiple payment recipients under unified control. This maps naturally to agent ecosystems where multiple agents operate under shared management.
Multichain foundation means agents won't be locked to single networks. The same payment flow that works on Base extends across any EVM chain.
## The Foundation is Ready
### Current Infrastructure Enables Agent Payments
The payment verification system already handles authorization validation and settlement, including Permit2 proxy settlement on non-EIP-3009 chains such as MegaETH, BSC, and BOT chain.
Organization management provides the access control framework that scales from single developers to multi-agent ecosystems.
Facilitator-based settlement and fee accounting create the operational layer that agents need to collect payments reliably across supported networks.
The fee structure provides sustainable funding for continued development and network effects.
## Meridian Scope
**Meridian Scope:**
* Payment authorization and settlement
* Multichain transaction coordination
* Economic validation through payment proofs
* Fee management and treasury operations
## Understanding the Architecture
### How Current Infrastructure Becomes Agent Infrastructure
See how proxy architecture and relayed settlement create the foundation for
agent payments.
Understand how multi-user organizations scale to multi-agent ecosystems.
Explore the network architecture that prevents agent platform lock-in.
# Analytics
Source: https://docs.mrdn.finance/command-centre/analytics
Understand payment performance and trends
Analytics helps you understand payment performance across time, receivers, and
products. Use it to spot trends and measure throughput at a glance.
## Metrics and calculations
Below is every metric shown in Analytics and how it is calculated for the
selected time range.
### Overview
* **Total transactions**: Count of all transactions in the time range.
* **Total volume**: Sum of transaction amounts in the time range.
* **Average transaction value**: Average of transaction amounts in the time
range.
* **Success rate**: `(settledTransactions / totalTransactions) × 100`, where
“settled” means `status = SETTLED`.
* **Volume trend %**: Percentage change in total volume vs the previous period
of the same length (previous period ends one day before the current start).
### Breakdowns
* **By status**: Count and percentage of total transactions per status.
`percentage = (statusCount / totalTransactions) × 100`.
* **By network**: Count, volume, and percentage of total transactions per
network. `percentage = (networkCount / totalTransactions) × 100`.
* **Daily**: Count and volume aggregated per day, with missing days shown as 0.
* **Hourly distribution**: Count and volume aggregated per hour of day.
* **Weekly trends**: Count and volume aggregated per week.
## What you can analyze
* **Volume and totals** by time range.
* **Top receivers** by activity.
* **Success vs refund rates** for operational health.
# Balances
Source: https://docs.mrdn.finance/command-centre/balances
View merchant balances and payout readiness
Balances shows merchant-level and receiver-level balances derived from settled
payments. These balances represent **available funds in Meridian's receiver
ledger**, not live on-chain wallet balances. Use this view to understand what is
ready for withdrawal, what is pending, and how balances roll up across receiver
wallets.
## How balances are calculated
All balances are pulled directly from on-chain reads and contract events.
### Merchant revenue (by network)
* **Source**: `InstantSettlement` events from the Meridian contract.
* **Calculation**: Sum of `netAmount` for all `InstantSettlement` events where
`recipient = your wallet`, per network.
* **Networks**: Base, Optimism, Arbitrum, Polygon, Unichain, Ink, MegaETH, HyperEVM, BNB Smart Chain (BSC), Monad.
### Ready-to-withdraw balance (protocol balance)
* **Source**: `balanceReadyToWithdrawal(recipient, usdcAddress)` on the Meridian
contract.
* **Calculation**: Direct contract read returning the amount available to
withdraw for the selected recipient and token.
### Wallet balance (USDC on each network)
* **Source**: ERC-20 `balanceOf(wallet)` for the network’s USDC address.
* **Calculation**: Direct token balance read on each supported network.
### MRDN balances
* **Current MRDN balance**: ERC-20 `balanceOf(wallet)` on Base mainnet.
* **Total MRDN earned**: Sum of `mrdnAmount` from `CashbackPaid` events where
`recipient = your wallet` (Base mainnet).
### Total revenue (top-line)
* **Calculation**: Sum of merchant revenue across **mainnet** networks, plus
current MRDN balance. Testnet balances are excluded.
## What you can monitor
* **Available balance**: Funds from settled payments that can be withdrawn.
* **Pending balance**: Payments not yet settled.
* **Receiver wallet totals**: Balance breakdown by receiver.
* **Merchant rollups**: Aggregate totals across all receivers in the org.
# Marketplace
Source: https://docs.mrdn.finance/command-centre/marketplace
Configure marketplace fees and route payouts with creditedRecipient
Marketplace mode lets your organization collect fees on payments routed through
Meridian while sending the remaining payout to a separate recipient wallet.
## Enable marketplace mode
Sign in to Meridian Command Centre and open **Settings** under **Financial
Services**.
Toggle **Marketplace** on.
Enter your fee in basis points. Example: `500` bps = `5%`.
Click **Save Changes** to apply the setting to your organization.
Older internal messages may call this "Platform" mode. In Command Centre the
setting is labeled **Marketplace**.
## Update your x402 payment requirements
Keep `payTo` pointed at the Meridian facilitator address for the target network.
Use `extra.creditedRecipient` to tell Meridian which wallet should receive the
net payout.
Below is a `paymentRequirements` example for the recommended Permit2-based
flow on a chain without native EIP-3009 support. The example uses MegaETH; use
the same pattern on BSC and BOT chain with that network's token and chain id.
```ts theme={"system"}
const paymentRequirements = {
amount: value.toString(),
recipient: address,
network: "megaeth",
scheme: "exact",
maxAmountRequired: value.toString(),
resource: `${FACILITATOR_URL}/v1/samples`,
description: `Payment for ${formatUnits(value, TOKEN_DECIMALS)} ${TOKEN_SYMBOL}`,
mimeType: "application/json",
payTo: MEGAETH_FACILITATOR_ADDRESS,
asset: MEGAETH_TOKEN_ADDRESS,
extra: {
creditedRecipient: recipientAddress,
name: TOKEN_SYMBOL,
version: "1",
destinationChainId: MEGAETH_CHAIN_ID,
},
};
```
On chains without EIP-3009 support, use the ERC-20 token address in `asset`,
approve Permit2 `0x000000000022D473030F116dDEE9F6B43aC78BA3`, and sign with
`x402ExactPermit2Proxy` `0x402085c248EeA27D92E8b30b2C58ed07f9E20001`. See
[Payment Types](/api-reference/payment-types/overview).
## How payouts work
* `payTo` remains the Meridian facilitator, not the seller wallet.
* On Permit2 networks such as MegaETH, BSC, and BOT chain, `asset` should be the ERC-20 token address for the current Permit2 flow.
* On Permit2 networks, `extra.name` and `extra.version` should describe the token used in the Permit2 flow.
* `extra.creditedRecipient` receives the payment amount remaining after fees.
* Your marketplace fee accrues inside the facilitator contract as a platform
balance for your organization.
* Fees do **not** automatically land in your wallet. Withdraw them from the
Settings page using **Withdraw Marketplace Fees**, or withdraw them directly
on-chain from the proxy contract.
If your marketplace fee is `500` bps, Meridian records `5%` of each payment as
marketplace fees. In the simple case where no other fee applies, the remaining
`95%` is settled to `creditedRecipient`.
Marketplace fees are tracked on-chain inside the facilitator and can later be
withdrawn to your connected wallet from Command Centre.
## Withdraw marketplace fees on-chain
You can also withdraw accumulated marketplace fees directly from the Meridian
proxy contract by calling:
```solidity theme={"system"}
withdrawPlatformFees(address token)
```
Call this function on the network's Meridian proxy/facilitator address from the
same wallet address that is configured as the marketplace platform address. The
platform address is inferred from `msg.sender`, so it is **not** passed as a
function argument.
```ts theme={"system"}
await facilitator.write.withdrawPlatformFees([tokenAddress]);
```
Use the token address for the asset in which fees accrued on that network, for example USDC on BSC or USDm on MegaETH.
## Related guides
* [Smart Contracts](/payments/smart-contracts)
* [Balances](/command-centre/balances)
# Refunds
Source: https://docs.mrdn.finance/command-centre/refunds
Permanent receipt generation for transaction refunds
## Overview
The refund service generates permanent, cryptographically-verifiable receipts when transactions are refunded. Merchants pay for receipt storage using x402.
## Refund Process
When a merchant refunds a transaction:
1. Refund executed on-chain
2. Receipt generated with transaction details
3. Merchant pays for permanent IPFS storage
4. Receipt hash logged to Meridian database
5. Receipt retrievable by transaction ID or IPFS hash
## Receipt Contents
* Original transaction hash
* Refund transaction hash
* Amount refunded
* Currency and network
* Merchant wallet address
* Customer wallet address
* Timestamp
* Block explorer link
### Example Receipt
```json theme={"system"}
{
"transactionId": "pmt_abc123xyz",
"originalTxHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"refundTxHash": "0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321",
"amount": "10.50",
"currency": "USDC",
"network": "base",
"refundedTo": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
"refundedBy": "0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199",
"refundedAt": "2026-01-22T10:30:00.000Z",
"explorerUrl": "https://basescan.org/tx/0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321",
"type": "meridian_refund_receipt",
"version": "1.0"
}
```
## Merchant-Paid Storage
Receipts use x402 protocol via [Pinata](https://docs.pinata.cloud/api-reference/endpoint/x402/pin) on Base mainnet. Merchants pay \~\$0.001 to permanently store refund proof.
**Why merchant-paid:** Ensures receipts remain accessible indefinitely without platform dependency. Customers receive permanent proof of refund.
**Pricing:** `$0.10/GB/month × 12 months = $1.20/GB total`
**Network:** Base (x402 protocol requirement)
## Networks
Refunds can be processed on all Meridian-supported networks:
**Mainnet:** Base, Optimism, Arbitrum, Polygon, Unichain, Ink, BNB Smart Chain (BSC), Monad
**Testnet:** Base Sepolia, Optimism Sepolia
Merchants need USDC on Base to pay for receipt storage via Pinata x402, regardless of which network the original transaction occurred on.
# Transactions
Source: https://docs.mrdn.finance/command-centre/transactions
Inspect payment events, status, and metadata
The Transactions view is the source of truth for payment activity across your
organization. Use it to trace a payment from authorization through verification,
settlement, or refund, and to inspect the metadata you need for support and
reconciliation.
## Key fields
* **Lifecycle status**: Authorized, verified, settled, or refunded.
* **Identifiers**: Payment ID and associated receiver wallet.
* **Amounts and timing**: Amount, currency, and timestamps.
* **Settlement + refund links**: Jump to related settlement or refund records.
## Filters
* **Status** to isolate in-flight or completed activity.
* **Time range** for daily, weekly, or custom audits.
* **Receiver wallet** to review individual balances.
# API Keys
Source: https://docs.mrdn.finance/essentials/api-keys
Create and manage API keys for Meridian x402 payment APIs
## Overview
API keys are required to authenticate Meridian x402 payment API requests. They provide secure, programmatic access to Meridian's payment infrastructure for your applications.
## Key Types
Meridian Protocol uses **public keys** for API authentication:
* **Public Key (pk\_)**: Used for API authentication
* **Test Mode Keys**: Prefixed with `pk_test_` for development
* **Production Keys**: Prefixed with `pk_` for live transactions
Secret keys are generated but only shown once during creation for security.
The public key is used for all API requests.
## Creating API Keys
### Via Developer Dashboard
Connect your wallet and authenticate using SIWE
Go to the API Keys section in your developer dashboard
Click "Create API Key" and provide a descriptive name
Select test mode for development or production for live transactions
Copy and securely store both keys - the secret is only shown once!
### Via API
You can also create API keys programmatically:
```bash theme={"system"}
curl -X POST https://api.mrdn.finance/v1/api_keys \
-H "Content-Type: application/json" \
-H "Cookie: siwe-session=your_session" \
-d '{
"name": "My Application Key",
"test_net": true
}'
```
**Response:**
```json theme={"system"}
{
"id": "key_1234567890abcdef",
"name": "My Application Key",
"organization": "org_456",
"api_key": "pk_test_1234567890abcdef...",
"api_secret_key": "sk_test_abcdef1234567890...",
"test_net": true,
"created_at": "2024-01-01T00:00:00.000Z",
"updated_at": "2024-01-01T00:00:00.000Z"
}
```
The `api_secret_key` is only returned once during creation. Store it securely!
## Using API Keys
### Authentication Header
Include your public key in the Authorization header:
`POST /v1/verify` is deprecated. Use `POST /v1/settle` for current API
examples and new integrations.
```bash theme={"system"}
curl -X POST https://api.mrdn.finance/v1/settle \
-H "Authorization: Bearer pk_1234567890abcdef..." \
-H "Content-Type: application/json" \
-d '{
"paymentPayload": {...},
"paymentRequirements": {...}
}'
```
### JavaScript/Node.js
```javascript theme={"system"}
const apiKey = "pk_test_1234567890abcdef...";
const response = await fetch("https://api.mrdn.finance/v1/settle", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
paymentPayload: {
/* ... */
},
paymentRequirements: {
/* ... */
},
}),
});
```
### Python
```python theme={"system"}
import requests
api_key = 'pk_test_1234567890abcdef...'
headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}
response = requests.post(
'https://api.mrdn.finance/v1/settle',
headers=headers,
json={
'paymentPayload': { /* ... */ },
'paymentRequirements': { /* ... */ }
}
)
```
## Managing API Keys
### List All Keys
```bash theme={"system"}
curl https://api.mrdn.finance/v1/api_keys \
-H "Cookie: siwe-session=your_session"
```
**Response:**
```json theme={"system"}
{
"apiKeys": [
{
"id": "key_1234567890abcdef",
"name": "My Application Key",
"organization": "org_456",
"api_key": "pk_test_1234567890abcdef...",
"test_net": true,
"created_at": "2024-01-01T00:00:00.000Z",
"updated_at": "2024-01-01T00:00:00.000Z",
"last_used_at": "2024-01-01T12:00:00.000Z"
}
]
}
```
### Get Single Key
```bash theme={"system"}
curl https://api.mrdn.finance/v1/api_keys/key_1234567890abcdef \
-H "Cookie: siwe-session=your_session"
```
## Test vs Production Keys
### Test Mode Keys (`pk_test_`)
* Used for development and testing
* Process payments on testnets (Base Sepolia, etc.)
* No real money involved
* Separate analytics and transaction history
### Production Keys (`pk_`)
* Used for live applications
* Process real payments on mainnets
* Handle actual value transfers
* Production-level monitoring and support
Always use test keys during development. Switch to production keys only when
your integration is complete and tested.
## Security Best Practices
### Key Storage
* **Never** commit API keys to version control
* Use environment variables or secure key management services
* Rotate keys regularly
* Use different keys for different environments
### Access Control
* API keys are scoped to your organization
* Each key tracks usage and last access time
* Keys can be individually managed and revoked
### Environment Variables
```bash theme={"system"}
# .env file
MERIDIAN_API_KEY=pk_test_1234567890abcdef...
# In your application
const apiKey = process.env.MERIDIAN_API_KEY
```
## API Key Endpoints
`POST /v1/api_keys` - Create a new API key pair
`GET /v1/api_keys` - Get all keys for your organization
`GET /v1/api_keys/:id` - Get details for a specific key
`DELETE /v1/api_keys/:id` - Delete an API key
## Troubleshooting
### Common Errors
**401 Unauthorized**
* Check that your API key is correct
* Ensure you're using the right environment (test vs production)
* Verify the Authorization header format: `Bearer pk_...`
**403 Forbidden**
* API key may be revoked or expired
* Check if you're accessing the correct organization's resources
### Testing Your API Key
```bash theme={"system"}
# Test authentication
curl https://api.mrdn.finance/v1/supported \
-H "Authorization: Bearer pk_test_your_key_here"
# Should return supported payment kinds
{
"kinds": [
{
"x402Version": 1,
"scheme": "exact",
"network": "base-sepolia"
}
]
}
```
## Next Steps
Start settling x402 payments with your API key
Monitor your payment transactions
Access detailed payment analytics
Manage keys in the web interface
# Overview
Source: https://docs.mrdn.finance/index
Build onchain applications with x402 payments and facilitator-based settlement
Meridian is a **layer built on top of Coinbase's infrastructure** that introduces **proxy facilitator architecture** for x402 payments. Unlike direct wallet-to-wallet transfers, Meridian routes payments through a facilitator that settles same-chain transfers immediately, tracks fees onchain, and supports cross-chain execution where needed.
### Key Innovation: Proxy Facilitator Architecture
**Traditional x402 (Coinbase):** Direct transfers from payer to recipient wallet
```
Payer Wallet → Recipient Wallet (immediate transfer)
```
**Meridian's Architecture:** Proxy facilitator settlement
```
Payer Wallet → Meridian Facilitator → Settlement / Bridge → Recipient
```
This enables:
* **Organization-scoped payment management** with multi-user access
* **Same-chain instant settlement** through the facilitator
* **Onchain fee accounting** for platform and treasury balances
* **Cross-chain routing** through Across when required
* **Enhanced security** with organization-scoped access control
## How x402 Works with Meridian
The sequence diagram above shows how Meridian implements the x402 payment protocol with facilitator-based settlement for secure, authenticated transactions.
## Build onchain apps
Use Meridian's backend and frontend suites of crypto payment services.
Accept your first x402 payment in minutes.
Complete API documentation for all endpoints.
## Key Features
Everything you need to build secure payment applications with facilitator-based settlement and multichain execution.
Proxy-mediated payment settlement with onchain accounting and relayed execution.
Platform and treasury fee accounting handled inside the facilitator.
Multi-user organizations with shared payment infrastructure.
Organization-scoped access control with API key management.
## Resources
Explore the codebase and contribute to Meridian's development.
# Mpay
Source: https://docs.mrdn.finance/mpay/overview
Gasless multi-token transfers with x402 and ERC-20 Permit flows
Mpay is Meridian's gasless multi-token transfer product. It lets users send supported tokens without paying gas directly, while keeping the signing flow simple and human readable.
## How Mpay works
Mpay uses one of two signing standards depending on the token being transferred:
### 1. x402 using EIP-3009
For tokens that support EIP-3009, Mpay uses an x402-style flow where the user, or an agent acting on the user's behalf, signs an off-chain payment authorization. The transfer is then executed from that signed message without requiring the user to submit an onchain transaction themselves.
This path is efficient, but support is still limited across the ERC-20 ecosystem. In practice, the main supported token today is USDC.
### 2. ERC20Permit using EIP-2612
For other supported tokens, Mpay uses ERC20Permit under EIP-2612. In this flow, the user signs a permit message that grants approval to the Meridian protocol contract, and the contract executes the token transfer.
The standard is different, but the user experience is the same: sign once, then the tokens move.
## Shared security guarantees
Both flows rely on the same core protections:
* **EIP-712 typed data** for human-readable signing prompts.
* **Nonces** to prevent replay attacks.
* **Expiry windows** so signatures are only valid for a limited time.
* **No private key exposure**, since signing happens client-side and keys never leave the wallet.
## Supported destinations
Mpay supports gasless transfers to:
* **ENS names**
* **Wallet addresses**
## Supported chains
Mpay is available on Meridian-supported deployments.
### Mainnet
| Network ID | Chain |
| ------------ | --------------- |
| `avalanche` | Avalanche |
| `base` | Base |
| `bsc` | BNB Smart Chain |
| `bot-chain` | BOT Chain |
| `optimism` | Optimism |
| `arbitrum` | Arbitrum One |
| `polygon` | Polygon |
| `unichain` | Unichain |
| `ink` | Ink |
| `worldchain` | World Chain |
| `sei` | Sei |
| `hyperevm` | HyperEVM |
| `megaeth` | MegaETH |
| `tempo` | Tempo |
| `monad` | Monad |
| `robinhood` | Robinhood Chain |
### Testnet
| Network ID | Chain |
| ------------------- | ----------------- |
| `arc-testnet` | Arc Testnet |
| `bot-chain-testnet` | BOT Chain Testnet |
| `base-sepolia` | Base Sepolia |
| `fluent-testnet` | Fluent Testnet |
| `optimism-sepolia` | Optimism Sepolia |
# Smart Contracts
Source: https://docs.mrdn.finance/payments/smart-contracts
x402 payment protocol and Meridian facilitator architecture
## Overview
Meridian extends x402 with a **proxy facilitator architecture**. Standard x402 transfers funds directly from payer to recipient; Meridian routes settlement through a facilitator contract instead:
```
Standard x402: Payer signs authorization → Direct transfer to recipient wallet
Meridian: Payer signs authorization → Facilitator receives funds → Facilitator settles recipient and fees
```
This one change is what enables fee handling, batch settlement, cross-chain routing, cashback, and organization-scoped payment management on top of the plain x402 flow.
On chains with native EIP-3009 support, Meridian settles standard x402 exact payloads through the facilitator; on chains without an EIP-3009-compatible token (MegaETH, BSC, BOT chain), Meridian settles via Permit2 through `x402ExactPermit2Proxy`. The `upto` scheme (usage-based pricing) settles via Permit2 through `x402UptoPermit2Proxy` on every supported chain. See [Payment Types](/api-reference/payment-types/overview) for how the facilitator routes each payload type.
## X402ProxyFacilitator.sol (V6)
```solidity theme={"system"}
0x8E7769D440b3460b92159Dd9C6D17302b036e2d6
```
The facilitator is a UUPS-upgradeable contract, currently at version 6.
* **Payment Methods**: EIP-3009 `transferWithAuthorization` (USDC), ERC-2612 `transferWithPermit`, and Permit2 `transferWithPermit2` / `transferWithPermit2Upto`
* **Instant Settlement**: Same-chain payments are settled to the recipient during payment execution
* **Batch Settlement**: One signed authorization can settle multiple payments in a single transaction (`batchTransferWithAuthorization` / `batchTransferWithPermit2`), each item with its own recipient, platform, and fee
* **Fee Handling**: Platform and treasury fees accrue inside the facilitator and are withdrawn via `withdrawPlatformFees` / `withdrawTreasuryFees`
* **MRDN Cashback**: On Base, USDC payments earn MRDN cashback priced via Aerodrome TWAP — the rate starts at 2% and decays as total cashback is distributed, capped at \$5 per transaction
* **Cross-Chain Support**: The same entrypoint initiates cross-chain settlement through Across on supported networks, authenticated by a backend-signed EIP-712 message
## x402ExactPermit2Proxy.sol (Non-EIP-3009 Chains)
Integrations on chains without EIP-3009-compatible tokens (MegaETH, BSC, BOT chain) use Permit2 settlement through the Meridian facilitator:
```solidity theme={"system"}
Facilitator: 0x8E7769D440b3460b92159Dd9C6D17302b036e2d6
x402ExactPermit2Proxy: 0x402085c248EeA27D92E8b30b2C58ed07f9E20001
x402UptoPermit2Proxy: 0x402015c795ecb48A360bDC6e35a2EaEb313a0002
Permit2: 0x000000000022D473030F116dDEE9F6B43aC78BA3
```
* **Flow**: Users approve Permit2 once, then sign a Permit2 witness authorization off-chain for each payment
* **Token model**: `paymentRequirements.asset` is the ERC-20 token address being paid
* **Facilitator binding**: `payTo` and `witness.to` stay bound to the Meridian facilitator
* **Settlement**: Meridian settles through `transferWithPermit2`, not through the buyer submitting a transaction
### x402UptoPermit2Proxy (upto scheme)
The `upto` scheme uses the same Permit2 flow with `x402UptoPermit2Proxy` as the signed spender (same address on every chain). The buyer authorizes a maximum amount; Meridian settles the actual usage amount through `transferWithPermit2Upto`. Differences from the exact proxy:
* **Witness shape**: `{ to, facilitator, validAfter }` — the extra `facilitator` field binds which contract may choose the settled amount; both `to` and `facilitator` stay bound to the Meridian facilitator
* **Settled amount**: `0 < settleAmount ≤ permit.permitted.amount`, passed by the seller at settle time (`paymentRequirements.extra.settleAmount`); fees and cashback apply to the settled amount only
```mermaid theme={"system"}
sequenceDiagram
participant User
participant Token as ERC20 Token
participant Permit2
participant Facilitator
participant ExactProxy as x402ExactPermit2Proxy
participant Recipient
Note over User: One-time setup on Permit2 chains
User->>Token: approve(Permit2, amount or max)
Token-->>User: Approval recorded
Note over User,Facilitator: Every payment
User->>User: Signs Permit2 witness authorization
User->>Facilitator: Sends signed payment payload
Facilitator->>ExactProxy: transferWithPermit2(...)
ExactProxy->>Permit2: settle signed transfer
Permit2->>Token: transferFrom(user, facilitator, amount)
Token-->>Facilitator: Tokens moved
Facilitator->>Recipient: Settle recipient amount and fees
Facilitator-->>User: Payment complete
```
## X402PaymentRouter.sol (Pay with Any Token)
The payment router lets buyers fund an exact USDC payment with another ERC-20 token. The buyer signs one Permit2 witness over the input token; the router pulls that token, swaps `tokenIn → WETH → USDC` (or `WETH → USDC`), refunds unused input, and pushes the exact USDC output into Facilitator V6\_1. USDC never passes through the buyer's wallet and no USDC signature is required.
The router is scoped to **Base** and **Robinhood Chain** and uses CREATE2 with the same address on both. Its new V6\_1 address will be published after deployment. Use `previewAmountIn(tokenIn, usdcAmount)` to quote the input requirement before signing.
The signed witness fixes the router, facilitator, exact USDC amount, recipient, platform fee, destination chain, payment ID, and start time. Anyone may submit the signed payment, but none of those terms can be changed. Permit2's nonce prevents replay.
* On **Base**, V6\_1 distributes the USDC locally to the payment recipient after fees.
* On **Robinhood Chain**, V6\_1 deposits the USDC into Across and forwards it to the recipient on Base.
* The intended first integration is the top-up gateway: its Base relayer receives the net USDC and deposits it into the selected inference provider.
The input token must have approved canonical Permit2 once. Input tokens with transfer taxes are unsupported because they break exact swap and refund accounting. Native ETH is not accepted; wrap it to WETH first.
## Solana (SVM)
On Solana, Meridian settles through the `meridian_x402` program instead of a
Solidity facilitator. Solana needs no EIP-3009: a transaction can carry multiple
signers, so the payer signs the settlement transaction as their USDC token
authority and the facilitator co-signs as fee payer and submits it. Settlement
is atomic — the program splits fees and the recipient's net directly from the
payer's token account in one transaction, with no escrow hop.
The program is live on both `solana` (mainnet) and `solana-devnet`. See
[Solana Program](/payments/solana-program) for the architecture, accounts, and
fee math, and [Solana payments](/ai-skills/solana) for an end-to-end integration
guide.
## How a Payment Flows
1. **Authorization Signing**: Payer signs a payment authorization with amount, recipient context, and network details.
2. **Verification**: Server verifies signature and authorization parameters.
3. **Transfer Execution**: Meridian executes settlement through the facilitator — `transferWithAuthorization` for native EIP-3009 tokens, `transferWithPermit2` via the proxy elsewhere.
4. **Fee Application**: Recipient and fee amounts are handled during settlement processing.
Payments are linked to your organization: API keys authenticate verification and settlement, the recipient wallet is configured in organization settings, and every payment lands in your organization's transaction history in [Command Centre](/command-centre/transactions).
# Solana Program
Source: https://docs.mrdn.finance/payments/solana-program
Meridian x402 payment facilitator on Solana (SVM)
## Overview
`meridian_x402` is the Solana (SVM) port of the Meridian facilitator. It is the
equivalent of [`X402ProxyFacilitator.transferWithAuthorization`](/payments/smart-contracts)
on EVM: it pulls USDC from a payer, subtracts platform and treasury fees, and
settles the remainder to the recipient — atomically, in a single transaction.
This first version is intentionally minimal. It settles same-chain USDC
payments on Solana and nothing else: no cross-chain (Across) routing, no MRDN
cashback, and no batched settlement (those live only on the EVM facilitator
today).
Integrations should read the program ID, facilitator pubkey, and on-chain
config from `GET /v1/solana/facilitator` at runtime rather than hardcoding
them, so they keep working across any redeploys.
## Deployment
| Network | Cluster | Program ID | Status |
| --------------- | ------------ | --------------------------------------------- | ------ |
| `solana` | mainnet-beta | `Ro6hz1smrm5zDh73849eDqKna9dE1EkPsWekAB5rBWm` | Live |
| `solana-devnet` | devnet | `Ro6hz1smrm5zDh73849eDqKna9dE1EkPsWekAB5rBWm` | Live |
Built with **Anchor 0.32.1**. The config account is a PDA at seeds `["config"]`,
derived from the program ID.
USDC mints the program settles against:
| Network | USDC Mint |
| --------------- | ---------------------------------------------- |
| `solana` | `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` |
| `solana-devnet` | `4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU` |
## Why it looks different from the EVM facilitator
On EVM, the payer cannot join the settlement transaction without paying gas, so
x402 relies on EIP-3009: the payer signs an off-chain authorization, and the
facilitator submits it on-chain where the token contract verifies the signature.
Solana needs none of that machinery:
1. **A transaction can have multiple signers, and any of them can pay the fee.**
The payer (`from`) signs the settlement transaction as the authority of their
USDC token account. The backend signer co-signs as `payer` (fee payer) and
submits it. The payer's transaction signature *is* the authorization — no
in-program signature verification required.
2. **Settlement is atomic within one transaction**, so there is no escrow hop.
The EVM contract first pulls the full amount into itself and then distributes;
here the program splits funds directly from the payer's token account via up
to three `transfer_checked` CPIs (platform fee, treasury fee, recipient net).
From the client's perspective the x402 flow is unchanged:
```mermaid theme={"system"}
sequenceDiagram
participant User as User (payer)
participant Seller
participant Facilitator as Meridian Facilitator
participant Program as meridian_x402
Seller->>User: HTTP 402 + payment requirements
User->>Facilitator: GET /v1/solana/facilitator
(fee payer, program id, mint, treasury, fees, paused)
User->>User: Build transfer_with_authorization tx, sign as token authority
User->>Seller: X-PAYMENT: base64(paymentPayload { transaction })
Seller->>Facilitator: POST /v1/settle (paymentPayload + requirements)
Facilitator->>Facilitator: Validate the signed transaction
Facilitator->>Program: Co-sign as fee payer, submit
Program->>Program: Enforce window, split fees, settle net atomically
Program-->>Facilitator: InstantSettlement event
Facilitator-->>Seller: { success, transaction: signature }
```
What is kept for parity with the EVM `transferWithAuthorization`:
* `valid_after` / `valid_before` settlement window, checked against the on-chain clock
* a 32-byte `nonce` for x402 payment correlation and idempotency
* identical fee economics (platform fee off gross, treasury fee off the remainder)
## Architecture
### Config account
A single global PDA (`seeds = ["config"]`) holds the program's configuration:
| Field | Type | Purpose |
| ------------------ | -------- | ----------------------------------------------------- |
| `authority` | `Pubkey` | Admin: fee updates, pause, treasury / signer rotation |
| `backend_signer` | `Pubkey` | Backend signer allowed to submit settlements |
| `treasury` | `Pubkey` | Wallet that owns the treasury-fee token account |
| `usdc_mint` | `Pubkey` | The only mint the program settles |
| `treasury_fee_bps` | `u16` | Protocol fee in basis points (max `1000` = 10%) |
| `paused` | `bool` | Circuit breaker for the settlement entrypoint |
| `bump` | `u8` | Config PDA bump |
### Instructions
| Instruction | Access | Purpose |
| ---------------------------------------------------------------------------------------- | --------------------------- | -------------------------- |
| `initialize(backend_signer, treasury, treasury_fee_bps)` | one-time | Create the `Config` PDA |
| `transfer_with_authorization(value, valid_after, valid_before, nonce, platform_fee_bps)` | payer + backend signer sign | Settle a payment |
| `set_treasury_fee_bps(bps)` | authority | Update the protocol fee |
| `set_treasury(pubkey)` | authority | Rotate the treasury wallet |
| `set_backend_signer(pubkey)` | authority | Rotate the backend signer |
| `set_paused(bool)` | authority | Pause / unpause settlement |
`transfer_with_authorization` account list:
| Account | Signer | Notes |
| ----------------- | ------ | ---------------------------------------------------------- |
| `payer` | ✓ | Backend signer (facilitator): pays the tx fee |
| `from` | ✓ | The paying user (USDC token authority) |
| `config` | | Config PDA |
| `usdc_mint` | | Must match `config.usdc_mint` |
| `from_token` | | Payer's USDC associated token account (authority = `from`) |
| `recipient_token` | | Recipient's USDC associated token account |
| `platform_token` | | *Optional* — omit for payments without a platform fee |
| `treasury_token` | | USDC token account owned by `config.treasury` |
| `token_program` | | SPL Token / Token-2022 program |
The settlement transaction does **not** create any token accounts. The payer,
recipient, platform (if used), and treasury USDC associated token accounts
must already exist, or settlement fails. The backend signer pays only the
transaction fee, never rent.
### Fee math
Identical to the EVM facilitator's `_settleAndDistribute`:
```
platform_fee = value * platform_fee_bps / 10_000 (0 if no platform account)
remainder = value - platform_fee
treasury_fee = remainder * treasury_fee_bps / 10_000 (skipped if platform == treasury)
net_amount = remainder - treasury_fee (→ recipient)
```
Both fees are capped at `MAX_FEE_BPS = 1000` (10%). Multiplication is widened to
`u128` so it cannot overflow. Each settlement emits an `InstantSettlement`
event with the full breakdown:
```rust theme={"system"}
InstantSettlement {
from, // payer wallet
recipient, // recipient token account
platform, // Option
nonce, // [u8; 32] — x402 payment correlation id
gross_amount, // value
platform_fee,
treasury_fee,
net_amount, // credited to the recipient
}
```
### Replay protection & the nonce
Replay protection is **transaction-level**, matching the reference x402 SVM
scheme. The paying user signs the settlement transaction itself, which embeds a
recent blockhash: the runtime rejects duplicate signatures, and the transaction
expires with the blockhash. Settling the same payment again would require a
fresh signature from the payer.
No nonce account is created on-chain, so no rent is locked per payment. The
32-byte `nonce` argument is carried into the `InstantSettlement` event for x402
payment correlation, and the facilitator additionally refuses to co-sign a nonce
it has already settled (a settlement cache in the payments table).
### Errors
| Error | Meaning |
| -------------------------- | ---------------------------------------------------- |
| `Paused` | The settlement entrypoint is paused |
| `Unauthorized` | Caller is not the config authority / backend signer |
| `FeeTooHigh` | A fee exceeds `MAX_FEE_BPS` (10%) |
| `InvalidValue` | `value` (or net after fees) is not greater than zero |
| `AuthorizationNotYetValid` | `now <= valid_after` |
| `AuthorizationExpired` | `now >= valid_before` |
| `InvalidMint` | Mint does not match `config.usdc_mint` |
(Treasury-token ownership is enforced by an Anchor account constraint, which
surfaces as a generic constraint error rather than a program-specific code.)
## How settlement is validated
The client builds and payer-signs the settlement transaction; the facilitator's
`POST /v1/settle` acts as the co-signing safety boundary. Before it adds the
backend signer's signature and submits, it checks that the transaction does
exactly one thing the backend signer is willing to pay for:
* the fee payer is the backend signer, and the transaction contains **exactly one**
`transfer_with_authorization` instruction against the Meridian program
* `payer` (account 0) is the backend signer; `from` (account 1) is a different signer
* `config` is the expected Config PDA and the token program is the SPL Token program
* the mint equals `paymentRequirements.asset`, and `value` equals `maxAmountRequired`
* the validity window is still open (`valid_after <= now`, `valid_before >= now + 6s`)
* `from_token`, `recipient_token`, and any `platform_token` are the correct
associated token accounts for the resolved recipient / platform, and
`platform_fee_bps` matches the organization's configured fee
* the payer's wallet signature is present and valid, and the backend signer has
not already signed
Because the program only moves USDC with the payer's signature and never creates
accounts, a structurally valid transaction means the backend signer risks only
the transaction fee. The recipient (and platform, in platform mode) is resolved
from the caller's Meridian **organization settings**, not blindly trusted from
the request.
## Deliberately omitted (vs. EVM V6)
Settlement is instant to every party, so there are no fee-accrual balances or
withdraw functions. Also out of scope for this version, all of which remain
EVM-only for now:
* MRDN cashback
* Cross-chain (Across) settlement
* Batch payments
## Building & running locally
The program lives in [`contracts-sol/`](https://github.com/meridian-protocol/meridian/tree/main/contracts-sol) in the Meridian
monorepo. Requires the Solana CLI (Agave) and Anchor 0.32.1 (`avm use 0.32.1`).
```bash theme={"system"}
cd contracts-sol
anchor build # compile + generate the IDL (target/idl/meridian_x402.json)
anchor test # spin up a local validator and run the test suite
```
The test suite covers the exact fee splits (with and without a platform fee),
nonce replay rejection, the validity window, the fee cap, a missing payer
signature, the treasury-as-platform skip, pause / unpause, and admin access
control. See `contracts-sol/README.md` and `contracts-sol/SETUP.md` for
deploying to devnet and running the facilitator + pay app against it.
## References
* [Solana payments (AI skill)](/ai-skills/solana) — end-to-end integration guide
* [Smart Contracts](/payments/smart-contracts) — the EVM facilitator
* [Supported Networks](/api-reference/supported-networks)
* [Payment Types](/api-reference/payment-types/overview)
* [Settle x402 Payment](/api-reference/endpoint/settle-payment)
# Quickstart
Source: https://docs.mrdn.finance/quickstart
Accept your first x402 payment in minutes
This guide takes you from zero to accepting USDC payments through Meridian on
any supported chain. The only dependency is `viem` — your server returns an
x402 challenge, the buyer signs a payment authorization off-chain, and your
server settles it through Meridian's API. No transaction is submitted by the
buyer and no gas is paid by either side.
```text theme={"system"}
1. Your server returns 402 + paymentRequirements
2. Buyer signs an EIP-3009 authorization (off-chain, gasless)
3. Buyer sends the signed payload to your server
4. Your server settles via Meridian POST /v1/settle
5. Meridian's facilitator executes the transfer on-chain
```
The code below is identical on every chain whose payment token supports
EIP-3009 (Base, Optimism, Arbitrum, Polygon, Ink, and more) — only the network
constants change. For chains without an EIP-3009 token (MegaETH, BSC, BOT
chain, Tempo), the buyer signs a Permit2 witness instead; see the
[non-EIP-3009 guide](/ai-skills/non-eip-3009).
Sign in with your wallet at [mrdn.finance/dev/api-keys](https://mrdn.finance/dev/api-keys) and create a key. Use a `pk_test_` key for development and a `pk_` key for production. Store it server-side:
```bash theme={"system"}
MERIDIAN_API_KEY=pk_test_...
```
See [API Keys](/essentials/api-keys) for details.
In your organization settings, configure the wallet that receives settled
funds. The recipient is tied to your API key — in the payment requirements,
`payTo` always stays pointed at the Meridian facilitator contract, never at
your own wallet.
Take the payment token and facilitator address for your chain from
[Supported Networks](/api-reference/supported-networks) and keep them in one
config object — everything below reads from it:
```typescript theme={"system"}
// Example: Base mainnet. Swap in any supported network's values.
const NETWORK = {
id: "base",
chainId: 8453,
token: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC
tokenName: "USD Coin", // EIP-712 domain name of the token
tokenVersion: "2", // EIP-712 domain version of the token
facilitator: "0x8E7769D440b3460b92159Dd9C6D17302b036e2d6",
};
```
For development, use a testnet (`pk_test_` key), e.g. Base Sepolia:
`chainId: 84532`, token `0x036CbD53842c5426634e7929541eC2318f3dCF7e`
(`tokenName: "USDC"`), facilitator
`0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A`. Test USDC is available from
[Circle's faucet](https://faucet.circle.com).
A minimal Base Sepolia test should use:
* `MERIDIAN_API_KEY=pk_test_...`
* a buyer wallet connected to Base Sepolia (`84532`)
* Base Sepolia USDC from Circle's faucet
* `paymentRequirements.network: "base-sepolia"`
* `paymentRequirements.payTo: "0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A"`
When an unpaid request hits your paid endpoint, respond with HTTP 402 and
the payment requirements:
```typescript theme={"system"}
const paymentRequirements = {
scheme: "exact",
network: NETWORK.id,
asset: NETWORK.token,
payTo: NETWORK.facilitator,
maxAmountRequired: "10000", // $0.01 in USDC base units (6 decimals)
resource: "https://your-api.example.com/api/premium",
description: "Access to premium content",
mimeType: "application/json",
maxTimeoutSeconds: 300,
extra: { name: NETWORK.tokenName, version: NETWORK.tokenVersion },
};
return Response.json(
{ x402Version: 1, accepts: [paymentRequirements] },
{ status: 402 },
);
```
To accept payments from more than one chain, return one requirement per
source chain in `accepts` — see [Payment
Types](/api-reference/payment-types/overview).
The buyer signs an EIP-3009 `TransferWithAuthorization` as typed data —
no approval, no transaction:
```typescript theme={"system"}
import { bytesToHex } from "viem";
const now = BigInt(Math.floor(Date.now() / 1000));
const authorization = {
from: account.address,
to: paymentRequirements.payTo as `0x${string}`,
value: BigInt(paymentRequirements.maxAmountRequired),
validAfter: 0n,
validBefore: now + BigInt(paymentRequirements.maxTimeoutSeconds),
nonce: bytesToHex(crypto.getRandomValues(new Uint8Array(32))),
};
const signature = await walletClient.signTypedData({
account,
domain: {
name: paymentRequirements.extra.name,
version: paymentRequirements.extra.version,
chainId: NETWORK.chainId,
verifyingContract: paymentRequirements.asset as `0x${string}`,
},
types: {
TransferWithAuthorization: [
{ name: "from", type: "address" },
{ name: "to", type: "address" },
{ name: "value", type: "uint256" },
{ name: "validAfter", type: "uint256" },
{ name: "validBefore", type: "uint256" },
{ name: "nonce", type: "bytes32" },
],
},
primaryType: "TransferWithAuthorization",
message: authorization,
});
```
Then send the payload to your server (bigints as decimal strings):
```typescript theme={"system"}
const paymentPayload = {
x402Version: 1,
scheme: "exact",
network: paymentRequirements.network,
payload: {
signature,
authorization: {
from: authorization.from,
to: authorization.to,
value: authorization.value.toString(),
validAfter: authorization.validAfter.toString(),
validBefore: authorization.validBefore.toString(),
nonce: authorization.nonce,
},
},
};
```
Your server settles the payment through Meridian, then serves the paid
response. Never expose the API key to the browser, and do not trust
buyer-supplied pricing, recipient, token, or network values. Rebuild or
look up the matching `paymentRequirements` on the server before settlement:
```typescript theme={"system"}
if (paymentPayload.network !== paymentRequirements.network) {
throw new Error("Payment network does not match the server requirement");
}
if (
paymentPayload.payload.authorization.to.toLowerCase() !==
paymentRequirements.payTo.toLowerCase()
) {
throw new Error("Payment must authorize the Meridian facilitator");
}
if (
paymentPayload.payload.authorization.value !==
paymentRequirements.maxAmountRequired
) {
throw new Error("Payment amount does not match the server price");
}
```
```typescript theme={"system"}
const response = await fetch("https://api.mrdn.finance/v1/settle", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MERIDIAN_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ paymentPayload, paymentRequirements }),
});
const result = await response.json();
if (!response.ok || !result.success) {
throw new Error(result.errorReason ?? "Settlement failed");
}
```
Open [Command Centre](/command-centre/transactions) to see the payment, its
settlement status, and your balance.
## Next steps
The full client-side flow: multi-chain challenges, requirement selection,
and error handling.
EIP-3009, Permit2, and Circle Gateway — and when to use which.
Chains, tokens, and contract addresses.
Self-contained integration instructions for AI coding agents.
# Roadmap
Source: https://docs.mrdn.finance/roadmap
Meridian is a payments facilitator. We're also building toward trustless refunds, cross-chain settlement, and **mrUSD**, a USD stablecoin issued via M0. The sections below follow those three tracks through 2026.
## 01. UMA Arbitration
**Status:** In progress
Today, refunds on Meridian are issued manually by merchants. UMA's optimistic oracle, the same dispute system used by Polymarket, adds a trustless escalation path for when refund requests are ignored or denied in bad faith.
For [EIP-8183](https://eips.ethereum.org/EIPS/eip-8183) agentic commerce jobs, UMA can serve as the evaluator: the independent party that attests whether work should be completed and paid out, or rejected and refunded.
* Buyer-initiated dispute escalation
* Neutral on-chain arbitration
* Automatic payout on resolution
This brings consumer-grade refund protection to x402 payments without requiring either party to trust a centralized arbiter.
## 02. Circle Nanopayments
**Status:** Completed
A new x402 settlement path built on top of Circle's [CCTP](https://www.circle.com/cross-chain-transfer-protocol) (Cross-Chain Transfer Protocol). Instead of routing USDC across chains through a bridge, CCTP burns USDC on the source chain and mints native USDC on the destination, giving Meridian a gas-free, capital-efficient cross-chain rail for small payments.
| | **Default path** | **Circle path** |
| ----------- | ---------------- | ------------------- |
| Speed | \< 2s settlement | Batched |
| Tokens | Multi-token | USDC only |
| Economics | Fee + cashback | No fee, no cashback |
| Cross-chain | Across bridge | Burn & mint |
Both paths remain **gas-free** for the payer. The new Circle path is optimized for high-frequency, small-dollar agent payments where zero fees and native USDC matter more than cashback.
## 03. mrUSD
**Status:** Planned
Meridian's native USD stablecoin, fully backed and issued via the [M0](https://m0.org/) network. mrUSD brings institutional-grade stability together with on-chain programmability purpose-built for agent-driven commerce.
* EIP-3009 authorization transfers built in
* Onramps, swaps, and cross-chain rails out of the box
* Powers agentic commerce flows natively across the Meridian stack
## Timeline
Q2 to Q4 2026.
Dates are directional. Scope and sequencing may shift as integrations land. The roadmap is intentionally opinionated about *what* ships, less so about *when*.
# Tokenomics
Source: https://docs.mrdn.finance/tokenomics
$MRDN token distribution, emissions, and cashback mechanics
## Token Distribution
The \$MRDN token has a carefully designed distribution model to ensure sustainable growth and proper incentive alignment across all stakeholders.
**Total Supply: 1,000,000,000 \$MRDN**
**Distribution Breakdown:**
**70% Emissions** - 700M tokens
**10% Treasury** - 100M tokens
**10% Team** - 100M tokens
**5% Liquidity & Listings** - 50M tokens
**3% Pool2** - 30M tokens
**1% Closed Round** - 10M tokens
**1% uOS Airdrop** - 10M tokens
**70%** of total supply for \$MRDN cashback emissions. Cashback starts at 2%,
decays over time, and is capped at \$5 of cashback value per eligible transaction.
**10%** of total supply Protocol development and ecosystem growth
**10%** of total supply 4-year linear vesting schedule
**5%** of total supply for \$MRDN/USDC trading liquidity & reserve for future listings
**3%** of total supply for additional liquidity incentives
**1%** of total supply to boot strap initial liquidity pool
**1%** of total supply Community distribution
## Emission Schedule
Exponential Decay Emission Model
**How it works:**
* **Continuous Decay:** Cashback rate decreases exponentially with total network transaction volume
* **Volume-Based:** Higher network usage naturally reduces emission rate over time
* **Smooth Transition:** Emissions decay continuously leading to halving events
* **Economic Alignment:** Early adopters receive higher rates while maintaining long-term sustainability
Decay Function
The cashback rate follows an exponential decay based on cumulative transaction
volume:
**Cashback Rate Formula:**
$y(x) = 0.02 \cdot e^{-13.9 \times 10^{-9} \cdot x}$
Where:
* $y(x)$ = Cashback percentage at volume $x$
* $x$ = Cumulative transaction volume processed (USD)
* $0.02$ = Initial cashback rate (2%)
* $13.9 \times 10^{-9}$ = Decay constant (adjustable parameter)
Emission Milestones
| Tokens Emitted | Current Rate |
| -------------- | ------------- |
| **0** | **2.0%** |
| **50M** | **1.0%** |
| **100M** | **0.5%** |
| **150M** | **0.25%** |
| **200M** | **0.125%** |
| **250M** | **0.0625%** |
| **300M** | **0.03125%** |
| **350M** | **0.015625%** |
**Key Parameters:**
* **Total Emission Supply:** 700M \$MRDN tokens
* **Per-Transaction Cap:** $5 of cashback value, paid in $MRDN
* **Halving Interval:** Every 50M tokens emitted
* **Decay Constant:** 13.9e-9
* **Volume Dependency:** Transaction volume requirements scale with token price
## Cashback Mechanism
How Cashback Works
Cashback rewards are paid in \$MRDN tokens for eligible x402 payments settled on
Base. The reward value follows the current cashback rate, but each transaction
is capped at **\$5 of cashback value** before conversion into \$MRDN.
```
Cashback Formula:
Total Payment × Current Cashback Rate = Cashback Amount (USD)
min(Cashback Amount, $5.00) = Capped Cashback Amount (USD)
Capped Cashback Amount ÷ $MRDN Price = $MRDN Tokens Received
```
\$MRDN is distributed to the cashback contract every few minutes as rewards. The
contract pays cashback FIFO: the first eligible transactions receive
cashback first, until the newly distributed rewards for that window are used.
Cashback is not paid for self-payments where the payer and recipient are the
same address.
Variable Token Payouts
Token payouts depend on market price:
* **Higher \$MRDN Price:** Fewer tokens received as cashback
* **Lower \$MRDN Price:** More tokens received as cashback
Example Calculation
```
Service Payment: $1000 USDC on Base x402
Cashback Calculation: $1000 × 0.02 = $20.00 USDC value
Per-Transaction Cap: min($20.00, $5.00) = $5.00 USDC value
$MRDN/USDC Price: $0.50
$MRDN Tokens Queued: $5.00 ÷ $0.50 = 10 $MRDN
```
## Fee Structure
Transaction Fees
A **1% protocol fee** is collected for x402 transactions on Base:
* **Fee Timing:** Collected during Base x402 settlement
* **Fee Application:** Applies only to x402 transactions on Base
* **No Fee on Permit Transfers:** Apps such as `pay.mrdn.finance` use permit for
gasless token transfers; the 1% protocol fee is not subtracted from those
transfers
* **No Fee on Non-Base x402:** The 1% protocol fee is not collected on x402
transactions outside Base
* **Fee Destination:** Collected by protocol treasury
* **Purpose:** Sustainable protocol revenue and ecosystem development funding
### Fee Distribution Example
```
Base x402 payment processed: $1000 USDC
├── Protocol Fee: -$10 USDC (1%)
├── Net to Recipient: $990 USDC
└── Cashback to Payer: up to $5 value in $MRDN, paid FIFO from reward distributions
```
## Token Utility
Primary Use Cases
* **Cashback Rewards:** Base x402 rewards paid in \$MRDN
* **Network Participation:** Incentivizes usage of Meridian payment infrastructure
* **Governance:** Future governance rights for protocol decisions
* **Real Yield:** Protocol-generated revenue provides sustainable returns
Economic Model
The tokenomics create a deflationary pressure through: - **Decreasing
Emissions:** Halving cycles reduce new token supply over time - **Usage-Based
Rewards:** Higher network usage increases token demand - **Fee Collection:**
Protocol revenue provides sustainable funding model
## Trading & Liquidity
Primary Trading Pair
The \$MRDN token will be primarily traded against USDC:
* **Main Pair:** \$MRDN/USDC
* **Liquidity Pool:** 5% of total supply allocated for initial \$MRDN/USDC liquidity
* **Price Discovery:** Market-driven pricing through decentralized exchanges
* **Stability:** USDC pairing provides stable reference point for cashback calculations
* **Auto Liquidity Provision:** USDC collected from Base x402 fees adds protocol owned liquidity
## Long-term Sustainability
Balanced Incentives
* **Early Adopters:** Higher cashback rates in early cycles reward pioneers -
**Long-term Users:** Sustained value through decreasing supply inflation -
**Protocol Growth:** Treasury and fee structure fund continuous development
Emission Flexibility
The dynamic emission model ensures: - **Early Adopters:** Higher absolute
emissions reward network pioneers - **Long-term Sustainability:** Emission rate
decreases with remaining supply - **Adaptive Schedule:** Halving triggered by
time or economic milestones provides flexibility