Base URL: http://localhost:3000/api/v1
All requests require X-API-Key header. See Authentication Guide.
List endpoints support cursor-based pagination for efficient data retrieval and consistency.
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
limit |
integer | 20 | 100 | Number of records per page |
cursor |
string | null | N/A | Opaque cursor for pagination position (from next_cursor or prev_cursor) |
direction |
string | next |
N/A | Pagination direction: next or prev |
snapshotAt |
string | null | N/A | Optional: ISO-8601 timestamp for consistent snapshot pagination (see below) |
All paginated endpoints return:
{
"success": true,
"data": [ /* records */ ],
"pagination": {
"next_cursor": "eyJ0aW1lc3RhbXAiOiIyMDI2LTAz...",
"prev_cursor": null,
"limit": 20,
"direction": "next",
"snapshotAt": "2026-03-26T05:00:00.000Z"
}
}Cursor pagination assumes the underlying dataset is immutable between requests. With concurrent inserts:
- Records inserted before the cursor position may be permanently missed
- Records inserted after the cursor position may appear unexpectedly on the next page
This primarily affects batch processing and reconciliation use cases.
Use the optional snapshotAt parameter to paginate a consistent snapshot. Records with timestamp < snapshotAt are guaranteed to appear exactly once across all pages.
# Start pagination session with snapshot
GET /api/v1/donations?limit=50&snapshotAt=2026-03-26T05:00:00Z
# All subsequent requests use the same snapshotAt
GET /api/v1/donations?limit=50&cursor=<next_cursor>&snapshotAt=2026-03-26T05:00:00Z
# To process new records, start a new session with current timestamp
GET /api/v1/donations?limit=50&snapshotAt=2026-03-26T05:30:00ZFor more details, see Cursor Pagination Stability.
Create a new donation.
Headers: X-API-Key, Content-Type: application/json, Idempotency-Key (optional)
Body:
{
"senderPublicKey": "GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN",
"recipientPublicKey": "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H",
"amount": "10.00",
"memo": "optional note"
}Response 201:
{
"success": true,
"data": {
"id": 1,
"transactionHash": "abc123...",
"status": "completed",
"amount": "10.00",
"memo": "optional note",
"createdAt": "2026-03-26T05:00:00.000Z"
}
}List all donations (paginated).
Query params:
limit(1–100, default 20)cursor(opaque pagination cursor)direction(nextorprev)snapshotAt(optional ISO-8601 timestamp for consistent pagination)status(filter by status)
Response 200:
{
"success": true,
"data": [ { "id": 1, "amount": "10.00", "status": "completed", "createdAt": "2026-03-26T05:00:00Z", ... } ],
"pagination": {
"next_cursor": "...",
"prev_cursor": null,
"limit": 20,
"direction": "next",
"snapshotAt": "2026-03-26T05:00:00Z"
}
}Get recent donations.
Query params: limit (default 10, max 100)
Get a specific donation by ID.
Response 404 if not found:
{ "success": false, "error": "Donation not found" }Get configured donation amount limits.
Response 200:
{ "success": true, "data": { "min": "0.0001", "max": "10000" } }Verify a donation transaction on the blockchain.
Body:
{ "transactionHash": "abc123..." }Update donation status (admin only).
Body:
{ "status": "completed" }Valid statuses: pending, completed, failed, cancelled
Register a wallet.
Body:
{
"publicKey": "GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN",
"label": "My Wallet"
}List all wallets.
Get wallet by ID.
Get all transactions for a wallet address.
Update wallet label or metadata.
Create a recurring donation schedule.
Body:
{
"senderPublicKey": "GAAZI...",
"recipientPublicKey": "GBRPY...",
"amount": "5.00",
"frequency": "weekly"
}Valid frequencies: daily, weekly, monthly
List all recurring schedules.
Get a specific schedule.
Cancel a recurring schedule.
Daily donation volume. Query: startDate, endDate (ISO 8601)
Weekly donation volume.
Overall summary: total donations, total volume, unique donors/recipients.
Stats grouped by donor wallet.
Stats grouped by recipient wallet.
Fee analytics summary.
Analytics for a specific wallet address.
Paginated transaction list. Query: limit, cursor, walletAddress
Sync transactions from Stellar network for a wallet.
Body:
{ "publicKey": "GAAZI..." }Decode and inspect an arbitrary Stellar XDR envelope. Returns the decoded transaction details without storing them.
Headers: X-API-Key (Admin), Content-Type: application/json
Body:
{ "xdr": "AAAAAgAAAAD..." }Response 200:
{
"success": true,
"data": {
"hash": "abc123...",
"source": "GAAZI...",
"fee": "100",
"sequence": "123456",
"operations": [ ... ],
"memo": { "type": "none" },
"signatures": [ ... ]
}
}Inspect the XDR envelope of a stored transaction by its ID.
Headers: X-API-Key (Admin)
Response 200:
Returns the same decoded structure as POST /admin/inspect/xdr.
Returns API health status. No authentication required.
Response 200:
{ "status": "ok" }All errors follow this shape:
{
"success": false,
"error": "Human-readable message",
"code": "ERROR_CODE"
}| Status | Meaning |
|---|---|
| 400 | Validation error / bad request |
| 401 | Missing or invalid API key |
| 403 | Insufficient permissions |
| 404 | Resource not found |
| 409 | Conflict (e.g. duplicate idempotency key) |
| 429 | Rate limit exceeded |
| 500 | Internal server error |
For full request/response examples, see API Examples.