Skip to main content

Credit Balance

Description

Credit tokens directly to a user's spot balance. Testnet only — this endpoint is hard-gated by the TESTNET_ONLY=true environment variable. On mainnet (or any environment where TESTNET_ONLY is not exactly true), the route responds with 404 DISABLED to keep the surface uniform.

Admin only. Requires the ADMIN_API_KEY environment variable to be set on the server and passed as X-API-Key in the request header.

Side effects on success:

  • Increments available for the (user_address, token) pair in spot_balances (upsert — creates the row if it doesn't exist).
  • Writes an audit row in spot_admin_credits with admin_actor = "admin_api_key" (the shared admin key is not per-user, so this generic actor is recorded).
  • Pushes a balance update via WebSocket so the UI reflects the new balance immediately without polling.

HTTP Request

POST /admin/spot/balances/credit (X-API-Key: ADMIN_API_KEY)

Testnet only (TESTNET_ONLY=true required on the server).

Weight

0 — admin endpoints have no weight limit. Each market mutation pings the engine with a ReloadMarket command so the in-memory MarketCache picks up the change without restart.

Request Parameters

NameTypeRequiredDescription
user_addressSTRINGYESEVM wallet address of the recipient (e.g. "0xabc..."). Stored and matched lowercase.
tokenSTRINGYESToken symbol to credit (e.g. "DF", "USDT").
amountDECIMALYESAmount to credit as a string. Must be > 0 — returns 400 AMOUNT_NON_POSITIVE otherwise.
reasonSTRINGNOFree-text reason recorded in the audit log. Omit if not applicable.

Response Example

200 OK

{
"ok": true
}
FieldNotes
okAlways true on success. The balance is updated and the audit row has been committed.

Error Responses

HTTPerrorWhen
400AMOUNT_NON_POSITIVEamount is <= 0.
404DISABLEDTESTNET_ONLY env var is not set to "true" on this server (mainnet guard).
500DB_ERRORUnexpected Postgres error during the balance upsert or audit insert. Investigate server logs.

Full list: Error Codes.

Code Examples

cURL

ADMIN_API_KEY="your_admin_api_key"

curl -s -X POST "https://api-sepolia.p99.world/api/v1/admin/spot/balances/credit" \
-H "X-API-Key: ${ADMIN_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"user_address": "0xabc123def456abc123def456abc123def456abc1",
"token": "DF",
"amount": "1000",
"reason": "testnet faucet grant"
}'

Python

import requests

ADMIN_API_KEY = "your_admin_api_key"
BASE_URL = "https://api-sepolia.p99.world/api/v1"

def credit_balance(user_address: str, token: str, amount: str, reason: str | None = None) -> dict:
body = {
"user_address": user_address,
"token": token,
"amount": amount,
}
if reason is not None:
body["reason"] = reason

r = requests.post(
f"{BASE_URL}/admin/spot/balances/credit",
json=body,
headers={"X-API-Key": ADMIN_API_KEY, "Content-Type": "application/json"},
timeout=5,
)
r.raise_for_status()
return r.json()

result = credit_balance(
user_address="0xabc123def456abc123def456abc123def456abc1",
token="DF",
amount="1000",
reason="testnet faucet grant",
)
print(result["ok"])