API Endpoints
Coordinator REST API reference.
Base URL
Replace {COORDINATOR_URL} with your coordinator service URL.
Local Development:
http://localhost:3001/apiProduction:
https://your-coordinator-domain.com/apiRegister Schedule
Register a schedule with recipient data for execution.
Endpoint: POST /api/schedules
This endpoint also updates an existing coordinator payload for the same
schedulePda. After editing a schedule on-chain, call this endpoint again with
the updated recipient list so the coordinator stores the new Merkle payload.
Request:
{
"schedulePda": "schedule_pubkey_here",
"scheduleId": [1, 2, 3, "..."],
"vaultEmployer": "employer_pubkey_here",
"tokenMint": "mint_pubkey_here",
"recipients": [
{ "address": "recipient1_pubkey", "amount": "100000" },
{ "address": "recipient2_pubkey", "amount": "200000" }
]
}Success response:
{
"success": true,
"schedulePda": "schedule_pubkey_here",
"merkleRoot": [1, 2, 3, "..."],
"alreadyRegistered": false
}If the exact same payload is submitted again for an already-registered schedule, the coordinator returns a successful response with alreadyRegistered: true instead of recomputing the registration.
Validation performed by the coordinator:
schedulePdamust matchvaultEmployer + tokenMint + scheduleId- the on-chain vault and schedule must exist
- the on-chain vault employer and mint must match the payload
- the recipient count must match the on-chain schedule
- the sum of recipient amounts must equal the on-chain
perExecutionAmount - the computed Merkle root must match the on-chain schedule
Operational limits:
- oversized recipient payloads are rejected before Merkle generation
- the current registration path rejects payloads above 1000 recipients
- this endpoint is rate-limited and may return
429
Example:
curl -X POST {COORDINATOR_URL}/api/schedules \
-H "Content-Type: application/json" \
-d '{
"schedulePda": "...",
"scheduleId": [1, 2, 3, "..."],
"vaultEmployer": "...",
"tokenMint": "...",
"recipients": [
{ "address": "...", "amount": "100000" }
]
}'Get Schedule Summary
Fetch the coordinator-side summary for a registered schedule.
Endpoint: GET /api/schedules/:schedulePda
Response:
{
"schedulePda": "...",
"scheduleId": [1, 2, 3, "..."],
"vaultEmployer": "...",
"recipientCount": 2,
"merkleRoot": [1, 2, 3, "..."],
"createdAt": 1777500000000
}This endpoint intentionally returns summary data only. Recipient addresses, per-recipient amounts, and Merkle proofs are not returned here.
Example:
curl {COORDINATOR_URL}/api/schedules/SchedulePDA...Get Schedule Payload
Get the stored recipient payload for a schedule. The dashboard uses this when editing a paused schedule.
Endpoint: GET /api/schedules/:schedulePda/payload
This endpoint requires a wallet-signed request from the schedule owner. Send:
x-veil-walletx-veil-timestampx-veil-signature
Response:
{
"schedulePda": "...",
"scheduleId": [1, 2, 3, "..."],
"vaultEmployer": "...",
"tokenMint": "...",
"recipients": [
{ "address": "...", "amount": "100000" }
],
"merkleRoot": [1, 2, 3, "..."],
"createdAt": 1777500000000
}Example:
curl {COORDINATOR_URL}/api/schedules/SchedulePDA.../payloadGet Execution History
Fetch recent execution runs and attempts for a registered schedule.
Endpoint: GET /api/schedules/:schedulePda/executions?limit=10
Response:
{
"schedulePda": "...",
"runs": [
{
"id": 12,
"schedulePda": "...",
"scheduledFor": 1777520400,
"status": "succeeded",
"attemptCount": 1,
"maxAttempts": 5,
"nextAttemptAt": 1777520400,
"startedAt": 1777520405,
"finishedAt": 1777520412,
"claimedCount": 2,
"alreadyPaidCount": 0,
"failedClaimCount": 0,
"delegateSignature": "...",
"commitSignature": "...",
"attempts": [
{
"id": 44,
"runId": 12,
"attemptNumber": 1,
"stage": "delegate",
"status": "succeeded",
"txSignature": "...",
"details": null,
"startedAt": 1777520405,
"finishedAt": 1777520406
}
]
}
]
}Query parameters:
limit- Optional. Clamped to1-25. Defaults to10.
Health Check
Check coordinator health.
Endpoint: GET /api/health
Response:
{
"status": "healthy",
"database": "connected",
"timestamp": 1777500000000,
"schedulesRegistered": 4
}If the database is unavailable, this endpoint returns an unhealthy payload with 503.
Metrics
Expose Prometheus metrics for the coordinator.
Endpoint: GET /api/metrics
By default this endpoint is protected. If METRICS_PUBLIC=false, callers must send:
Authorization: Bearer <METRICS_AUTH_TOKEN>Example:
curl {COORDINATOR_URL}/api/metrics \
-H "Authorization: Bearer <METRICS_AUTH_TOKEN>"Error Responses
All JSON endpoints return errors in this format:
{
"error": "Error message"
}Status Codes:
200- Success400- Invalid request payload403- Forbidden404- Not found429- Rate limited500- Internal server error503- Dependency unavailable / unhealthy service state