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.