Coin API — Complete Reference
api.js and logic.js.Table of contents
1) Overview
This documentation mirrors the exact behavior implemented in the server files (api.js and logic.js).
Key architecture: the HTTP API enqueues write operations into a bounded in‑memory queue (with optional DB persistence for pending jobs) and then either waits for the queue worker result or returns a legacy‑shaped response for backward compatibility. The queue attaches a txId to payloads for idempotency; whether that txId appears in the HTTP response depends on per‑route mapping rules implemented in doEnqueueAndMap.
2) Authentication
Endpoints that require authentication use an Authorization header with a session token:
Authorization: Bearer <sessionId>
Content-Type: application/json
The middleware resolves the session using db.getSession and sets req.userId. If the session is invalid the route returns 403 with { error: "operation failed" }.
3) Queue & idempotency
- The server uses
queue.enqueueAndWait(payload). Before enqueueing,doEnqueueAndMapensurespayload.args.ipis set and attachespayload.txId= a random UUID if not provided. - If the queue refuses with
ENQUEUE_REJECTEDthe wrapper attempts an in‑memory cache and a DB pending job. If that also fails, the API returns429/{ error: "QUEUE_FULL" }. The cache worker later flushes pending items into the queue. - Per‑route legacy mapping:
legacyReturn: 'transfer'→ response is always{ success: true }(hides txId).legacyReturn: 'transfer_card'→ response is{ success: true, txId?, date? }if the worker result contains atxId, otherwise{ success: true }.- Default (no legacyReturn) → returns the worker result as‑is.
4) Endpoints (complete list)
POST /api/login
Description: Authenticates a user and creates a session. The server hashes the password using SHA‑256 before checking.
Body:
{
"username": "alice",
"password": "secret"
}
Response (success):
{
"sessionCreated": true,
"passwordCorrect": true,
"userId": "123456789012345678",
"sessionId": "<session-token>",
"saldo": 12.345678,
"cooldownRemainingMs": 0
}
If IP is locked due to too many failed attempts, returns 429 with error: "IP blocked. Try again in X seconds.".
POST /api/register
Description: Creates a new user. Enforces a 1‑second IP registration cooldown (24h block in code, but currently set to 1s).
Body:
{
"username": "bob",
"password": "s3cret"
}
Response:
{
"success": true,
"userId": "987654321",
"sessionId": "<session-token>"
}
Errors: 409 if username already taken, 429 if IP blocked or queue full.
POST /api/logout
Description: Deletes the session token provided in the Authorization header.
Auth: Bearer token
Response: { success: true }
POST /api/account/change
Description: Changes the username and/or password for the authenticated user. Requires both username and password in the body.
Auth: Bearer token
Body:
{
"username": "newalice",
"password": "newpass"
}
Response: { success: true }
POST /api/account/unregister
Description: Deletes the user account (clears username/password and removes the session).
Auth: Bearer token
Response: { success: true }
POST /api/account/update
Description: Updates the username and password hash for the user.
Auth: Bearer token
Body:
{
"username": "alice",
"passwordHash": "sha256 hash"
}
Response: { success: true }
POST /api/transfer
Description: Transfers coins from the authenticated user to another user. This endpoint uses legacy response (hides txId).
Auth: Bearer token
Body:
{
"toId": "987654321",
"amount": 0.001
}
Response: { success: true } (txId hidden).
Note: If you need the txId, either supply your own txId in the body or use the card‑based endpoint.
POST /api/transfer/card
Description: Transfers coins using a card code. Resolves the owner from the card hash. May return txId if available.
Body:
{
"cardCode": "abcd-efgh-1234",
"toId": "11111",
"amount": 0.01
}
Response (if txId available):
{
"success": true,
"txId": "uuid-12345-abcdef",
"date": "2025-12-07T12:00:00.000Z"
}
Response (legacy fallback): { success: true }
POST /api/card/pay
Description: Card‑to‑card transfer (alias of /api/transfer_between_cards).
Body:
{
"fromCard": "abcd-ef",
"toCard": "wxyz-12",
"amount": 0.002
}
Response: same as /api/transfer/card.
POST /api/claim
Description: Claims the daily (or configured) reward. Respects cooldown set in claimConfig.
Auth: Bearer token
Response (success):
{
"success": true,
"claimed": 0.05
}
Response (cooldown):
{
"error": "Cooldown active",
"nextClaimInMs": 12345,
"cooldownMs": 86400000,
"lastClaimTs": 1234567890
}
GET /api/claim/status
Description: Returns the remaining cooldown for the authenticated user.
Auth: Bearer token
Response:
{
"cooldownRemainingMs": 12345,
"lastClaimTimestamp": 1234567890,
"cooldownMs": 86400000
}
POST /api/card
Description: Retrieves the card code of the authenticated user.
Auth: Bearer token
Response:
{
"cardCode": "abc123..."
}
POST /api/card/reset
Description: Generates a new card code for the user (invalidates the old one).
Auth: Bearer token
Response:
{
"newCode": "def456..."
}
POST /api/card/info
Description: Get account information by card code (no authentication required).
Body:
{
"cardCode": "abcdef"
}
Response:
{
"success": true,
"userId": "123",
"coins": "0.00012345",
"sats": 12345,
"totalTransactions": 5,
"lastClaimTs": 1234567890,
"cooldownRemainingMs": 0,
"cooldownMs": 86400000
}
POST /api/card/claim
Description: Claims reward using a card code (no auth).
Body: { "cardCode": "abcdef" }
Response:
{
"success": true,
"claimed": 0.05
}
On cooldown: 429 with error: "COOLDOWN_ACTIVE".
POST /api/backup/create
Description: Generates backup codes for the authenticated user. Up to 12 codes will be created if the user has a positive balance.
Auth: Bearer token
Response: { success: true }
POST /api/backup/list
Description: Lists the backup codes for the authenticated user.
Auth: Bearer token
Response:
{
"backups": ["code1", "code2"]
}
POST /api/backup/restore
Description: Consumes a backup code and transfers the entire balance of the original owner to the authenticated user. Cannot restore your own backup.
Auth: Bearer token
Body: { "backupId": "code" }
Response: { success: true }
GET /api/totalusers
Description: Returns the total number of registered users.
Response:
{
"totalUsers": 42
}
GET /api/tx/:txid
Description: Looks up a transaction by its ID. Returns detailed information including amounts in satoshis and coins.
Response (found):
{
"success": true,
"tx": {
"id": "uuid-12345",
"date": "2025-12-07T12:00:00.000Z",
"from": "11111",
"to": "22222",
"amountSats": 12345,
"amountCoins": "0.00012345"
}
}
Response (not found): 404 with { error: "INVALID_TRANSACTION", message: "Transaction not found" }
GET /api/transactions
Description: Lists transactions for the authenticated user with pagination (page parameter).
Auth: Bearer token
Query: ?page=1
Response:
{
"transactions": [
{
"id": "tx-1",
"date": "2025-12-07T12:00:00.000Z",
"from_id": "11111",
"to_id": "22222",
"amount": "0.001"
}
],
"page": 1
}
GET /api/user/:userId/balance
Description: Returns the balance of the authenticated user.
Auth: Bearer token
Response:
{
"coins": 12.345678
}
GET /api/rank
Description: Returns the top 25 users by balance and the total coins in circulation.
Auth: Bearer token
Response:
{
"totalCoins": 1234.56,
"rankings": [
{ "id": "111", "username": "alice", "coins": 100.5 },
...
]
}
POST /api/bill/create
Description: Creates a bill (invoice) from the authenticated user (or from a specified fromId) to a recipient. The bill expires after the given duration.
Auth: Bearer token
Body:
{
"toId": "recipient_id",
"amount": 0.5,
"time": "1d" // optional, defaults to now
}
Response:
{
"success": true,
"billId": "bill-abc123"
}
POST /api/bill/pay
Description: Pays a bill using the authenticated user's balance.
Auth: Bearer token
Body: { "billId": "bill-abc123" }
Response: { success: true }
POST /api/bill/list
Description: Lists bills to pay (incoming) and bills to receive (outgoing) for the authenticated user.
Auth: Bearer token
Body (optional): { "page": 1 }
Response:
{
"toPay": [
{ "id": "b1", "from_id": "111", "to_id": "222", "amount": "0.1", "date": "..." }
],
"toReceive": [
{ "id": "b2", "from_id": "333", "to_id": "222", "amount": "0.2", "date": "..." }
],
"page": 1
}
POST /api/bill/list/from
Description: Lists bills that the authenticated user must pay (incoming).
Auth: Bearer token
Body: { "page": 1 }
Response: { "toPay": [...], "page": 1 }
POST /api/bill/list/to
Description: Lists bills that the authenticated user will receive (outgoing).
Auth: Bearer token
Body: { "page": 1 }
Response: { "toReceive": [...], "page": 1 }
POST /api/bill/create/card
Description: Creates a bill using card codes (resolves owner IDs from the cards). At least one of fromCard or toCard must be provided.
Body:
{
"fromCard": "abcd-ef",
"toCard": "wxyz-12",
"amount": 0.5,
"time": "1d"
}
Response: { success: true, billId: "..." }
POST /api/bill/pay/card
Description: Pays a bill using a card code (the payer is resolved from the card).
Body:
{
"cardCode": "abcd-ef",
"billId": "bill-123"
}
Response: { success: true }
GET /api/queue/info
Description: Returns queue statistics (only available if EXPOSE_INTERNALS=true).
Response:
{
"queued": 3,
"usedBytes": 1234,
"maxBytes": 524288,
"maxOpsPerSecond": 500
}
GET /api/queue/status/:id
Description: Returns the status of a specific queue item (if exposed).
Response: { state: "done", ts: 1234567890, result: {...} }
5) txId: generation & when responses include it
- Every enqueued payload receives a
payload.txId(UUID) for idempotency; the server only sets it if the client didn't provide one. - Whether the HTTP response includes the
txIddepends on the route mapping:legacyReturn: 'transfer'→ response is always{ success: true }(txId hidden).legacyReturn: 'transfer_card'→ response is{ success: true, txId?, date? }if the worker result contains a txId; otherwise{ success: true }.- Default (no legacyReturn) → returns the worker result as‑is, which may include
txIdif the underlying logic function returns it.
- To always receive the
txId, provide it yourself in the request body or modifydoEnqueueAndMapmapping.
6) Errors & status codes
- 400 – invalid parameters:
{ error: 'Invalid parameters' } - 403 – authentication failure:
{ error: 'operation failed' } - 404 – resource not found (e.g. card, transaction)
- 409 – conflict (username already taken)
- 429 – rate limit exceeded, queue full, or IP locked:
{ error: "QUEUE_FULL" }or{ error: "RATE_LIMIT_EXCEEDED" } - 504 – queue wait timeout:
{ error: 'QUEUE_TIMEOUT' } - 500 – internal server error:
{ error: 'Internal error' }
7) Appendix — op names
login, register, logout, account_change, account_unregister, account_update,
transfer, transfer_card, claim, claim_status, get_card, reset_card,
backup_create, backup_list, backup_restore,
get_balance, rank, total_users, tx_lookup, transactions,
bill_list, bill_list_from, bill_list_to, bill_create, bill_pay,
card_info, card_claim, transfer_between_cards,
bill_create_card, bill_pay_card
Developer note: to change whether a route returns txId, edit doEnqueueAndMap mapping in api.js. You can also supply your own txId in the request to maintain idempotency and correlate with /api/tx/:txid.