Beta. This endpoint is not final. Field names and response shapes can change before general availability.
Overview
Every Finn workspace has one wallet. Calls, phone number rent, and other usage draw down the wallet balance. When the balance reaches zero, outbound campaigns stop dispatching and inbound calls are rejected before they are answered, so treat the balance as an operational signal, not an accounting detail.
The Wallet API is read-only in beta. You can read the current balance and page through the transactions that produced it. Topping up is done in the dashboard, not through the API. There is no API method for adding funds, and none is planned for the first release.
Base URL is https://api.hirefinn.ai/v1. All requests need Authorization: Bearer <FINN_API_KEY>. See authentication and api-conventions.
Get the wallet
curl https://api.hirefinn.ai/v1/wallet \
-H "Authorization: Bearer $FINN_API_KEY"
{
"object": "wallet",
"id": "wal_8f3a21c9",
"balance": 42350,
"currency": "USD",
"updated_at": "2026-07-30T09:14:02Z"
}
| Field | Type | Notes |
|---|---|---|
id | string | Wallet identifier. One wallet per workspace. |
balance | integer | Balance in the smallest currency unit. 42350 with currency: "USD" means 423.50 USD. |
currency | string | ISO 4217 code. Fixed at workspace creation and not changeable through the API. |
updated_at | string | RFC 3339 timestamp of the last balance change. |
Read balance as a minor-unit integer. If you render it as a float without dividing by 100, you will show a balance a hundred times too large, and this is the most common integration mistake with this endpoint.
Whether the response also carries a low-balance threshold or an auto-recharge object is not yet settled. Do not depend on fields beyond the four above.
List transactions
curl "https://api.hirefinn.ai/v1/wallet/transactions?limit=20" \
-H "Authorization: Bearer $FINN_API_KEY"
{
"object": "list",
"data": [
{
"object": "wallet_transaction",
"id": "wtx_5c1d90ab",
"type": "call_usage",
"amount": -1840,
"currency": "USD",
"balance_after": 42350,
"description": "Outbound call, 4m 12s",
"call_id": "call_71b0e4f2",
"created_at": "2026-07-30T09:14:02Z"
},
{
"object": "wallet_transaction",
"id": "wtx_44ae02f1",
"type": "topup",
"amount": 50000,
"currency": "USD",
"balance_after": 44190,
"description": "Card top-up",
"call_id": null,
"created_at": "2026-07-29T17:02:44Z"
}
],
"has_more": true,
"next_cursor": "wtx_44ae02f1"
}
amount is signed. Debits are negative, credits are positive. balance_after is the wallet balance immediately after the transaction was applied, which lets you reconcile a page without replaying the whole ledger.
| Field | Type | Notes |
|---|---|---|
id | string | Transaction identifier. |
type | string | See the table below. |
amount | integer | Signed minor units. Negative for debits. |
balance_after | integer | Balance after this entry. |
description | string | Human-readable label. Free text. Do not parse it. |
call_id | string or null | Set for call-derived entries. Null otherwise. Join against api-calls. |
created_at | string | RFC 3339 timestamp. |
Transaction types
type | Sign | Meaning |
|---|---|---|
call_usage | negative | Charge for a completed call. |
number_rent | negative | Recurring charge for a rented phone number. See api-phone-numbers. |
topup | positive | Funds added from the dashboard. |
adjustment | either | Manual correction applied by Finn support. |
refund | positive | Reversal of an earlier charge. |
Treat this list as open. New types can be added without a version bump, so route unknown values to a default branch rather than throwing.
Query parameters
| Parameter | Type | Default | Notes |
|---|---|---|---|
limit | integer | 20 | Page size. |
cursor | string | none | Cursor from next_cursor. |
type | string | none | Filter to one transaction type. |
created_after | string | none | RFC 3339. Inclusive. |
created_before | string | none | RFC 3339. Exclusive. |
Pagination follows api-pagination. Order is newest first. A call charge lands after the call ends, not while it is in progress, so a transaction list read seconds after a call completes may not include it yet.
Poll the balance
import os
import requests
BASE = "https://api.hirefinn.ai/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['FINN_API_KEY']}"}
def balance_minor_units() -> int:
r = requests.get(f"{BASE}/wallet", headers=HEADERS, timeout=10)
r.raise_for_status()
return r.json()["balance"]
def low(threshold_major: float = 100.0) -> bool:
return balance_minor_units() < threshold_major * 100
if low():
print("Wallet below 100.00. Top up before the next campaign.")
Poll on a schedule rather than before each call. The endpoint counts against your api-rate-limits budget, and a balance read in a per-call hot path is the first thing to hit the limit during a campaign.
Whether Finn emits a webhook on low balance is not yet settled. Until it is documented in webhook-events, polling is the only supported mechanism.
Errors
| Status | Condition |
|---|---|
401 | Missing or invalid API key. |
403 | Key lacks wallet read scope. |
404 | No wallet provisioned for the workspace. |
429 | Rate limited. Back off and retry. |
Error bodies follow api-errors. A 404 here usually means the workspace was created but never completed billing setup, not that the wallet was deleted.