Guides

Schedules and webhooks

Schedule one-time or recurring events and verify signed delivery.

Schedules fire durable events and deliver their payloads to organization-owned webhook endpoints. Current schedules have one action type: webhook delivery.

Create a webhook endpoint

An org-admin registers an HTTPS URL:

curl -H "Authorization: Bearer $ORG_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -X POST "$BASE_URL/v1/webhook-endpoints" -d '{
  "name":"Application events",
  "url":"https://app.example.com/webhooks/deeplinq"
}'

Copy the returned signing secret immediately. Later list responses expose only a masked hint.

Endpoint URLs are SSRF-guarded and HTTPS-only outside explicit hermetic development mode.

Verify delivery signatures

Deeplinq sends the signature in X-Signature:

t=<unix-seconds>,v1=<hex-hmac>

Compute:

HMAC-SHA256(endpoint_secret, timestamp + "." + exact_request_body_bytes)

Compare the decoded MAC in constant time and reject timestamps outside a short replay window. Verify against the exact bytes received before parsing JSON; re-serializing the payload changes the signature.

Create a one-time schedule

curl -H "Authorization: Bearer $DEEPLINQ_API_KEY" \
  -H "X-End-User-Id: user-42" \
  -H "Content-Type: application/json" \
  -X POST "$BASE_URL/v1/schedules" -d '{
  "kind":"once",
  "fire_at":"2026-08-01T09:00:00Z",
  "endpoint_id":"<endpoint-id>",
  "payload":{"type":"follow_up","case_id":"case-1842"}
}'

Create a recurring schedule

curl -H "Authorization: Bearer $DEEPLINQ_API_KEY" \
  -H "X-End-User-Id: user-42" \
  -H "Content-Type: application/json" \
  -X POST "$BASE_URL/v1/schedules" -d '{
  "kind":"cron",
  "cron":"0 9 * * 1",
  "timezone":"Europe/Lisbon",
  "runs_left":12,
  "endpoint_id":"<endpoint-id>",
  "payload":{"type":"weekly_review"}
}'

Cron expressions use plain five-field POSIX syntax. Use until_at or runs_left to bound recurring work.

Schedule an agent run

Set agent_id on a schedule the caller can see. When due, a PostgreSQL-backed deployment creates a durable run for that agent and owner instead of enqueueing webhook delivery:

{
  "kind": "cron",
  "cron": "0 8 * * 1-5",
  "timezone": "Europe/Lisbon",
  "agent_id": "<agent-id>",
  "endpoint_id": "<endpoint-id>",
  "payload": {"task": "Prepare the morning mailbox summary"}
}

endpoint_id remains required by the current schedule schema even though an agent-bound fire creates a run rather than a webhook event. If the agent is unavailable when the schedule fires, Deeplinq pauses the schedule with an explicit status reason.

Manage lifecycle

GET    /v1/schedules?status=active&limit=50&cursor=<opaque>
GET    /v1/schedules/{id}
PATCH  /v1/schedules/{id}
POST   /v1/schedules/{id}/pause
POST   /v1/schedules/{id}/resume
DELETE /v1/schedules/{id}

Resuming a cron schedule computes the next future occurrence from the current time. It does not replay every missed interval.

Poll authoritative events

GET /v1/schedule-events?schedule_id={id}&limit=50&cursor=<opaque>

Event rows record:

  • fire and delivery status;
  • scheduled and actual fire times;
  • attempt count and last attempt;
  • response code or bounded error;
  • the original payload.

Webhook failure never rolls back a committed schedule event. Delivery retries through the durable state machine.

Rotate the signing secret

curl -H "Authorization: Bearer $ORG_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -X PATCH "$BASE_URL/v1/webhook-endpoints/$ENDPOINT_ID" \
  -d '{"rotate_secret":true}'

The replacement secret is shown once. Update the receiver before retiring the old verification path according to your deployment's overlap procedure.

An endpoint cannot be deleted while a non-completed schedule references it. Deactivate it first when you need to stop delivery without removing schedule history.

On this page