Configs
Manage agent configs over the REST API. List and create saved configs, set repo and account default agents, and fetch the built-in starter templates.
/v1/configs is your saved agents as the API sees them, /v1/defaults picks which one runs when a session names none, and /v1/templates serves the built-in starters. Authenticate with your API key as a bearer token, like the rest of the API.
List configs
GET /v1/configs returns every saved agent config in your account.
curl https://api.ellipsis.dev/v1/configs \
-H "Authorization: Bearer $ELLIPSIS_API_TOKEN"The response is { "configs": [...] }. Each entry is the config plus its provenance: every agent is a YAML file in git, so agent_config_source_details names the repository, path, and branch it syncs from, and last_synced_commit_sha is the exact commit the live version came from. agent_config is the parsed file with every default filled in.
{
"configs": [
{
"id": "agent_x9Kd3Fq2",
"customer_id": "cust_2Vb8kQ4nRw6p",
"created_at": "2026-07-14T09:03:44+00:00",
"updated_at": "2026-07-31T16:02:09+00:00",
"deleted": false,
"last_agent_session_id": "session_3Fp9dR2k",
"last_agent_session_created_at": "2026-07-27T09:00:02+00:00",
"edited_by": {
"id": 5201153,
"login": "priya-shah",
"type": "User",
"avatar_url": "https://avatars.githubusercontent.com/u/5201153"
},
"agent_config_source_details": {
"repo_id": 71203944,
"path": "agents/recent-work-summary.yaml",
"branch": "main"
},
"last_synced_commit_sha": "9c4e1f7a2b5d8036e4a1c9f72d05b8e3a6f41c29",
"last_sync_error": null,
"pending_pull_request_url": null,
"agent_config": {
"ellipsis": {
"version": "v1",
"name": "Recent work summary",
"description": "A weekly summary of the code changes we shipped",
"metadata": { "labels": [], "annotations": {} },
"enabled": true,
"interactive": true,
"ide": true
},
"claude": {
"system": "Use the GitHub tools to find the pull requests merged in the\nlast week and summarize what the team has been working on.\nKeep it under 150 words and grounded in what the tools\nreturned. Never invent activity.\n",
"model": "claude-haiku-4-5-20251001",
"effort": null,
"fallback_model": null,
"max_turns": null,
"settings": null
},
"codex": null,
"llm": { "proxy": null },
"trigger": { "type": "cron", "schedule": "0 9 * * 1" },
"sandbox": {
"repositories": [
{ "name": "splitshift-api", "owner": null, "ref": null }
],
"variables": [],
"compute": { "cpu": null, "memory": null, "timeout": null },
"image": { "dockerfile_append": null, "setup": null },
"hooks": { "post_start": null, "post_clone": null },
"github": { "permissions": null, "repositories": null },
"ports": [3000, 5173, 8000, 8080]
},
"skills": [],
"structured_output": null,
"budget": { "session": 1.0, "day": null, "week": 2.0, "month": null },
"mcp_servers": []
},
"is_pull_request_head_preview": false
}
]
}Three fields carry state you may need to act on:
last_sync_erroris the parse or validation error from the most recent sync of the file, ornullwhen it succeeded.pending_pull_request_urlis set while a config's creating pull request is still open: the agent exists but does not run until the pull request merges.last_agent_session_idis the newest session this config ran.
Fetch one config with GET /v1/configs/{config_id}; an unknown or deleted id is 404.
POST /v1/configs creates an agent the way the dashboard does: it opens a pull request adding the YAML file to a repository you name, and the agent goes live when that pull request merges.
curl https://api.ellipsis.dev/v1/configs \
-H "Authorization: Bearer $ELLIPSIS_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"template_id": "daily-standup",
"repository": "splitshift-api"
}'| Field | Type | Description |
|---|---|---|
config | object | An inline agent config. Pass exactly one of config and template_id. |
template_id | string | A starter template slug from GET /v1/templates, e.g. daily-standup. |
repository | string | Required. The repository the file is added to, as a bare name in your account (splitshift-api, not splitshift-hq/splitshift-api). An unknown repository is 404. |
path | string | Where the file goes. Defaults to agents/<slug>.yaml, slugified from the agent's name. A custom path must be a .yaml/.yml file under agents/, .agents/, ellipsis/, or .ellipsis/ at any depth, else 400. |
The response is { "config": {...}, "path": "...", "pull_request_url": "..." }: the saved config in the same shape the list returns, born pending (pending_pull_request_url set to the same URL), the file path chosen, and the pull request to merge. If another agent already syncs from that path, or a file already exists there, the request is refused with 409; rename the agent or pass a different path.
Default agents
A session started with no config_id, config, or template_id resolves its config down a ladder: the repository's default agent if one is set, else the account default, else a bare ad-hoc config (an empty system prompt on claude-opus-5, no trigger, default sandbox and budget, so the per-session prompt is the whole instruction). These endpoints manage the two rungs you can set. A rung is addressed by what it covers, never by row id: the account default is repository omitted (or null), a repository default is repository as "owner/name".
GET /v1/defaults lists every rung that is set.
curl https://api.ellipsis.dev/v1/defaults \
-H "Authorization: Bearer $ELLIPSIS_API_TOKEN"{
"defaults": [
{
"id": "agent_default_6Wn2rT8kPq4z",
"repository": null,
"config_id": "agent_x9Kd3Fq2",
"config_name": "Recent work summary",
"broken": null,
"updated_at": "2026-07-29T11:36:50+00:00"
},
{
"id": "agent_default_3Jm9xC5vDf7s",
"repository": "splitshift-hq/splitshift-api",
"config_id": "agent_7Tp4wN6bZk2m",
"config_name": "Linear issue implementer",
"broken": null,
"updated_at": "2026-07-31T09:12:04+00:00"
}
]
}broken is null when the rung can serve sessions, else why it cannot: config_deleted, config_disabled, config_pending_pr, or repo_inaccessible. A broken rung fails bare session starts with 409 and a message naming the setting, never a silent fallback to the next rung, so a deleted config cannot quietly swap which agent your automation runs. Fix or clear it.
PUT /v1/defaults sets a rung's pointer, replacing whatever it pointed at before. The response is the updated rung, in the same shape GET returns.
curl https://api.ellipsis.dev/v1/defaults \
-H "Authorization: Bearer $ELLIPSIS_API_TOKEN" \
-H "Content-Type: application/json" \
-X PUT \
-d '{"repository": "splitshift-hq/splitshift-api", "config_id": "agent_7Tp4wN6bZk2m"}'| Field | Type | Description |
|---|---|---|
repository | string | The repository whose default to set, as owner/name. Omit to set the account default. A repository outside your installation is 404. |
config_id | string | The saved config to point the rung at. Only a live, synced config is accepted: an unknown or deleted id is 404; a disabled config, or one whose pull request has not merged, is 400. |
DELETE /v1/defaults clears the account default; DELETE /v1/defaults?repository=owner/name clears that repository's. Success is 204; clearing a rung that is not set is 404.
curl "https://api.ellipsis.dev/v1/defaults?repository=splitshift-hq/splitshift-api" \
-H "Authorization: Bearer $ELLIPSIS_API_TOKEN" \
-X DELETEThe token an agent holds inside its own sandbox can read the ladder but not change it: code running in a sandbox must not be able to repoint which agent your account runs by default. PUT and DELETE need an API key or user token; a sandbox token is refused with 403.
Templates
GET /v1/templates lists the built-in starter templates: complete, deployable agent configs you can ship as-is or use as a starting point. Fetch one with GET /v1/templates/{template_id}.
curl https://api.ellipsis.dev/v1/templates \
-H "Authorization: Bearer $ELLIPSIS_API_TOKEN"The response is { "templates": [...], "walkthrough_yaml": "..." }. Each template carries its slug (the id you pass elsewhere), name, description, tags, a longer summary, a use_case, and yaml: the complete config file, ready to commit. walkthrough_yaml is a display-only example config the dashboard's install walkthrough shows; it is not a template you can deploy or run by slug.
{
"templates": [
{
"slug": "daily-standup",
"name": "Daily Standup",
"description": "Posts a product-level summary of yesterday's merged pull requests across every repository.",
"tags": ["scheduled", "reporting"],
"summary": "Runs each weekday morning, gathers every pull request merged in the last day across all repositories, and synthesizes them into a themed, product-level standup written for the #engineering channel.",
"use_case": "Use this when the team wants one clear morning update instead of scanning merge notifications. It groups related merges into the features and fixes they add up to, keeps internal maintenance to a footnote, and returns a Slack-ready summary.",
"yaml": "ellipsis:\n version: v1\n name: Daily Standup\n description: A product-level summary of yesterday's merged pull requests across every repository\n\nclaude:\n model: claude-sonnet-5\n system: ...\n\ntrigger:\n type: cron\n schedule: \"0 13 * * 1-5\"\n\nsandbox:\n github:\n permissions: read_only\n\nbudget:\n session: 1.00\n day: 2.00\n week: 10.00\n month: 30.00\n"
}
],
"walkthrough_yaml": "ellipsis:\n version: v1\n name: Team Activity Report\n..."
}A slug is accepted in two places, and the two accept different sets:
template_idon create config deploys a template from this list: it opens the pull request that adds the template's YAML to your repository.template_idon start session runs a template once, without deploying anything. Only the run-on-demand templates are accepted here:welcome-to-ellipsis,agent-config-builder,session-log-search, andteam-activity-report. Any other slug is404, because those templates carry example repositories and triggers meant to be edited before they run.