An investment in knowledge pays the best interest.
Benjamin Franklin

Billing

Billing APIs#

Retrieve current wallet balances and usage information 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 do not include wallet identity and any wallet headers are stripped.
See authentication and security details in
markup
../auth.md
. For OpenAPI schema details, refer to
markup
../../public/openapi.yaml
.

GET /portalpay/api/billing/balance#

Return the current wallet balance and usage 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/billing/balance" \
  -H "Ocp-Apim-Subscription-Key: $APIM_SUBSCRIPTION_KEY"
GET/portalpay/api/billing/balance

Try It: Billing Balance

Fetch current wallet balance and usage.

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/billing/balance"
Response Status
Response Headers
Response Body

Response#

Success (200 OK):

json
{
  "balances": [
    { "currency": "USDC", "available": 1250.42, "reserved": 150.00 },
    { "currency": "ETH", "available": 1.2345, "reserved": 0.0500 }
  ],
  "usage": {
    "monthUsd": 399.00,
    "lastUpdatedAt": 1698765432000
  }
}

Notes:

  • markup
    balances
    shows available and reserved amounts by currency.
  • markup
    usage.monthUsd
    may reflect fees or consumption metrics depending on deployment configuration.

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 balance" }

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 getBillingBalance() {
  const res = await fetch(`${BASE_URL}/api/billing/balance`, {
    headers: { 'Ocp-Apim-Subscription-Key': APIM_SUBSCRIPTION_KEY }
  });
  if (!res.ok) throw new Error(`billing_failed_${res.status}`);
  return res.json() as Promise<{
    balances: { currency: string; available: number; reserved: number }[];
    usage?: { monthUsd?: number; lastUpdatedAt?: number };
  }>;
}

Python#

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

def get_billing_balance():
  r = requests.get(
    f'{BASE_URL}/api/billing/balance',
    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 operations use JWT cookies (
    markup
    cb_auth_token
    ) with CSRF and role checks for sensitive actions; billing balance is a developer read.
  • Client requests do not include wallet identity; APIM strips wallet headers and stamps the resolved identity.