DIAL Scheduler API
This reference covers the Scheduler API for platform engineers verifying a configured service. It describes the HTTP API, schedule definition, run lifecycle, and MCP interface. All resource operations are scoped to the caller resolved through DIAL Core.
Paths and authentication
Container paths begin with /v1. Through the upstream application definition, the Core route prefix is:
<DIAL_URL>/v1/deployments/applications/public/dial_scheduler__1.0.0/route
Append /v1/schedules/ or another container path to that prefix. Public Core requests use DIAL authentication; Core forwards an Api-Key for the Scheduler's caller lookup. Direct container requests require Api-Key; the Scheduler resolves it through Core's /v1/user/info. A bearer token alone does not satisfy that direct header dependency.
Sources: caller authentication, router prefixes, and application route definition.
Operations
| Method | Container path | Input | Success response |
|---|---|---|---|
POST | /v1/schedules/ | Schedule definition | 201, full schedule |
GET | /v1/schedules/ | Pagination and optional filters | 200, paginated schedules |
GET | /v1/schedules/{schedule_id} | Path ID | 200, full schedule, including soft-deleted records |
PUT | /v1/schedules/{schedule_id} | Complete replacement definition | 200, full schedule |
POST | /v1/schedules/{schedule_id}/pause | No body | 200, paused schedule |
POST | /v1/schedules/{schedule_id}/resume | No body | 200, resumed schedule |
DELETE | /v1/schedules/{schedule_id} | Path ID | 204, empty body |
POST | /v1/schedules/{schedule_id}/run | No body or overrides | 202, newly created run |
GET | /v1/schedules/{schedule_id}/runs | Pagination and run ordering | 200, paginated run summaries |
GET | /v1/schedules/{schedule_id}/runs/{run_id} | Path IDs | 200, run detail and result |
GET | /v1/sign-in/status | Required service_id query parameter | 200, sign-in state |
The trailing slash on collection paths is significant: the API disables automatic slash redirects. Full schedule responses include id, display_name, service_id, description, next_run_time, trigger, properties, metadata, is_deleted, created_by, created_at, and updated_at.
Sources: schedule routes, run routes, and schedule response schema.
Schedule definition
POST and PUT accept the same body. PUT replaces all writable fields; it is not a partial update.
| Field | Required | Default | Description |
|---|---|---|---|
display_name | Yes | — | Non-empty name; whitespace-only values are rejected. |
service_id | Yes | — | Registered external service used to obtain the owner's credentials, normally dial-native. |
description | No | null | Notes, up to 1000 characters. |
trigger | Yes | — | Exactly one cron or date trigger. |
properties | Yes | — | Target configuration described below. |
metadata | No | {} | String-keyed tags; only string-valued entries support list filtering. |
The server supplies ownership and timestamps. is_deleted is read-only and ignored if supplied in a create or replace body. Definitions are validated by the request schemas.
Triggers
trigger.date is an ISO-8601 datetime for one execution. trigger.cron contains required fields and optional start_date and end_date bounds. Supplying both trigger types, or neither, returns 422.
Cron fields are year, month, day, week, day_of_week, hour, minute, and second. Each accepts a string cron expression, an integer, or null. Non-null fields are passed to APScheduler's CronTrigger; omitted values follow that library's cron semantics.
Triggers use UTC. An every-weekday-at-09:00 example is:
{
"cron": {
"fields": {
"day_of_week": "mon-fri",
"hour": 9,
"minute": 0,
"second": 0
}
}
}
Source: trigger construction.
Target properties
| Field | Default | Description |
|---|---|---|
target_type | — | Required: chat_completion, responses, rest, or sse. |
url | — | Required HTTP/HTTPS URL. Model targets use a base URL, such as http://dial-core:8080/openai/; HTTP targets use the endpoint URL. |
method | null | Required for rest and sse: GET, POST, or PUT. Must be absent or null for model targets. |
payload | {} | Target request body. Model targets require payload.model; their stream defaults to false. |
extra_headers | {} | Additional request headers. REST and SSE executors merge these with the owner's delegated authentication header. |
api_version | null | Required for model targets; must be absent or null for REST and SSE. |
timeout | Process default | Positive absolute duration ceiling per attempt, in seconds. |
idle_timeout | Process default | Positive maximum gap between parsed stream events, in seconds. Used for SSE and streamed model calls; must not exceed an explicitly supplied timeout. |
retry | null | Optional retry policy; no Scheduler policy retries when omitted. |
create_conversation | false | Save a successful run as a DIAL conversation. true is allowed only for chat_completion. |
For model targets, url is the API base and payload.model selects the deployment. It is not the full deployment-specific completion URL. Conversation creation is best effort; failure is logged without changing a successful target run to an error.
Sources: property validation, chat executor, and conversation persistence. The upstream configuration document omits idle_timeout; this table follows code.
Retries
When present, retry requires both fields:
| Field | Constraint | Meaning |
|---|---|---|
interval_sequence | Non-empty array of positive numbers | Seconds to wait before each successive retry; [5, 30] allows three total attempts. |
retryable_errors | Non-empty array of integers from 100 to 599 | HTTP status codes eligible for policy retries. |
Credential lookup happens before target execution. A credentials-stage failure never dispatches the target or consumes this retry policy. Duration expiry, idle expiry, and transport failures without an HTTP status are terminal for Scheduler's policy. See retry implementation.
Sign-in status
Create and replace require state=signed_in for the requested service_id before writing the schedule. The API reads Core's application details with the caller's key and examines the external service's auth_settings:
| State | Meaning | Create or replace |
|---|---|---|
signed_in | Application approval and user sign-in both report SIGNED_IN | Continues |
not_signed_in | Application approval exists, but user sign-in does not | 403 |
unknown | Application approval is missing, or status could not be determined | 502 |
The status response includes service_id, state, signed_in, and detail. signed_in is a derived boolean; inspect state to distinguish missing user sign-in from an unresolved state.
When X-DIAL-CLIENT-CHANNEL-ID is forwarded, a check that is not signed in can request an interactive sign-in through Core's client channel. It then rechecks status after a successful interaction. The check does not modify schedules, but it can initiate that user interaction.
The upstream README and API contract describe an OBO-probe check and a read-only status endpoint. The implemented sign-in service instead uses application auth status and supports the client-channel interaction.
Verification request
Through Core, with the upstream application path:
curl --fail-with-body \
-H 'Api-Key: <YOUR_DIAL_API_KEY>' \
'https://<YOUR_DIAL_HOST>/v1/deployments/applications/public/dial_scheduler__1.0.0/route/v1/sign-in/status?service_id=dial-native'
An example response after approval and user sign-in is:
{
"service_id": "dial-native",
"state": "signed_in",
"detail": "Signed in to dial-native.",
"signed_in": true
}
Create and verify a schedule
The following request uses an existing deployment ID and a URL reachable from the Scheduler containers. The model must support the requested Chat Completions API version. The schedule fires every weekday at 09:00 UTC and saves successful runs as conversations.
curl --fail-with-body \
-H 'Api-Key: <YOUR_DIAL_API_KEY>' \
-H 'Content-Type: application/json' \
-X POST \
'https://<YOUR_DIAL_HOST>/v1/deployments/applications/public/dial_scheduler__1.0.0/route/v1/schedules/' \
--data '{
"display_name": "Weekday summary",
"service_id": "dial-native",
"trigger": {
"cron": {
"fields": {"day_of_week": "mon-fri", "hour": 9, "minute": 0, "second": 0}
}
},
"properties": {
"target_type": "chat_completion",
"url": "http://dial-core:8080/openai/",
"api_version": "2025-01-01-preview",
"payload": {
"model": "<DEPLOYMENT_ID>",
"messages": [{"role": "user", "content": "Summarize the latest project updates."}],
"stream": true
},
"timeout": 300,
"idle_timeout": 60,
"create_conversation": true
}
}'
Use the returned id for an immediate verification run:
curl --fail-with-body \
-H 'Api-Key: <YOUR_DIAL_API_KEY>' \
-X POST \
'https://<YOUR_DIAL_HOST>/v1/deployments/applications/public/dial_scheduler__1.0.0/route/v1/schedules/<SCHEDULE_ID>/run'
It returns 202 with this shape; the ID and timestamp are illustrative:
{
"id": "2d816fac-83a2-464e-9d69-84d84efca623",
"status": "in_progress",
"start_time": "2026-11-09T15:00:00Z",
"end_time": null,
"conversation_id": null
}
Poll /v1/schedules/<SCHEDULE_ID>/runs/<RUN_ID> through the same Core route prefix until it completes. This run executes in the API process, can overlap other runs, and does not change next_run_time. Acceptance is not execution success; credential failures are recorded later on the run.
Listing and run results
List responses contain count, limit, offset, results, next, and previous. limit defaults to 20 and must be at least 1; offset defaults to 0 and must be non-negative.
Schedule filters include case-insensitive name and model substrings, metadata__<KEY>=<VALUE> string matches, and is_deleted (default false). Filters combine with AND. is_deleted=true lists only soft-deleted records, not both states. Ordering accepts order_by=created_at|next_run_time|name and order_dir=asc|desc; the default is created_at desc. Schedules without a next run sort last when ordering by next_run_time.
Run lists support order_by=created_at and order_dir=asc|desc, defaulting to descending creation time. Run detail includes id, status, start_time, end_time, result, schedule, and conversation_id. schedule summarizes the schedule's current name, trigger, and target properties, not the definition the run executed; after a replacement, earlier runs show the new definition. Status values are in_progress, success, and error.
| Result | Meaning |
|---|---|
{"result": {...}} | Model response from a chat-completion or Responses target |
{"status_code": 200, "body": ...} | REST result; JSON is decoded when possible, otherwise text is stored |
{"events": [...]} | Collected SSE event data |
{"error_text": "..."} | Target execution failed |
{"stage": "credentials", "error_text": "...", "credentials_response": {...}} | Owner credentials could not be obtained; target dispatch did not occur |
conversation_id is populated after successful conversation storage for opted-in chat completions; otherwise it remains null. Sources: list routes, run schemas, run detail, and target executors.
Deletion and errors
Deletion unregisters future execution. A schedule without runs is removed; one with any run history is retained with is_deleted=true. Its details and history stay readable, but update, pause, resume, run-now, and repeat deletion return 409. There is no restore operation. See deletion implementation.
| Status | Meaning |
|---|---|
401 | Core accepted the Api-Key, but its user-info response did not resolve a caller identity. |
403 | Required user sign-in is missing on create or replace. |
404 | Resource does not exist or is not owned by the caller. |
409 | Operation conflicts with a soft-deleted schedule. |
422 | Missing required header or parameter, invalid schedule definition, or invalid list parameter. |
502 | Core rejected or did not answer the caller lookup, including for an invalid or expired Api-Key; sign-in state is unresolved; or job registration or removal failed. |
Errors raised by the endpoint handlers use FastAPI's {"detail": ...} envelope. Sign-in rejection places service_id, state, signed_in, and detail inside that envelope. The upstream API contract's bare-string error examples differ from the implemented handlers.
MCP interface
With MCP_ENABLED=true, the API exposes HTTP MCP at MCP_PATH (default /mcp). It generates tools from schedule, run, and sign-in routes; health and diagnostic routes are excluded. run_schedule_now and get_sign_in_status are explicit tool operation IDs.
The MCP adapter forwards incoming Api-Key and X-DIAL-CLIENT-CHANNEL-ID to the in-process HTTP operations. Both headers are removed from tool input schemas because clients provide them through the request context. The DIAL application definition enables per-request key forwarding for this connection.
Sources: MCP server and header forwarding.
Further reading
- Scheduler configuration — deployment, application identity, consent, and process defaults
- Scheduled tasks — create tasks and view their results in DIAL Chat
- DIAL Chat features — enable scheduled tasks and select Scheduler IDs