Payment Receiver Configs

Payment Receiver Configs specify where and how you want to receive payments. They are separate from billing flows, allowing you to reuse payment settings across multiple flows or provide them when creating charges.

Why Receiver Configs?

Billing flows are logical groupings for charges (e.g., "Image API Usage", "Premium Feature X"). They don't need to know payment details.

Receiver configs are your payment preferences:

  • Which blockchain network (e.g., solana-mainnet)
  • Which asset (e.g., USDC)
  • Which wallet address receives payments
  • Escrow settings, facilitator URLs, timeouts

This separation allows:

  • Flexibility: Use different payment configs per charge without changing flows
  • Reusability: Create configs once, use across multiple flows
  • Simplicity: Create flows without payment setup complexity
  • Multiple wallets: Have different configs for different wallets (even same network/asset)

Key Concepts

Multiple Configs Per Organization

You can create multiple receiver configs for the same network and asset. For example:

  • "Main Wallet" - solana-mainnet / USDC0xMain...
  • "Treasury Wallet" - solana-mainnet / USDC0xTreasury...
  • "Operations Wallet" - solana-mainnet / USDC0xOps...

Each config has a friendly name, so you can choose which one to use when creating charges.

Default Config

You can mark one config as default (is_default: true). If you don't specify a config when creating a charge, the default will be used automatically.

Fallback Chain

When creating a charge, Meshpay resolves x402 configuration using this priority:

  1. Charge request x402 fields (if provided directly)
  2. Receiver config (if receiver_config_id provided)
  3. Default receiver config (if is_default: true exists)
  4. Connected Solana wallet (if user has primary wallet connected)
  5. Error (require x402 configuration)

This means you can:

  • Provide payment details directly per charge
  • Reference a specific receiver config
  • Rely on your default config
  • Use your connected wallet automatically (for Solana users)

Creating a Receiver Config

Via API

POST
/v1/billing/receiver-configs

Request Body:

FieldTypeRequiredDescriptionExample
namestring
Required
User-friendly name (e.g., 'Main Wallet', 'Treasury Wallet')Main Wallet
networkstring
Required
Blockchain network (e.g., 'solana-mainnet', 'base-mainnet')solana-mainnet
assetstring
Required
Asset/token (e.g., 'USDC', 'USDT')USDC
pay_to_addressstring
Required
Wallet address to receive payments0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
escrow_addressstringOptionalMeshpay settlement wallet (required if collection_mode is 'escrow')0x...
facilitatorstringOptionalFacilitator endpoint URL for payment confirmationhttps://facilitator.example.com/webhook
max_timeout_secondsintegerOptionalMaximum timeout for payment (default: 60)60
collection_modestringOptionalCollection mode: 'direct' (payments go to your wallet) or 'escrow' (payments go to Meshpay settlement wallet)direct
is_defaultbooleanOptionalSet as default config for organization (default: false)

Example:

import requests
import os
url = "https://api.orvion.sh/v1/billing/receiver-configs"
headers = {
"Authorization": f"Bearer {os.environ['MESHPAY_API_KEY']}",
"Content-Type": "application/json"
}
data = {
"name": "Main Wallet",
"network": "solana-mainnet",
"asset": "USDC",
"pay_to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"facilitator": "https://facilitator.example.com/webhook",
"max_timeout_seconds": 60,
"collection_mode": "direct",
"is_default": True
}
response = requests.post(url, json=data, headers=headers)
config = response.json()

Response:

{
  "id": "config_abc123",
  "organization_id": "org_xyz",
  "name": "Main Wallet",
  "network": "solana-mainnet",
  "asset": "USDC",
  "pay_to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "escrow_address": null,
  "facilitator": "https://facilitator.example.com/webhook",
  "max_timeout_seconds": 60,
  "collection_mode": "direct",
  "is_default": true,
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-15T10:30:00Z"
}

Using Receiver Configs When Creating Charges

When creating a charge, you have three options:

Option 1: Use Receiver Config ID

Reference a specific receiver config:

cURL
curl -X POST "https://api.orvion.sh/v1/flows/flow_123/charges" \
-H "Authorization: Bearer $MESHPAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 100,
"currency": "USD",
"receiver_config_id": "config_abc123"
}'

Option 2: Provide x402 Fields Directly

Provide payment details directly in the charge request:

cURL
curl -X POST "https://api.orvion.sh/v1/flows/flow_123/charges" \
-H "Authorization: Bearer $MESHPAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 100,
"currency": "USD",
"network": "solana-mainnet",
"asset": "USDC",
"pay_to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
}'

Option 3: Use Default Config or Connected Wallet

Don't provide any payment config - Meshpay will:

  1. Use your default receiver config (if is_default: true exists)
  2. Or use your connected Solana wallet (if you have one)
  3. Or return an error
cURL
curl -X POST "https://api.orvion.sh/v1/flows/flow_123/charges" \
-H "Authorization: Bearer $MESHPAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 100,
"currency": "USD"
}'

Managing Receiver Configs

List All Configs

GET
/v1/billing/receiver-configs

Returns all receiver configs for your organization, sorted by default first, then by creation date.

Get a Config

GET
/v1/billing/receiver-configs/{config_id}

Update a Config

PATCH
/v1/billing/receiver-configs/{config_id}

All fields are optional. If you set is_default: true, any existing default will be cleared.

Delete a Config

