API Reference

Complete reference for the Nexus Broker REST API. All endpoints accept and return JSON. The base URL is https://nexus-broker.dev.

Authentication

The API uses two authentication methods depending on the endpoint:

Firebase ID Token

Used for user-scoped management operations (creating API keys, viewing stats). Pass the token in the Authorization header:

Authorization: Bearer <firebase-id-token>

Obtain the ID token from the Firebase Auth client SDK after sign-in. Tokens expire after one hour and must be refreshed.

API Key

Used for webhook management and queue operations. Pass the API key in the x-api-key header:

x-api-key: nxb_your_api_key

API keys are prefixed with nxb_. They are stored hashed (SHA-256) on the server. The full key is only visible at creation time.

API Keys

Create API Key

POST /api/keys — Generate a new API key. Requires Firebase authentication.

Request Body

FieldTypeRequiredDescription
namestringYesHuman-readable name (max 64 chars)
curl -X POST https://nexus-broker.dev/api/keys \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"name": "production"}'

Response (201)

{
  "id": "key_2kf9x7",
  "name": "production",
  "key": "nxb_Kj3m9xRq7wYpNhBvT5cF...Dg2e",
  "createdAt": "2025-01-15T10:30:00Z"
}

List API Keys

GET /api/keys — List all API keys for the authenticated user. Requires Firebase authentication. Returns keys with last 4 characters of the key for identification.

curl https://nexus-broker.dev/api/keys \
  -H "Authorization: Bearer <token>"
{
  "keys": [
    {
      "id": "key_2kf9x7",
      "name": "production",
      "prefix": "nxb_...Dg2e",
      "createdAt": "2025-01-15T10:30:00Z",
      "lastUsedAt": "2025-01-20T14:22:00Z"
    }
  ]
}

Delete API Key

DELETE /api/keys/{id} — Permanently delete an API key. Requires Firebase authentication.

curl -X DELETE https://nexus-broker.dev/api/keys/key_2kf9x7 \
  -H "Authorization: Bearer <token>"

Response (204 No Content)

Rotate API Key

POST /api/keys/{id}/rotate — Generate a new key value for an existing key. The old key is immediately invalidated. Requires Firebase authentication.

curl -X POST https://nexus-broker.dev/api/keys/key_2kf9x7/rotate \
  -H "Authorization: Bearer <token>"
{
  "id": "key_2kf9x7",
  "name": "production",
  "key": "nxb_Mw8pRt4xBnKq...Yj6c",
  "createdAt": "2025-01-15T10:30:00Z",
  "rotatedAt": "2025-02-01T09:00:00Z"
}

Webhooks

Create Webhook

POST /api/webhooks — Create a new webhook endpoint. Requires API key authentication.

Request Body

FieldTypeRequiredDescription
namestringYesHuman-readable name (max 128 chars)
publicKeystringYesPEM-encoded public key (RSA-2048 or X25519)
algorithmstringNo"RSA-2048" (default) or "X25519"
lockTimeoutnumberNoLock timeout in seconds (default: 300)
maxRetriesnumberNoMax retry attempts (default: per plan)
ttlnumberNoMessage TTL in seconds (default: per plan)
curl -X POST https://nexus-broker.dev/api/webhooks \
  -H "x-api-key: nxb_Kj3m9x...Rq7w" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "stripe-webhooks",
    "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBg...",
    "algorithm": "RSA-2048",
    "lockTimeout": 600,
    "maxRetries": 5
  }'
{
  "id": "wh_a1b2c3",
  "name": "stripe-webhooks",
  "slug": "f8k2m9x4p7",
  "url": "https://nexus-broker.dev/wh/f8k2m9x4p7",
  "algorithm": "RSA-2048",
  "lockTimeout": 600,
  "maxRetries": 5,
  "createdAt": "2025-01-15T11:00:00Z"
}

List Webhooks

GET /api/webhooks — List all webhooks for the authenticated user. Requires API key authentication.

