Skip to content

Endpoint profiles

An endpoint profile is a named, reusable destination plus its delivery policy. Instead of repeating the same URL, headers, and retry settings on every schedule, you define them once as a profile (ep_…) and reference it by endpoint_id. Edit the profile and future deliveries pick up the change automatically — without rewriting any schedule.

Use a profile when more than one schedule targets the same destination, or when you want a single place to rotate auth headers and tune retry/breaker behavior.

Terminal window
# Create a profile once...
curl -sS https://api.schedstack.com/v1/endpoints \
-H "Authorization: Bearer sk_test_…" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/billing",
"method": "POST",
"headers": { "X-Api-Key": "whk_abc123" }
}'
{
"id": "ep_3Qa1bC2dEf",
"object": "endpoint",
"mode": "test",
"url": "https://example.com/hooks/billing",
"method": "POST",
"timeout": null,
"header_keys": ["X-Api-Key"],
"metadata": {},
"version": 1,
"archived": false,
"created_at": "2026-06-27T12:00:00Z",
"updated_at": "2026-06-27T12:00:00Z"
}

POST /v1/endpoints. Only url is required, and it must be an https URL.

Field Required Notes
url yes https only. A non-https URL returns 422 url_blocked; an absent one returns 422 missing_url. The URL is not pre-trusted — the resolved IP is re-validated at connect time on every delivery.
method no Defaults to POST. An unsupported method returns 400 invalid_method.
headers no Static auth/custom headers (object of string→string).
retry_policy no Same shape and bounds as a schedule’s retry policy (max_attempts + backoff).
retry_budget no { "rate": <number>, "burst": <number> }. Caps retry amplification against this destination. Both values must be ≥ 0.
breaker_policy no Circuit-breaker tuning. See Breaker policy — all four fields are required together.
timeout no Per-request HTTP timeout (duration string up to 1h). Stored but not yet enforced — see below.
rate_limit no { "per_second": <number> }, ≥ 0. Stored but not yet enforced — see below.
metadata no Free-form string→string map for your own bookkeeping.

When you set breaker_policy, all four fields are required — an omitted (zero) open or probe window produces a breaker that re-opens immediately, i.e. no protection, so the API rejects a partial policy with 422 invalid_breaker_policy.

Field Notes
threshold Consecutive failures before the circuit opens. Integer, 1–1000.
base_open Initial open duration. Positive duration string, up to 24h.
max_open Cap on the (backing-off) open duration. Up to 24h.
probe_timeout How long a half-open probe may run before it counts as a failure. Up to 24h.
Terminal window
curl -sS https://api.schedstack.com/v1/endpoints \
-H "Authorization: Bearer sk_test_…" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/billing",
"method": "POST",
"headers": { "X-Api-Key": "whk_abc123" },
"retry_policy": { "max_attempts": 6 },
"retry_budget": { "rate": 10, "burst": 100 },
"breaker_policy": {
"threshold": 20,
"base_open": "30s",
"max_open": "10m",
"probe_timeout": "5s"
},
"metadata": { "team": "billing" }
}'

On POST /v1/schedules, pass endpoint_id instead of the inline endpoint. The two are mutually exclusive.

Terminal window
curl -sS https://api.schedstack.com/v1/schedules \
-H "Authorization: Bearer sk_test_…" \
-H "Content-Type: application/json" \
-d '{
"endpoint_id": "ep_3Qa1bC2dEf",
"delay": "1h",
"body": { "invoice": "inv_123" }
}'

The schedule inherits the profile’s URL, method, headers, and policies. You still set the per-schedule fields — timing (delay / fire_at / cron), body, ttl, idempotency_key, metadata — on the schedule itself.

A profile is a live link for future deliveries but a frozen snapshot within a delivery. This is what makes editing a profile safe.

  • Every mutating edit (PATCH) bumps the profile’s version.
  • When a delivery is materialized, SchedStack resolves the profile and snapshots the version it resolved onto that delivery. New occurrences re-resolve, so a profile edit (new header, rotated auth, tuned retry) automatically reaches future deliveries.
  • That snapshot is frozen for the life of the delivery, including every retry. A single logical delivery never switches destination mid-retry after a profile edit — its retries hit the same URL with the same resolved config it started with.

This keeps receiver dedup correct (a stable Idempotency-Key always lands on one destination) and keeps history auditable: you can ask which URL and profile version an attempt actually used, and the answer never changes.

PATCH /v1/endpoints/{id} updates any subset of fields and bumps version. Future deliveries resolve against the new version; in-flight deliveries keep their frozen snapshot.

Terminal window
curl -sS -X PATCH https://api.schedstack.com/v1/endpoints/ep_3Qa1bC2dEf \
-H "Authorization: Bearer sk_test_…" \
-H "Content-Type: application/json" \
-d '{ "headers": { "X-Api-Key": "whk_rotated456" } }'

The same validation as create applies (https-only URL, supported method, full breaker_policy if present, retry_budget / rate_limit ≥ 0).

  1. Fetch one:

    Terminal window
    curl -sS https://api.schedstack.com/v1/endpoints/ep_3Qa1bC2dEf \
    -H "Authorization: Bearer sk_test_…"
  2. List them (cursor-paginated). Archived profiles are excluded unless you ask for them:

    Terminal window
    curl -sS "https://api.schedstack.com/v1/endpoints?include_archived=true" \
    -H "Authorization: Bearer sk_test_…"

Profiles are scoped to (project, mode), like everything else: an sk_test_… key only sees test profiles, and a schedule can only reference a profile in its own mode. See Test vs live modes.

There is no hard delete — history rows reference profiles forever. Instead, soft-archive:

Terminal window
curl -sS -X POST https://api.schedstack.com/v1/endpoints/ep_3Qa1bC2dEf/archive \
-H "Authorization: Bearer sk_test_…"

An archived profile stays queryable for history and audit, but cannot back new schedules.

You never have to use a profile. A schedule can carry its endpoint inline (endpoint + headers + retry_policy + …) exactly as before — see One-shot deliveries. Reach for a profile when the same destination is used by more than one schedule, or when you want one place to rotate auth and tune delivery policy.