An investment in knowledge pays the best interest.
Benjamin Franklin

Reserve

Reserve APIs#

Retrieve reserve balances and recommended reserve settings for your subscription.

Overview#

  • Base URL:
    markup
    https://api.pay.ledger1.ai/portalpay
  • Authentication (Developer APIs): All requests require an Azure APIM subscription key header:
    • markup
      Ocp-Apim-Subscription-Key: {your-subscription-key}
  • Gateway posture: APIM custom domain is the primary endpoint. Azure Front Door (AFD) may be configured as an optional/fallback edge; if enabled, APIM accepts an internal
    markup
    x-edge-secret
    per policy.
  • Rate limiting headers (if enabled):
    markup
    X-RateLimit-Limit
    ,
    markup
    X-RateLimit-Remaining
    ,
    markup
    X-RateLimit-Reset
  • Identity: Wallet identity is resolved automatically at the gateway based on your subscription; client requests must not include wallet identity headers.
See authentication and security details in
markup
../auth.md
. For OpenAPI schema details, refer to
markup
../../public/openapi.yaml
.

GET /portalpay/api/reserve/balances#

Return current reserve balances, by currency, for the merchant associated with your subscription.

Request#

Headers:

markup
Ocp-Apim-Subscription-Key: {your-subscription-key}

Example Requests:

curl -X GET "https://api.pay.ledger1.ai/portalpay/api/reserve/balances" \
  -H "Ocp-Apim-Subscription-Key: $APIM_SUBSCRIPTION_KEY"
GET/portalpay/api/reserve/balances

Try It: Reserve Balances

Fetch current reserve balances by currency.

