Skip to content

Top Up Card

Create a top-up request that transfers funds from the user's Holyheld main account to the Holyheld card. The request is accepted synchronously, but the balance update is asynchronous — it may take up to 5 minutes to appear on the card.

Endpoint

POST https://apicore.holyheld.com/v4/ai-agents/topup-request

Request

HeaderRequiredValue
AuthorizationBearer <token>
Content-Typeapplication/json

Request body:

json
{
  "amount": "50.00"
}
FieldTypeRequiredDescription
amountstringAmount in EUR to top up. Must be a decimal string matching ^\d+(\.\d{1,2})?$

Amount format rules

The amount field must be a string (not a number) and must match the pattern ^\d+(\.\d{1,2})?$:

ValueValid?Note
"50"Integer amounts are valid
"50.00"Two decimal places
"50.5"One decimal place
"50.123"More than 2 decimal places
50.00Number type — must be a string
"€50"No currency symbol
"-10"No negative values

Use amount.toFixed(2) in JavaScript to format a number as a valid amount string.

Response

200 OK — top-up request accepted

json
{
  "status": "ok"
}

A 200 response means the request was accepted and the top-up process has begun. It does not mean the balance has already updated. Poll GET /balance to confirm the settlement.

Balance updates are asynchronous

After receiving a 200, the card balance may take up to 5 minutes to reflect the top-up. Do not assume the top-up is reflected immediately. Always poll to confirm before reporting success to the user.

The polling pattern

After a successful POST /topup-request, poll GET /balance until the balance increases or a timeout is reached.

javascript
const BASE_URL = 'https://apicore.holyheld.com/v4/ai-agents';
const POLL_INTERVAL_MS = 30_000;  // 30 seconds
const TIMEOUT_MS = 5 * 60_000;   // 5 minutes

async function topUpAndConfirm(amount, token) {
  const headers = {
    Authorization: `Bearer ${token}`,
    'Content-Type': 'application/json',
  };

  // 1. Record balance before top-up
  const beforeRes = await fetch(`${BASE_URL}/balance`, { headers });
  const before = await beforeRes.json();
  const balanceBefore = parseFloat(before.payload.balance);

  // 2. Request the top-up
  const topupRes = await fetch(`${BASE_URL}/topup-request`, {
    method: 'POST',
    headers,
    body: JSON.stringify({ amount: parseFloat(amount).toFixed(2) }),
  });

  if (!topupRes.ok) {
    const err = await topupRes.json();
    throw new Error(`Top-up failed: ${err.errorCode} — ${err.error}`);
  }

  // 3. Poll until balance increases or timeout
  const deadline = Date.now() + TIMEOUT_MS;

  while (Date.now() < deadline) {
    await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));

    const currentRes = await fetch(`${BASE_URL}/balance`, { headers });
    const current = await currentRes.json();
    const balanceNow = parseFloat(current.payload.balance);

    if (balanceNow > balanceBefore) {
      return {
        success: true,
        previousBalance: balanceBefore,
        newBalance: balanceNow,
        added: balanceNow - balanceBefore,
      };
    }
  }

  // Timeout — top-up may still complete; advise the user to check later
  throw new Error(
    'Top-up accepted but balance has not updated within 5 minutes. ' +
    'Check your Holyheld card balance in a few minutes.'
  );
}
bash
curl -X POST https://apicore.holyheld.com/v4/ai-agents/topup-request \
  -H "Authorization: Bearer $HOLYHELD_AGENT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"amount": "50.00"}'
python
import httpx, time, os

BASE_URL = 'https://apicore.holyheld.com/v4/ai-agents'

def topup_and_confirm(amount: float, token: str) -> dict:
    headers = {
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json',
    }

    # 1. Record balance before
    before = httpx.get(f'{BASE_URL}/balance', headers=headers)
    balance_before = float(before.json()['payload']['balance'])

    # 2. Request top-up
    res = httpx.post(
        f'{BASE_URL}/topup-request',
        headers=headers,
        json={'amount': f'{amount:.2f}'},
    )
    if res.status_code != 200:
        err = res.json()
        raise RuntimeError(f"{err['errorCode']}: {err['error']}")

    # 3. Poll
    deadline = time.time() + 300  # 5 minutes
    while time.time() < deadline:
        time.sleep(30)
        current = httpx.get(f'{BASE_URL}/balance', headers=headers)
        balance_now = float(current.json()['payload']['balance'])
        if balance_now > balance_before:
            return {'new_balance': balance_now, 'added': balance_now - balance_before}

    raise TimeoutError('Top-up accepted but balance not updated within 5 minutes.')

Error responses

400 Bad Request — malformed amount

json
{
  "status": "error",
  "errorCode": "WRONG_REQUEST",
  "error": "Failed to parse request body"
}

Check the amount format. See Amount format rules above.

500 — Insufficient balance

json
{
  "status": "error",
  "errorCode": "AI_TOPUP_INSUFFICIENT_BALANCE",
  "error": "Insufficient balance for top up"
}

The user does not have enough available balance on their Holyheld main account. The agent cannot resolve this autonomously — notify the user that they need to add funds to their Holyheld account.

500 — Spending limit exceeded

json
{
  "status": "error",
  "errorCode": "AI_TOPUP_LIMIT_EXCEEDED",
  "error": "Limit exceeded"
}

The agent's cumulative spending limit has been reached. Only the user can reset this limit from the Holyheld dashboard. Do not retry — further attempts will continue to fail until the user resets the limit. Notify the user immediately.

500 / default — Internal server error

json
{
  "status": "error",
  "errorCode": "INTERNAL_SERVER_ERROR",
  "error": "Internal Server Error"
}

An unexpected server-side error occurred. Retry with exponential backoff (1s → 2s → 4s). If the error persists after 3 attempts, surface a generic failure message to the user.

Error handling decision tree:

POST /topup-request

       ├── 200 OK ──────────────────► Poll GET /balance (up to 5 min)
       │                                      │
       │                               balance increased?
       │                                 ├── Yes ──► Report success
       │                                 └── No  ──► Report timeout; advise manual check

       ├── 400 WRONG_REQUEST ────────► Fix amount format and retry immediately

       ├── 401/403 AI_AUTHORIZATION_INVALID ──► Check Bearer token or get new agent instructions

       ├── 500 AI_TOPUP_INSUFFICIENT_BALANCE ──► Notify user: add funds to Holyheld account
       │                                         Do NOT retry — user action required

       ├── 500 AI_TOPUP_LIMIT_EXCEEDED ────────► Notify user: reset limit in dashboard
       │                                         Do NOT retry — user action required

       └── 500 INTERNAL_SERVER_ERROR ──────────► Retry with exponential backoff (max 3×)

See Error Reference for full recovery guidance.

Next steps

Read the Error Reference for handling every error code. Then see Build an MCP Server to wrap these endpoints as Claude tools.