This reference documents the HTTP endpoints currently registered by the
backend. Except for health checks and metrics, API routes are mounted under
/v1. Replace values in angle brackets in the examples with real IDs,
addresses, timestamps, and signatures. JSON response fields shown are
representative; timestamps are ISO 8601 strings.
Routes marked Admin signature require all three headers:
x-admin-address: an allowed Stellar public key configured byADMIN_ADDRESSorADMIN_ADDRESSES.x-admin-timestamp: the current Unix timestamp in milliseconds.x-admin-signature: the SEP-53 Stellar message signature forMETHOD:PATH_AND_QUERY:TIMESTAMP, where the timestamp is the exact header value. For example, signGET:/v1/ngo-applications?limit=20:1760000000000for that request.
The signed message must use the generic Stellar message-signing operation.
Signatures expire when the timestamp is more than five minutes from the
server's clock, and a signature cannot be replayed. Admin routes return
401 for missing or invalid authentication, 503 with
{"error":"admin_auth_not_configured"} if no admin address is configured,
and 401 with {"error":"timestamp_unit_mismatch"} for a timestamp in
seconds.
Routes marked Public do not require authentication. Public directory,
stream, and impact endpoints may return 304 Not Modified when the
If-None-Match header matches their ETag.
Stream onChainId values are stored as JavaScript bigint values in the
backend. Amounts originating from the contract, including rate, lastRate,
balance, and withdrawn, are stored as decimal strings to preserve the
contract's full integer precision. Aggregated amounts such as totalCommitted
and totalWithdrawn are returned as decimal strings too.
JSON cannot serialize JavaScript bigint values directly. The API therefore
converts onChainId to a decimal string before sending stream responses;
on-chain event streamId values are also serialized as strings (or null).
Treat these fields as strings when consuming the API. Do not convert IDs or
amounts to JavaScript number, which can silently lose integer precision.
For exact integer arithmetic, parse decimal strings with BigInt in
JavaScript, and convert results back to strings for JSON.
These endpoints are mounted at the server root, not under /v1.
Auth: Public
Params: None.
Checks database and Stellar RPC connectivity. Returns 200 when both checks
succeed and 503 otherwise.
{ "status": "ok", "db": "ok", "rpc": "ok" }Auth: Public
Params: None.
Checks database connectivity and indexer progress. Returns 200 when ready,
or 503 if the indexer has not started, is too far behind, or a dependency is
unavailable.
{
"status": "ok",
"lag": 5,
"latestLedger": 123455,
"checkpointLedger": 123450
}Auth: Public
Params: None.
Returns Prometheus exposition text (text/plain; version=0.0.4), including
HTTP request and duration metrics, indexer checkpoint and lag, and webhook
delivery metrics. Example response:
# HELP streamgive_http_requests_total Total HTTP requests handled.
# TYPE streamgive_http_requests_total counter
streamgive_http_requests_total{method="GET",route="/health",status_code="200"} 1
# HELP streamgive_http_request_duration_seconds HTTP request duration in seconds.
# TYPE streamgive_http_request_duration_seconds summary
streamgive_http_request_duration_seconds_sum{method="GET",route="/health",status_code="200"} 0.001
streamgive_http_request_duration_seconds_count{method="GET",route="/health",status_code="200"} 1
# HELP streamgive_indexer_checkpoint_ledger Last ledger checkpointed by the indexer.
# TYPE streamgive_indexer_checkpoint_ledger gauge
streamgive_indexer_checkpoint_ledger 123450
# HELP streamgive_indexer_latest_ledger Latest ledger observed from Stellar RPC.
# TYPE streamgive_indexer_latest_ledger gauge
streamgive_indexer_latest_ledger 123455
# HELP streamgive_indexer_lag_ledgers Difference between the latest and checkpoint ledgers.
# TYPE streamgive_indexer_lag_ledgers gauge
streamgive_indexer_lag_ledgers 5
# HELP streamgive_notification_deliveries_total Webhook notification delivery attempts.
# TYPE streamgive_notification_deliveries_total counter
streamgive_notification_deliveries_total{outcome="success"} 1
streamgive_notification_deliveries_total{outcome="failure"} 0
Auth: Public
Query params:
| Name | Type | Default | Description |
|---|---|---|---|
limit |
integer, 1–100 | 100 |
Maximum results. |
cursor |
UUID | — | Continue after this NGO ID. |
sort |
newest, oldest, name |
newest |
Result ordering. |
q |
string, up to 100 characters | — | Case-insensitive substring search on the public name. |
Lists verified NGOs. nextCursor is the last returned NGO ID when another
page is available, otherwise null.
{
"ngos": [
{
"id": "<UUID>",
"ownerAddress": "<STELLAR_PUBLIC_KEY>",
"name": "Example Aid",
"displayName": null,
"verified": true,
"createdAt": "<ISO-8601>",
"updatedAt": "<ISO-8601>"
}
],
"nextCursor": null
}Auth: Admin signature
Query params:
| Name | Type | Default | Description |
|---|---|---|---|
limit |
integer, 1–100 | 100 |
Maximum results. |
cursor |
UUID | — | Continue after this NGO ID. |
verified |
true or false |
— | Filter by verification status. |
Lists verified and unverified NGOs.
{
"ngos": [
{
"id": "<UUID>",
"ownerAddress": "<STELLAR_PUBLIC_KEY>",
"name": "Example Aid",
"displayName": null,
"verified": false,
"createdAt": "<ISO-8601>",
"updatedAt": "<ISO-8601>"
}
],
"nextCursor": null
}Auth: Public
Query params: address (required): Stellar public key (G followed by
55 base32 characters).
Looks up an NGO profile by its owner address. Returns 400 {"error":"invalid_request"} for an invalid address and 404 {"error":"not_found"} if there is no matching NGO. The response has the same
shape as GET /v1/ngos/{id}; see that endpoint's example response.
Auth: Public
Path params: id (required): NGO UUID.
Returns an NGO profile, impact totals, and up to ten recent streams. Returns
400 {"error":"invalid_request"} for an invalid ID or
404 {"error":"not_found"} if no NGO exists.
{
"id": "<UUID>",
"ownerAddress": "<STELLAR_PUBLIC_KEY>",
"name": "Example Aid",
"displayName": null,
"verified": true,
"createdAt": "<ISO-8601>",
"updatedAt": "<ISO-8601>",
"registered": true,
"description": "Supporting local communities.",
"website": "https://example.org",
"country": "Example",
"stats": {
"totalCommitted": "12000",
"totalWithdrawn": "2000",
"activeStreamCount": 2,
"donorCount": 3
},
"recentStreams": [
{
"id": "<UUID>",
"donor": { "address": "<STELLAR_PUBLIC_KEY>" },
"tokenAddress": "<STELLAR_CONTRACT_ADDRESS>",
"rate": "100",
"balance": "1000",
"withdrawn": "200",
"status": "ACTIVE",
"createdAt": "<ISO-8601>",
"onChainId": "42"
}
],
"recentStreamsNextCursor": null
}description, website, and country are null when no approved
application supplies them. The public name uses the display name when one
is set; registered indicates whether an on-chain registry name exists.
Auth: Public
Path params: id (required): NGO UUID.
Query params: limit (integer, 1–100, default 100) and cursor (donor
UUID, optional).
Lists donors with streams for this NGO. Each donor's totalCommitted is a
decimal string. Returns 400 {"error":"invalid_request"} for invalid
parameters and 404 {"error":"not_found"} if the NGO does not exist.
{
"donors": [
{
"id": "<UUID>",
"address": "<STELLAR_PUBLIC_KEY>",
"totalCommitted": "1200"
}
],
"nextCursor": null
}Auth: Admin signature
Path params: id (required): NGO UUID.
JSON body: displayName (optional; string or null).
Updates the public display name. Returns the updated NGO record with name
set to the display name when present, otherwise its registered name. Returns
400 {"error":"invalid_request"} for invalid input and
404 {"error":"not_found"} if the NGO does not exist.
{
"id": "<UUID>",
"ownerAddress": "<STELLAR_PUBLIC_KEY>",
"name": "Example Aid",
"displayName": "Example Aid",
"verified": true,
"createdAt": "<ISO-8601>",
"updatedAt": "<ISO-8601>"
}Auth: Public
Query params:
| Name | Type | Default | Description |
|---|---|---|---|
sort |
committed or withdrawn |
committed |
Amount used to rank donors. |
order |
asc or desc |
desc |
Sort direction. |
limit |
integer, 1–100 | 100 |
Maximum results. |
cursor |
UUID | — | Continue after this donor ID. |
Returns donor totals across all streams.
{
"donors": [
{
"id": "<UUID>",
"address": "<STELLAR_PUBLIC_KEY>",
"createdAt": "<ISO-8601>",
"totalCommitted": "1200",
"totalWithdrawn": "200"
}
],
"nextCursor": null
}Invalid query parameters or an unknown cursor return
400 {"error":"invalid_request"}.
Auth: Public
Path params: address (required): Stellar public key (G followed by
55 base32 characters).
Returns one donor's totals, number of active streams, and distinct NGO count.
Returns 400 {"error":"invalid_request"} for an invalid address and
404 {"error":"not_found"} if no donor exists.
{
"id": "<UUID>",
"address": "<STELLAR_PUBLIC_KEY>",
"createdAt": "<ISO-8601>",
"totalCommitted": "1200",
"totalWithdrawn": "200",
"activeStreamCount": 2,
"distinctNgoCount": 1
}Auth: Public
Query params:
| Name | Type | Default | Description |
|---|---|---|---|
donor |
Stellar public key | — | Filter by donor address. |
ngo |
UUID | — | Filter by NGO ID. |
ngoAddress |
Stellar public key | — | Filter by NGO owner address. |
token |
Stellar contract address | — | Filter by token contract. |
status |
ACTIVE or CANCELLED |
— | Filter by stream status. |
limit |
integer, 1–100 | 100 |
Maximum results. |
cursor |
UUID | — | Continue after this stream ID. |
Returns streams newest first. On-chain integer values are serialized as decimal strings.
{
"streams": [
{
"id": "<UUID>",
"onChainId": "42",
"donorId": "<UUID>",
"ngoId": "<UUID>",
"tokenAddress": "<STELLAR_CONTRACT_ADDRESS>",
"rate": "100",
"lastRate": null,
"balance": "1000",
"withdrawn": "200",
"status": "ACTIVE",
"createdTxHash": "<TRANSACTION_HASH>",
"createdAt": "<ISO-8601>",
"updatedAt": "<ISO-8601>",
"donor": { "address": "<STELLAR_PUBLIC_KEY>" },
"ngo": {
"id": "<UUID>",
"name": "Example Aid",
"displayName": null,
"ownerAddress": "<STELLAR_PUBLIC_KEY>",
"registered": true
}
}
],
"hasMore": false,
"nextCursor": null
}Invalid filters return 400 {"error":"invalid_request"}.
Auth: Public
Path params: id (required): stream UUID.
Returns one stream in the same shape as an item from
GET /v1/streams. Returns 400 {"error":"invalid_request"} for an invalid
ID and 404 {"error":"not_found"} if no stream exists. Example response: the
single stream object shown in the GET /v1/streams example (without the
streams, hasMore, and nextCursor wrapper).
Auth: Public
Path params: id (required): stream UUID.
Query params: limit (integer, 1–100, default 100) and cursor (event
UUID, optional).
Returns the stream's indexed activity newest first. streamId is a decimal
string or null.
{
"events": [
{
"id": "<UUID>",
"type": "created",
"streamId": "42",
"ledger": 123450,
"txHash": "<TRANSACTION_HASH>",
"payload": {
"donor": "<STELLAR_PUBLIC_KEY>",
"ngo": "<STELLAR_PUBLIC_KEY>",
"token": "<STELLAR_CONTRACT_ADDRESS>",
"deposit": "1000",
"rate": "100"
},
"createdAt": "<ISO-8601>"
}
],
"hasMore": false
}Returns 400 {"error":"invalid_request"} for invalid parameters and
404 {"error":"not_found"} if the stream does not exist.
Auth: Public
Params: None.
Returns platform-wide totals.
{
"totalCommitted": "12000",
"totalWithdrawn": "2000",
"activeStreams": 4,
"verifiedNgoCount": 3
}Auth: Public
Path params: ngoId (required): NGO UUID.
Returns impact totals for one NGO and its share of platform-wide committed
funds. Returns 400 {"error":"invalid_request"} for a malformed UUID and
404 {"error":"not_found"} if no NGO exists.
{
"ngoId": "<UUID>",
"name": "Example Aid",
"totalCommitted": "5000",
"totalWithdrawn": "1200",
"activeStreams": 2,
"cancelledStreams": 1,
"uniqueDonors": 3,
"platformSharePercent": 41.67
}Auth: Public
JSON body:
| Name | Type | Required | Description |
|---|---|---|---|
ownerAddress |
Stellar public key | Yes | Applicant's wallet address. |
name |
string, 1–200 characters | Yes | Organization name. |
description |
string, 1–5000 characters | Yes | Organization description. |
contactEmail |
email string | Yes | Contact email. |
website |
URL string | No | Website; a missing scheme is normalized to https://. |
country |
string, up to 100 characters | No | Country. |
Creates a pending application and returns 201 with the application record.
Returns 400 {"error":"invalid_request"} for an invalid body,
409 {"error":"already_approved"} if this address already has an approved
application, or 409 {"error":"application_already_pending"} if one is
pending.
{
"id": "<UUID>",
"ownerAddress": "<STELLAR_PUBLIC_KEY>",
"name": "Example Aid",
"description": "Supporting local communities.",
"website": "https://example.org",
"contactEmail": "contact@example.org",
"country": "Example",
"status": "PENDING",
"reviewNote": null,
"createdAt": "<ISO-8601>",
"updatedAt": "<ISO-8601>"
}Auth: Public
Query params: ownerAddress (required): applicant's Stellar public key.
Returns only the most recent application's status and timestamps; it does not
expose application contact details or description. Returns
400 {"error":"invalid_request"} for an invalid address and
404 {"error":"not_found"} if there is no application.
{
"status": "PENDING",
"createdAt": "<ISO-8601>",
"updatedAt": "<ISO-8601>"
}Auth: Admin signature
Params: None.
Returns counts grouped by application status.
{
"counts": { "PENDING": 2, "APPROVED": 4, "REJECTED": 1 },
"total": 7
}Auth: Admin signature
Query params: status (PENDING, APPROVED, or REJECTED, optional),
limit (integer, 1–100, default 100), and offset (integer, minimum 0,
default 0).
Returns application records and the total count matching the optional status.
{
"applications": [
{
"id": "<UUID>",
"ownerAddress": "<STELLAR_PUBLIC_KEY>",
"name": "Example Aid",
"description": "Supporting local communities.",
"website": "https://example.org",
"contactEmail": "contact@example.org",
"country": "Example",
"status": "PENDING",
"reviewNote": null,
"createdAt": "<ISO-8601>",
"updatedAt": "<ISO-8601>"
}
],
"total": 1,
"limit": 100,
"offset": 0
}Auth: Admin signature
Path params: id (required): application UUID.
Returns one application record. Returns 400 {"error":"invalid_request"}
for an invalid ID and 404 {"error":"not_found"} if none exists. Example
response: the application object shown in the POST /v1/ngo-applications
example, with its current status and review note.
Auth: Admin signature
Path params: id (required): application UUID.
JSON body: reviewNote (optional string, up to 2000 characters); an empty
JSON object is also valid.
Approves a pending application and returns the updated application record.
Returns 400 {"error":"invalid_request"} for invalid input,
404 {"error":"not_found"} if no application exists, or
409 {"error":"already_reviewed"} if it is no longer pending. Example
response: the application object shown in the POST /v1/ngo-applications
example, with status set to APPROVED and reviewNote set if supplied.
Auth: Admin signature
Path params: id (required): application UUID.
JSON body: reviewNote (optional string, up to 2000 characters); an empty
JSON object is also valid.
Rejects a pending application and returns the updated application record.
Returns 400 {"error":"invalid_request"} for invalid input,
404 {"error":"not_found"} if no application exists, or
409 {"error":"already_reviewed"} if it is no longer pending. Example
response: the application object shown in the POST /v1/ngo-applications
example, with status set to REJECTED and reviewNote set if supplied.
Auth: Public
Params: None.
Returns contract configuration and the latest indexer checkpoint. Ledger
values are null when no contracts are configured or no checkpoint is
available.
{
"configured": true,
"checkpointLedger": 123450,
"updatedAt": "<ISO-8601>",
"latestLedger": 123455,
"ledgerLag": 5
}In non-production environments, Swagger UI is available at /docs and the
OpenAPI JSON document at /docs/json.