curl https://nexus-broker.dev/api/webhooks \
  -H "x-api-key: nxb_Kj3m9x...Rq7w"
{
  "webhooks": [
    {
      "id": "wh_a1b2c3",
      "name": "stripe-webhooks",
      "slug": "f8k2m9x4p7",
      "url": "https://nexus-broker.dev/wh/f8k2m9x4p7",
      "algorithm": "RSA-2048",
      "messageCount": 142,
      "queueDepth": 3,
      "deadLetterCount": 1,
      "createdAt": "2025-01-15T11:00:00Z"
    }
  ]
}

Get Webhook

GET /api/webhooks/{id} — Get details for a specific webhook. Requires API key authentication.

curl https://nexus-broker.dev/api/webhooks/wh_a1b2c3 \
  -H "x-api-key: nxb_Kj3m9x...Rq7w"

Update Webhook

PATCH /api/webhooks/{id} — Update webhook configuration. Only included fields are updated. Requires API key authentication.

Request Body

FieldTypeDescription
namestringNew name
publicKeystringNew PEM public key (triggers key rotation)
lockTimeoutnumberNew lock timeout in seconds
maxRetriesnumberNew max retry count
curl -X PATCH https://nexus-broker.dev/api/webhooks/wh_a1b2c3 \
  -H "x-api-key: nxb_Kj3m9x...Rq7w" \
  -H "Content-Type: application/json" \
  -d '{"name": "stripe-webhooks-v2", "lockTimeout": 600}'

Delete Webhook

DELETE /api/webhooks/{id} — Permanently delete a webhook and all its queued messages. This action is irreversible. Requires API key authentication.

curl -X DELETE https://nexus-broker.dev/api/webhooks/wh_a1b2c3 \
  -H "x-api-key: nxb_Kj3m9x...Rq7w"

Response (204 No Content)

Ingestion

Send Webhook

POST /wh/{slug} — Public ingestion endpoint. No authentication required. Accepts any valid JSON body. The payload is encrypted and queued.

curl -X POST https://nexus-broker.dev/wh/f8k2m9x4p7 \
  -H "Content-Type: application/json" \
  -d '{
    "event": "payment.completed",
    "data": {
      "id": "evt_123",
      "amount": 4999
    }
  }'
{
  "id": "msg_x9y8z7",
  "sequence": 42,
  "status": "queued",
  "createdAt": "2025-01-15T12:00:00Z"
}

Status Codes

CodeMeaning
202Accepted and queued
400Invalid JSON or missing content-type
404Webhook slug not found
413Payload exceeds plan size limit
429Rate limit exceeded
507Queue depth limit reached

Queue Operations

Dequeue Message

POST /api/webhooks/{id}/dequeue — Fetch and lock the next available message in FIFO order. The message is locked until the lock timeout expires or you commit/error it. Requires API key authentication.

curl -X POST https://nexus-broker.dev/api/webhooks/wh_a1b2c3/dequeue \
  -H "x-api-key: nxb_Kj3m9x...Rq7w"
{
  "message": {
    "id": "msg_x9y8z7",
    "sequence": 42,
    "status": "locked",
    "lockExpiresAt": "2025-01-15T12:05:00Z",
    "createdAt": "2025-01-15T12:00:00Z"
  },
  "encrypted": {
    "ciphertext": "Base64...",
    "iv": "Base64...",
    "tag": "Base64...",
    "encryptedKey": "Base64...",
    "algorithm": "RSA-2048-AES-256-GCM"
  },
  "headers": {
    "content-type": "application/json"
  }
}

Status Codes

CodeMeaning
200Message dequeued and locked
204No messages available
401Invalid or missing API key
404Webhook not found

Commit Message

POST /api/webhooks/{id}/messages/{msgId}/commit — Acknowledge successful processing. Removes the message from the active queue. Requires API key authentication.

curl -X POST https://nexus-broker.dev/api/webhooks/wh_a1b2c3/messages/msg_x9y8z7/commit \
  -H "x-api-key: nxb_Kj3m9x...Rq7w"

