Webhooks

Webhooks let APULODI notify your servers when things happen — a file is uploaded, replaced, copied, deleted, or an upload session completes. APULODI POSTs the event to an endpoint you register; the request carries an APULODI-Signature header so you can verify it really came from us.

Events

EventFires when
file.createda file record is created (upload initiated)
file.uploadedupload completes and bytes are verified
file.downloadeda download URL is generated
file.replaceda replacement publishes a new version
file.copieda file is copied
file.renameda file is renamed
file.moveda file is moved to another folder
file.metadata_updatedmetadata is replaced
file.processedan image variant finishes processing successfully
file.processing_failedan image variant fails to process
file.deleteda file is soft-deleted
file.restoreda soft-deleted file is restored
file.purgedthe purge sweep removes an expired deleted file's object
upload.initiateda multipart upload session is created
upload.completeda multipart upload completes
upload.aborteda multipart upload is aborted

Registering an endpoint with no events list subscribes it to all events.

Delivery

For every event, APULODI creates a delivery for each matching subscription and attempts it immediately, retrying with exponential backoff (APULODI_WEBHOOK_RETRY_DELAYS_MS, default 1s,5s,30s,2m). After the last attempt the delivery is marked FAILED and can be redelivered manually.

Each request is:

http
POST <your-endpoint>
Content-Type: application/json
User-Agent: APULODI-Webhooks/1.0
APULODI-Signature: t=<unix-seconds>,v1=<hex-hmac-sha256>
json
{
  "id": "evt_…",
  "type": "file.uploaded",
  "created_at": "2026-09-05T11:22:50.667Z",
  "data": {
    "projectId": "…",
    "organizationId": "…",
    "fileId": "file_…",
    "size": 12345
  }
}

APULODI expects a 2xx response within 10 seconds. Any other status or a timeout counts as a failed attempt.

Verify the signature

Your endpoint should verify the APULODI-Signature header (HMAC-SHA256 of <timestamp>.<body> using your signing secret) and reject requests older than ~5 minutes. The SDK provides a helper that does this for you — see the SDK webhooks guide.

Register an endpoint

http
POST /v1/webhooks
Authorization: Bearer $APULODI_API_KEY
Content-Type: application/json
bash
curl -X POST https://api.apulodi.com/v1/webhooks \
  -H "Authorization: Bearer $APULODI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/apulodi",
    "events": ["file.uploaded", "file.deleted"]
  }'
json
{
  "data": {
    "webhook": {
      "id": "wh_…",
      "url": "https://example.com/hooks/apulodi",
      "events": ["file.uploaded", "file.deleted"],
      "status": "ACTIVE",
      "createdAt": "2026-09-05T11:22:50.667Z"
    },
    "secret": "whsec_…"
  }
}

The secret is returned exactly once. It is an HMAC signing key shared between APULODI and your endpoint — store it in your server-side secrets, and never in client-side code.

Manage endpoints

http
GET    /v1/webhooks                // list (secrets never included)
GET    /v1/webhooks/:id            // a single endpoint
DELETE /v1/webhooks/:id            // unregister
bash
curl https://api.apulodi.com/v1/webhooks \
  -H "Authorization: Bearer $APULODI_API_KEY"

Inspect deliveries

To debug a missed webhook, list recent deliveries for an endpoint:

http
GET /v1/webhooks/:id/deliveries
bash
curl "https://api.apulodi.com/v1/webhooks/wh_…/deliveries?limit=25" \
  -H "Authorization: Bearer $APULODI_API_KEY"
json
{
  "data": [
    {
      "id": "dl_…",
      "eventId": "evt_…",
      "status": "FAILED",
      "attempts": 4,
      "responseStatus": 500,
      "lastError": "endpoint returned HTTP 500",
      "deliveredAt": null,
      "createdAt": "2026-09-05T11:22:50.667Z",
      "event": { "type": "file.uploaded", "createdAt": "2026-09-05T11:22:50.667Z" }
    }
  ]
}

Re-queue a failed (or pending) delivery immediately:

http
POST /v1/webhooks/:id/deliveries/:deliveryId/redeliver

Errors

StatusCodeWhy
404WEBHOOK_NOT_FOUNDNo endpoint with that id in your project
404DELIVERY_NOT_FOUNDNo delivery with that id for the endpoint
403WEBHOOK_LIMIT_REACHEDA project is capped at 20 endpoints
400VALIDATION_ERRORInvalid URL or unknown event type