DELETE
/v1/billing/receiver-configs/{config_id}

Note: Deleting a config doesn't affect existing charges or transactions. Only future charges that reference this config will fail.

Fallback Chain Explained

When you create a charge without specifying payment configuration, Meshpay uses this fallback chain:

┌─────────────────────────────────────┐
│  Create Charge                      │
│  (no payment config provided)       │
└──────────────┬──────────────────────┘
               │
               ▼
┌─────────────────────────────────────┐
│  1. Check charge request            │
│     x402 fields provided?            │
└──────────────┬──────────────────────┘
               │ No
               ▼
┌─────────────────────────────────────┐
│  2. Check receiver_config_id        │
│     provided in charge request?     │
└──────────────┬──────────────────────┘
               │ No
               ▼
┌─────────────────────────────────────┐
│  3. Check default receiver config   │
│     (is_default: true) exists?      │
└──────────────┬──────────────────────┘
               │ No
               ▼
┌─────────────────────────────────────┐
│  4. Check connected Solana wallet   │
│     (only if user_id available)     │
│     → Use: solana-mainnet/USDC/    │
│       primary wallet address        │
└──────────────┬──────────────────────┘
               │ No
               ▼
┌─────────────────────────────────────┐
│  5. Error: x402 config required     │
└─────────────────────────────────────┘

Collection Modes

Direct Mode

Configuration:

{
  "collection_mode": "direct",
  "pay_to_address": "0xYourWallet..."
}

Flow:

  • Payments go directly to your pay_to_address
  • No escrow wallet needed
  • Faster settlement
  • Simpler flow

Use when: You want payments to go directly to your wallet without escrow.

Escrow Mode

Configuration:

{
  "collection_mode": "escrow",
  "pay_to_address": "0xYourWallet...",
  "escrow_address": "0xMeshpaySettlement..."
}

Flow:

  • Payments go to Meshpay escrow_address first
  • Funds are then distributed according to payout splits
  • Required for complex payout logic or splits

Use when: You need escrow, splits, or complex payout distribution.

Note: escrow_address is required when collection_mode is escrow.

Best Practices

1. Create Named Configs

Give your configs descriptive names that indicate their purpose:

  • ✅ "Main Wallet" - Clear purpose
  • ✅ "Treasury Wallet" - Indicates use case
  • ✅ "Operations USDC" - Includes asset info
  • ❌ "Config 1" - Not descriptive
  • ❌ "Wallet" - Too generic

2. Set a Default Config

Mark your most commonly used config as default:

{
  "name": "Main Wallet",
  "is_default": true,
  ...
}

This allows you to create charges without specifying payment config.

3. Use Connected Wallets

If you're using Solana, connect your wallet in the dashboard. This enables automatic fallback to your primary wallet when no config is provided.

4. Multiple Configs for Same Network/Asset

You can have multiple configs for the same network/asset combo:

  • "Main Wallet" - solana-mainnet / USDC0xMain...
  • "Treasury Wallet" - solana-mainnet / USDC0xTreasury...

Choose which one to use per charge via receiver_config_id.

5. Per-Charge Override

You can override config settings per charge by providing x402 fields directly:

{
  "amount": 100,
  "currency": "USD",
  "receiver_config_id": "config_abc123",
  "pay_to_address": "0xDifferentWallet..."  // Override pay_to_address
}

Examples

Example 1: Simple Setup with Default Config

Step 1: Create a default receiver config

POST /v1/billing/receiver-configs
{
  "name": "Main Wallet",
  "network": "solana-mainnet",
  "asset": "USDC",
  "pay_to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "is_default": true
}

Step 2: Create charges without payment config

POST /v1/flows/flow_123/charges
{
  "amount": 100,
  "currency": "USD"
}

The charge will automatically use your default config.

Example 2: Multiple Wallets, Choose Per Charge

Step 1: Create multiple configs

POST /v1/billing/receiver-configs
{
  "name": "Main Wallet",
  "network": "solana-mainnet",
  "asset": "USDC",
  "pay_to_address": "0xMain...",
  "is_default": true
}

POST /v1/billing/receiver-configs
{
  "name": "Treasury Wallet",
  "network": "solana-mainnet",
  "asset": "USDC",
  "pay_to_address": "0xTreasury...",
  "is_default": false
}

Step 2: Use specific config per charge

POST /v1/flows/flow_123/charges
{
  "amount": 100,
  "currency": "USD",
  "receiver_config_id": "config_treasury"  // Use treasury wallet
}

Example 3: Override Config Per Charge

POST /v1/flows/flow_123/charges
{
  "amount": 100,
  "currency": "USD",
  "receiver_config_id": "config_abc123",
  "pay_to_address": "0xOverride..."  // Override the config's address
}

Error Handling

Missing Escrow Address

If collection_mode is escrow but escrow_address is missing:

{
  "detail": "escrow_address is required for escrow collection mode"
}

Solution: Provide escrow_address when creating or updating a config with collection_mode: "escrow".

No x402 Configuration Found

If you create a charge without payment config and no fallback is available:

{
  "detail": "x402 configuration required. Provide x402 fields in charge request, receiver_config_id, create a default receiver config, or connect a Solana wallet."
}

Solution:

  • Create a default receiver config
  • Or provide x402 fields in the charge request
  • Or connect a Solana wallet (for automatic fallback)

Related Documentation