Response (204 No Content)

Error Message

POST /api/webhooks/{id}/messages/{msgId}/error — Report a processing failure. The message is released for retry. If the retry count exceeds the maximum, the message moves to the dead letter queue. Requires API key authentication.

Request Body

FieldTypeRequiredDescription
reasonstringNoDescription of the failure (max 1024 chars)
curl -X POST https://nexus-broker.dev/api/webhooks/wh_a1b2c3/messages/msg_x9y8z7/error \
  -H "x-api-key: nxb_Kj3m9x...Rq7w" \
  -H "Content-Type: application/json" \
  -d '{"reason": "Database connection timeout"}'
{
  "id": "msg_x9y8z7",
  "status": "queued",
  "retryCount": 2,
  "maxRetries": 10
}

Messages

List Messages

GET /api/webhooks/{id}/messages — List messages for a webhook with optional filtering. Returns message metadata (not encrypted payloads). Requires API key authentication.

ParamTypeDescription
statusstringFilter by status: queued, locked, committed, error, dead
limitnumberMax results (default: 50, max: 200)
cursorstringPagination cursor from previous response
curl "https://nexus-broker.dev/api/webhooks/wh_a1b2c3/messages?status=queued&limit=20" \
  -H "x-api-key: nxb_Kj3m9x...Rq7w"
{
  "messages": [
    {
      "id": "msg_x9y8z7",
      "sequence": 42,
      "status": "queued",
      "retryCount": 0,
      "createdAt": "2025-01-15T12:00:00Z"
    }
  ],
  "nextCursor": "eyJzZXF1ZW5jZSI6NDJ9"
}

Dead Letters

List Dead Letters

GET /api/webhooks/{id}/errors — List messages in the dead letter queue. Supports the same query parameters as the messages endpoint. Requires API key authentication.

curl https://nexus-broker.dev/api/webhooks/wh_a1b2c3/errors \
  -H "x-api-key: nxb_Kj3m9x...Rq7w"
{
  "messages": [
    {
      "id": "msg_p3q4r5",
      "sequence": 38,
      "status": "dead",
      "retryCount": 10,
      "maxRetries": 10,
      "lastError": "Connection refused",
      "createdAt": "2025-01-14T08:00:00Z",
      "diedAt": "2025-01-14T09:30:00Z"
    }
  ]
}

Retry Dead Letter

POST /api/webhooks/{id}/errors/{msgId}/retry — Move a dead letter message back to the queue for reprocessing. Resets the retry counter. Requires API key authentication.

curl -X POST https://nexus-broker.dev/api/webhooks/wh_a1b2c3/errors/msg_p3q4r5/retry \
  -H "x-api-key: nxb_Kj3m9x...Rq7w"
{
  "id": "msg_p3q4r5",
  "status": "queued",
  "retryCount": 0,
  "message": "Message requeued for processing"
}

Discard Dead Letter

DELETE /api/webhooks/{id}/errors/{msgId} — Permanently delete a dead letter message. This action is irreversible. Requires API key authentication.

curl -X DELETE https://nexus-broker.dev/api/webhooks/wh_a1b2c3/errors/msg_p3q4r5 \
  -H "x-api-key: nxb_Kj3m9x...Rq7w"

Response (204 No Content)

Error Responses

All errors follow a consistent JSON format:

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Retry after 60 seconds.",
    "details": {
      "retryAfter": 60,
      "limit": 100,
      "window": "60s"
    }
  }
}
HTTP StatusCodeDescription
400VALIDATION_ERRORRequest body failed validation
401UNAUTHORIZEDMissing or invalid authentication
403FORBIDDENAuthenticated but not authorized for this resource
404NOT_FOUNDResource does not exist
409CONFLICTMessage is not in the expected state
413PAYLOAD_TOO_LARGEPayload exceeds plan size limit
429RATE_LIMIT_EXCEEDEDToo many requests
500INTERNAL_ERRORUnexpected server error
507QUEUE_FULLQueue depth limit reached