Default is the APIM custom domain. For AFD, enter only the AFD endpoint host (e.g., https://afd-endpoint-pay-...) without any path; the /portalpay prefix is added automatically for /api/* and /healthz.

The key is kept only in memory while this page is open. Do not paste secrets on shared machines.

For public reads (GET /api/inventory, GET /api/shop/config), include the merchant wallet (0x-prefixed 40-hex). Non-GET requests should use JWT and will ignore this header.

Using server-side proxy to avoid CORS. Requests go through /api/tryit-proxy to AFD/APIM.
cURL
curl -X GET "https://api.pay.ledger1.ai/portalpay/api/reserve/balances"
Response Status
Response Headers
Response Body

Response#

Success (200 OK):

json
{
  "balances": [
    { "currency": "USDC", "reserved": 100.00, "target": 150.00 },
    { "currency": "ETH", "reserved": 0.025, "target": 0.050 }
  ],
  "updatedAt": 1698765432000
}

Notes:

  • markup
    reserved
    is the currently held amount.
  • markup
    target
    is the recommended or configured target amount (if available).

Response Headers (when enabled at gateway):

  • markup
    X-RateLimit-Limit
  • markup
    X-RateLimit-Remaining
  • markup
    X-RateLimit-Reset

POST /portalpay/api/reserve/recommend (Admin – JWT)#

Update reserve recommendation settings (e.g., jurisdictions or strategy inputs) via the PortalPay admin UI. This operation is not callable via a developer APIM key.

Request#

Headers:

markup
Content-Type: application/json
Cookie: cb_auth_token=...

Body (JSON) example (deployment-dependent):

json
{
  "taxConfig": { "jurisdictions": ["US-CA"], "provider": "ava" },
  "defaultJurisdictionCode": "US-CA"
}

Response#

Success (200 OK):

json
{ "ok": true }

Other responses:

  • 400:
    markup
    invalid_input
  • 403:
    markup
    forbidden
  • 429:
    markup
    rate_limited
  • 500:
    markup
    failed

Notes:

  • Client-provided wallet headers are ignored; the authenticated admin wallet is used.
  • CSRF protections apply for browser-based writes.

GET /portalpay/api/reserve/recommend#

Return recommended reserve targets by currency based on recent activity and configuration.

Request#

Headers:

markup
Ocp-Apim-Subscription-Key: {your-subscription-key}

Example Requests:

curl -X GET "https://api.pay.ledger1.ai/portalpay/api/reserve/recommend" \
  -H "Ocp-Apim-Subscription-Key: $APIM_SUBSCRIPTION_KEY"
GET/portalpay/api/reserve/recommend

Try It: Reserve Recommendations

Fetch recommended reserve targets by currency.

Default is the APIM custom domain. For AFD, enter only the AFD endpoint host (e.g., https://afd-endpoint-pay-...) without any path; the /portalpay prefix is added automatically for /api/* and /healthz.

The key is kept only in memory while this page is open. Do not paste secrets on shared machines.

For public reads (GET /api/inventory, GET /api/shop/config), include the merchant wallet (0x-prefixed 40-hex). Non-GET requests should use JWT and will ignore this header.

Using server-side proxy to avoid CORS. Requests go through /api/tryit-proxy to AFD/APIM.
cURL
curl -X GET "https://api.pay.ledger1.ai/portalpay/api/reserve/recommend"
Response Status
Response Headers
Response Body

Response#

Success (200 OK):

json
{
  "recommendations": [
    { "currency": "USDC", "target": 200.00, "basis": "30d_median_payouts" },
    { "currency": "ETH", "target": 0.075, "basis": "fees_buffer" }
  ],
  "windowDays": 30,
  "updatedAt": 1698765432000
}

Notes:

  • markup
    basis
    indicates the heuristic used (deployment-dependent).
  • Use these values to adjust reserve levels for smoothing payouts and covering fees.

Response Headers (when enabled at gateway):

  • markup
    X-RateLimit-Limit
  • markup
    X-RateLimit-Remaining
  • markup
    X-RateLimit-Reset

Error Responses#

401 Unauthorized

json
{ "error": "unauthorized", "message": "Missing or invalid subscription key" }

403 Forbidden

json
{ "error": "forbidden", "message": "Insufficient privileges or origin enforcement failed" }

429 Too Many Requests

json
{ "error": "rate_limited", "resetAt": 1698765432000 }

500 Internal Server Error

json
{ "error": "failed", "message": "Unable to retrieve reserve data" }

Code Examples#

JavaScript/TypeScript#

typescript
const APIM_SUBSCRIPTION_KEY = process.env.APIM_SUBSCRIPTION_KEY!;
const BASE_URL = 'https://api.pay.ledger1.ai/portalpay';

export async function getReserveBalances() {
  const res = await fetch(`${BASE_URL}/api/reserve/balances`, {
    headers: { 'Ocp-Apim-Subscription-Key': APIM_SUBSCRIPTION_KEY }
  });
  if (!res.ok) throw new Error(`reserve_balances_failed_${res.status}`);
  return res.json() as Promise<{
    balances: { currency: string; reserved: number; target?: number }[];
    updatedAt?: number;
  }>;
}

export async function getReserveRecommendations() {
  const res = await fetch(`${BASE_URL}/api/reserve/recommend`, {
    headers: { 'Ocp-Apim-Subscription-Key': APIM_SUBSCRIPTION_KEY }
  });
  if (!res.ok) throw new Error(`reserve_recommend_failed_${res.status}`);
  return res.json() as Promise<{
    recommendations: { currency: string; target: number; basis?: string }[];
    windowDays?: number;
    updatedAt?: number;
  }>;
}

Python#

python
import os, requests
APIM_SUBSCRIPTION_KEY = os.environ['APIM_SUBSCRIPTION_KEY']
BASE_URL = 'https://api.pay.ledger1.ai/portalpay'

def get_reserve_balances():
  r = requests.get(
    f'{BASE_URL}/api/reserve/balances',
    headers={'Ocp-Apim-Subscription-Key': APIM_SUBSCRIPTION_KEY}
  )
  r.raise_for_status()
  return r.json()

def get_reserve_recommendations():
  r = requests.get(
    f'{BASE_URL}/api/reserve/recommend',
    headers={'Ocp-Apim-Subscription-Key': APIM_SUBSCRIPTION_KEY}
  )
  r.raise_for_status()
  return r.json()

Notes on Auth Models#

  • Developer reads must use
    markup
    Ocp-Apim-Subscription-Key
    . Wallet identity is resolved automatically at the gateway based on your subscription; the backend trusts the resolved identity.
  • Admin/UI writes (e.g., POST
    markup
    /portalpay/api/reserve/recommend
    ) require JWT cookies (
    markup
    cb_auth_token
    ) with CSRF and role checks; any client-supplied wallet headers are ignored on writes.
  • Client requests do not include wallet identity for developer APIs; it is resolved at the gateway per subscription.