Skip to content

API overview and authentication

The Delay API lets your code schedule jobs and create crons. It has two endpoints, takes JSON, returns JSON, and authenticates with one bearer token.

Base URL and endpoints

https://app.delay.run/api
EndpointWhat it doesReference
POST /api/jobsSend a request once, now or after a delay of up to 24 hoursSchedule a job
POST /api/cronsCreate a cron that sends a request on a scheduleCreate a cron

That’s the whole API. It can’t:

  • list, read, update, pause or delete jobs and crons;
  • create or configure queues (POST /api/jobs creates a queue with default settings when it sees a new queue name; change its settings in the dashboard, see queues);
  • set success assertions;
  • return run results (set a callback_url to get them pushed to you, see callbacks);
  • manage dead letters, alerts or teams.

Use the dashboard for those.

Get your API token

  1. In the dashboard, open Settings > API token. It’s also in the account menu as API token.
  2. Click the eye icon (Show token) to see it, or the copy icon (Copy token).
  3. Store it as an environment variable or in your secret store, for example export DELAY_TOKEN="...".
  • The token is created for you the first time you open this page (or the Jobs or Cron jobs tab). It’s 64 characters long.
  • It doesn’t expire and has no scopes. Each user has exactly one.
  • You can show and copy it again at any time.
  • To replace it, click Regenerate token, then Regenerate in the dialog. The old token stops working immediately, so update everything that uses it.

Which team the token acts on

Your token belongs to you, not to a team. Each call creates its job or cron in the team you have selected in the dashboard at the moment of the call. If you switch teams in the browser, your scripts’ next calls go to the new team. For separate staging and production setups, see teams for environments.

Send a request

Every request needs three headers:

HeaderValueWhy
AuthorizationBearer $DELAY_TOKENIdentifies you. There’s no other way to authenticate.
Content-Typeapplication/jsonWithout it, the body isn’t read as JSON and every field looks missing.
Acceptapplication/jsonWithout it, a validation error comes back as a 302 redirect instead of a 422 with details.

There are no official SDKs. Any HTTP client works:

Terminal window
curl -X POST https://app.delay.run/api/jobs \
-H "Authorization: Bearer $DELAY_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"queue": "emails", "url": "https://api.yourapp.com/send-welcome", "payload": {"user_id": 42}}'

A 201 means the job is scheduled. The response body and every field are on Schedule a job.

Errors

StatusWhenBody
401No Authorization: Bearer header{"error": "Missing authorization token"}
401The token doesn’t match, for example after it was regenerated{"error": "Invalid webhook token"} (“webhook token” is an old name for the API token)
422A field is missing or invalid, and you sent Accept: application/jsonmessage and errors (below)
302The same validation error without Accept: application/jsonA redirect page with no details
429Rate limit reached{"message": "Too Many Attempts."} with Accept: application/json, otherwise an HTML page
500Your account has no team selected, for example because the selected team was deleted. Pick a team in the dashboard’s team switcher.A server error

401 responses are always JSON. A 422 looks like this:

{
"message": "A queue name is required. (and 1 more error)",
"errors": {
"queue": ["A queue name is required."],
"url": ["The target URL must be a valid URL."]
}
}

message is the first error plus a count of the others, and errors lists the messages for each field.

Validation runs before the token check. A request with a bad body gets a 422 (or 302) even when the token is missing or wrong. Fix the body first; once it’s valid, a bad token shows up as 401.

The API accepts jobs and crons even when your team has used up its monthly requests. They fail when they run, see how usage is counted.

Rate limit

You can send 60 requests per minute from one IP address. POST /api/jobs and POST /api/crons share that budget, and so does everything else that calls the API from the same IP address. It isn’t per token or per team. Every request counts, including ones rejected with 401 or 422.

Each response has X-RateLimit-Limit and X-RateLimit-Remaining headers. A 429 also has Retry-After, the number of seconds to wait. To create many jobs, send them one after another, watch X-RateLimit-Remaining, and after a 429 wait Retry-After seconds before you continue.

This limit is about API calls. Your plan’s monthly quota counts runs, not API calls.

Keep your token safe

  • Keep it in environment variables or a secret store, never in client-side code or a repository.
  • Anyone with your token can create jobs and crons in whichever team you have selected.
  • If it leaks, regenerate it.

Next steps