CoordinatorAPI Endpoints

API Endpoints

Coordinator REST API reference.

Base URL

Replace {COORDINATOR_URL} with your coordinator service URL.

Local Development:

http://localhost:3001/api

Production:

https://your-coordinator-domain.com/api

Register 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:

  • schedulePda must match vaultEmployer + 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-wallet
  • x-veil-timestamp
  • x-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.../payload

Get 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 to 1-25. Defaults to 10.

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 - Success
  • 400 - Invalid request payload
  • 403 - Forbidden
  • 404 - Not found
  • 429 - Rate limited
  • 500 - Internal server error
  • 503 - Dependency unavailable / unhealthy service state