REST API · v1

API reference

Telos exposes a REST API over the same service layer the app uses. Every response includes a HATEOAS actions array, and every error includes a machine-actionable suggestion. OpenAPI 3.1 spec at /api/v1/openapi.json.

Auth

Authentication

Authenticate with a bearer token in the Authorization header. Keys start with telos_live_ and carry a role (engineer, pm, em, executive, admin) that determines which fields are returned. Keys are issued from inside the app at Configurations → API Keys; Telos is invite-only today, so request access via the waitlist.

curl
curl -X GET 'https://your-host.telos.app/api/v1/visions' \
  -H 'Authorization: Bearer telos_live_…'
Lists

Pagination

List endpoints use cursor pagination. Pass cursorfrom the previous response's meta.pagination.nextCursor to fetch the next page. Default page size is 50; max is 200 via the limit parameter. The same actions array surfaces the next page as a rel: "next" link, so agents can walk pagination without parsing meta.

response
{
  "ok": true,
  "data": [ /* … items … */ ],
  "meta": {
    "requestId": "01H8X3F4S0Z9KMQ4N6PYZR7C5A",
    "timestamp": "2026-05-18T14:23:11.842Z",
    "pagination": {
      "cursor": null,
      "nextCursor": "eyJpZCI6IjAxIH0=",
      "hasMore": true
    }
  },
  "actions": [
    { "rel": "next", "href": "/api/v1/visions?cursor=eyJpZCI6IjAxIH0=" }
  ]
}
Failure modes

Errors

Errors return a non-2xx status with a body in the standard envelope. The suggestion field is written for LLMs: it states what the caller should do differently. Status codes: 400 validation, 401 missing/invalid credentials, 403 role-gated, 404 not found, 409 conflict (idempotency or state), 422 business-rule violation (e.g. validation gate), 429 rate-limited, 5xx internal.

response
{
  "ok": false,
  "error": {
    "code": "validation_failed",
    "message": "Field 'narrative' must be at least 1 character",
    "suggestion": "Provide a non-empty narrative. The minimum is 1 character."
  },
  "meta": { "requestId": "01H8X3F4S0Z9KMQ4N6PYZR7C5A", "timestamp": "…" }
}
One round trip

Batch

POST /api/v1/batch executes up to 20 operations in a single request. Each operation runs independently; the response is a 207 multi-status whose data contains the per-operation envelopes keyed by the id you supplied. Send an Idempotency-Key header on the batch request to make retries safe.

request body
{
  "operations": [
    { "id": "1", "method": "POST", "path": "/api/v1/objectives", "body": { /* … */ } },
    { "id": "2", "method": "GET",  "path": "/api/v1/visions/abc" }
  ]
}
Resource

Visions

GET/api/v1/visions

List visions

List visions with cursor pagination.

Parameters
cursor
query · string
Opaque pagination cursor from a previous response
limit
query · integer
Number of items per page (default 50, max 200)
sort
query · string
Sort order: field:asc or field:desc, comma-separated
Response · 200 — List of visions
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X GET 'https://your-host.telos.app/api/v1/visions' \
  -H 'Authorization: Bearer telos_live_…'
POST/api/v1/visions

Create a vision

Create a new strategic vision

Request body · required
  • name:stringrequired
  • kind?:"company" | "product"
  • narrative:stringrequired
  • principles?:string
Response · 201 — Created vision
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X POST 'https://your-host.telos.app/api/v1/visions' \
  -H 'Authorization: Bearer telos_live_…' \
  -H 'Content-Type: application/json' \
  -d '{ /* request body */ }'
GET/api/v1/visions/{id}

Get a vision

Parameters
idrequired
path · string (uuid)
Response · 200 — The vision
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X GET 'https://your-host.telos.app/api/v1/visions/{id}' \
  -H 'Authorization: Bearer telos_live_…'
PATCH/api/v1/visions/{id}

Update a vision

Parameters
idrequired
path · string (uuid)
Request body · required
  • name?:string
  • narrative?:string
  • principles?:unknown
Response · 200 — Updated vision
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X PATCH 'https://your-host.telos.app/api/v1/visions/{id}' \
  -H 'Authorization: Bearer telos_live_…' \
  -H 'Content-Type: application/json' \
  -d '{ /* request body */ }'
GET/api/v1/visions/{id}/objectives

List objectives for a vision

Parameters
idrequired
path · string (uuid)
Vision ID
cursor
query · string
Opaque pagination cursor from a previous response
limit
query · integer
Number of items per page (default 50, max 200)
sort
query · string
Sort order: field:asc or field:desc, comma-separated
Response · 200 — Objectives for this vision
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X GET 'https://your-host.telos.app/api/v1/visions/{id}/objectives' \
  -H 'Authorization: Bearer telos_live_…'
Resource

Objectives

GET/api/v1/objectives

List objectives

List objectives with cursor pagination.

Parameters
cursor
query · string
Opaque pagination cursor from a previous response
limit
query · integer
Number of items per page (default 50, max 200)
sort
query · string
Sort order: field:asc or field:desc, comma-separated
Response · 200 — List of objectives
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X GET 'https://your-host.telos.app/api/v1/objectives' \
  -H 'Authorization: Bearer telos_live_…'
POST/api/v1/objectives

Create an objective

Create a strategic objective under a vision

Request body · required
  • title:stringrequired
  • description?:string
  • deadline?:string (date-time)
  • visionId:string (uuid)required
  • driId:string (uuid)required
  • metric:objectrequired
    • metricId:string (uuid)required
    • operator:"gte" | "lte" | "eq"required
    • target:numberrequired
    • startValue?:unknown
Response · 201 — Created objective
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X POST 'https://your-host.telos.app/api/v1/objectives' \
  -H 'Authorization: Bearer telos_live_…' \
  -H 'Content-Type: application/json' \
  -d '{ /* request body */ }'
GET/api/v1/objectives/{id}

Get an objective

Parameters
idrequired
path · string (uuid)
Response · 200 — The objective
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X GET 'https://your-host.telos.app/api/v1/objectives/{id}' \
  -H 'Authorization: Bearer telos_live_…'
PATCH/api/v1/objectives/{id}

Update an objective

Parameters
idrequired
path · string (uuid)
Request body · required
  • title?:string
  • description?:string
  • deadline?:unknown
  • driId?:string (uuid)
  • status?:"active" | "achieved" | "abandoned"
Response · 200 — Updated objective
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X PATCH 'https://your-host.telos.app/api/v1/objectives/{id}' \
  -H 'Authorization: Bearer telos_live_…' \
  -H 'Content-Type: application/json' \
  -d '{ /* request body */ }'
Resource

Metrics

GET/api/v1/metrics

List metrics

List metrics with cursor pagination.

Parameters
cursor
query · string
Opaque pagination cursor from a previous response
limit
query · integer
Number of items per page (default 50, max 200)
sort
query · string
Sort order: field:asc or field:desc, comma-separated
Response · 200 — List of metrics
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X GET 'https://your-host.telos.app/api/v1/metrics' \
  -H 'Authorization: Bearer telos_live_…'
POST/api/v1/metrics

Create a metric

Create a measurable metric

Request body · required
  • name:stringrequired
  • description?:string
  • currentValue?:number
  • unit:"percentage" | "count" | "currency" | "ratio" | "duration" | "custom"required
  • dataSourceType?:"manual" | "integration"
  • dataSourceConfig?:unknown
  • stewardId?:string (uuid)
Response · 201 — Created metric
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X POST 'https://your-host.telos.app/api/v1/metrics' \
  -H 'Authorization: Bearer telos_live_…' \
  -H 'Content-Type: application/json' \
  -d '{ /* request body */ }'
GET/api/v1/metrics/{id}

Get a metric

Parameters
idrequired
path · string (uuid)
Response · 200 — The metric
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X GET 'https://your-host.telos.app/api/v1/metrics/{id}' \
  -H 'Authorization: Bearer telos_live_…'
PATCH/api/v1/metrics/{id}

Update a metric

Parameters
idrequired
path · string (uuid)
Request body · required
  • name?:string
  • description?:string
  • currentValue?:number
  • unit?:"percentage" | "count" | "currency" | "ratio" | "duration" | "custom"
  • dataSourceType?:"manual" | "integration"
  • dataSourceConfig?:unknown
  • stewardId?:unknown
Response · 200 — Updated metric
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X PATCH 'https://your-host.telos.app/api/v1/metrics/{id}' \
  -H 'Authorization: Bearer telos_live_…' \
  -H 'Content-Type: application/json' \
  -d '{ /* request body */ }'
Resource

Opportunities

GET/api/v1/opportunities

List opportunities

List opportunities with cursor pagination.

Parameters
cursor
query · string
Opaque pagination cursor from a previous response
limit
query · integer
Number of items per page (default 50, max 200)
sort
query · string
Sort order: field:asc or field:desc, comma-separated
status
query · string
Filter by status: draft, under_review, approved, in_progress, complete, measured
Response · 200 — List of opportunities
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X GET 'https://your-host.telos.app/api/v1/opportunities' \
  -H 'Authorization: Bearer telos_live_…'
POST/api/v1/opportunities

Create an opportunity

Create a work opportunity. Financial fields are ACL-gated.

Request body · required
  • title:stringrequired
  • description?:string
  • estimatedCost?:number
  • leadId?:string (uuid)
  • teamId?:unknown
  • workflowId:string (uuid)required
  • objectiveLinks?:object[]
  • tagIds?:string (uuid)[]
  • prdTemplateId?:unknown
Response · 201 — Created opportunity
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X POST 'https://your-host.telos.app/api/v1/opportunities' \
  -H 'Authorization: Bearer telos_live_…' \
  -H 'Content-Type: application/json' \
  -d '{ /* request body */ }'
GET/api/v1/opportunities/{id}

Get an opportunity

Parameters
idrequired
path · string (uuid)
Response · 200 — The opportunity
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X GET 'https://your-host.telos.app/api/v1/opportunities/{id}' \
  -H 'Authorization: Bearer telos_live_…'
PATCH/api/v1/opportunities/{id}

Update an opportunity

Parameters
idrequired
path · string (uuid)
Request body · required
  • title?:string
  • description?:string
  • content?:string
  • estimatedCost?:number
  • leadId?:string (uuid)
  • teamId?:unknown
  • prd?:unknown
Response · 200 — Updated opportunity
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X PATCH 'https://your-host.telos.app/api/v1/opportunities/{id}' \
  -H 'Authorization: Bearer telos_live_…' \
  -H 'Content-Type: application/json' \
  -d '{ /* request body */ }'
GET/api/v1/opportunities/{id}/projects

List projects for an opportunity

Parameters
idrequired
path · string (uuid)
Opportunity ID
cursor
query · string
Opaque pagination cursor from a previous response
limit
query · integer
Number of items per page (default 50, max 200)
sort
query · string
Sort order: field:asc or field:desc, comma-separated
Response · 200 — Projects for this opportunity
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X GET 'https://your-host.telos.app/api/v1/opportunities/{id}/projects' \
  -H 'Authorization: Bearer telos_live_…'
POST/api/v1/opportunities/{id}/link-objective

Tie an objective to an opportunity

Parameters
idrequired
path · string (uuid)
Opportunity ID
Request body · required
  • opportunityId:string (uuid)required
  • objectiveId:string (uuid)required
  • estimatedDelta?:unknown
Response · 201 — Objective tied
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X POST 'https://your-host.telos.app/api/v1/opportunities/{id}/link-objective' \
  -H 'Authorization: Bearer telos_live_…' \
  -H 'Content-Type: application/json' \
  -d '{ /* request body */ }'
POST/api/v1/opportunities/{id}/cancel-via-workflow

Reject an opportunity from the workflow step bar

Transitions the opportunity to status 'rejected' with the provided reason AND marks all pending/active workflow step instances as 'skipped' in one atomic call.

Parameters
idrequired
path · string (uuid)
Opportunity ID
Request body · required
  • opportunityId:string (uuid)required
  • reason:stringrequired
Response · 200 — Opportunity rejected; remaining workflow steps skipped
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X POST 'https://your-host.telos.app/api/v1/opportunities/{id}/cancel-via-workflow' \
  -H 'Authorization: Bearer telos_live_…' \
  -H 'Content-Type: application/json' \
  -d '{ /* request body */ }'
GET/api/v1/opportunities/{id}/roi

Calculate ROI for an opportunity

Parameters
idrequired
path · string (uuid)
Opportunity ID
Response · 200 — ROI calculation result
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X GET 'https://your-host.telos.app/api/v1/opportunities/{id}/roi' \
  -H 'Authorization: Bearer telos_live_…'
Resource

Projects

GET/api/v1/projects/{id}/tasks

List tasks for a project

Parameters
idrequired
path · string (uuid)
Project ID
cursor
query · string
Opaque pagination cursor from a previous response
limit
query · integer
Number of items per page (default 50, max 200)
sort
query · string
Sort order: field:asc or field:desc, comma-separated
Response · 200 — Tasks for this project
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X GET 'https://your-host.telos.app/api/v1/projects/{id}/tasks' \
  -H 'Authorization: Bearer telos_live_…'
Resource

Tasks

GET/api/v1/tasks

List tasks

List tasks with cursor pagination.

Parameters
cursor
query · string
Opaque pagination cursor from a previous response
limit
query · integer
Number of items per page (default 50, max 200)
sort
query · string
Sort order: field:asc or field:desc, comma-separated
status
query · string
Filter by status: backlog, todo, in_progress, done, cancelled
priority
query · string
Filter by priority: low, medium, high, urgent
projectId
query · string
Filter by parent project
Response · 200 — List of tasks
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X GET 'https://your-host.telos.app/api/v1/tasks' \
  -H 'Authorization: Bearer telos_live_…'
POST/api/v1/tasks

Create a task

Create a task attached to an opportunity

Request body · required
  • title:stringrequired
  • description?:string
  • content?:string
  • status?:"backlog" | "todo" | "in_progress" | "done" | "cancelled"
  • priority?:"low" | "medium" | "high" | "urgent"
  • opportunityId?:string (uuid)
  • teamId?:unknown
  • workflowId?:string (uuid)
  • estimateMinutes?:integer
  • dueDate?:string (date-time)
  • tagIds?:string (uuid)[]
Response · 201 — Created task
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X POST 'https://your-host.telos.app/api/v1/tasks' \
  -H 'Authorization: Bearer telos_live_…' \
  -H 'Content-Type: application/json' \
  -d '{ /* request body */ }'
GET/api/v1/tasks/{id}

Get a task

Parameters
idrequired
path · string (uuid)
Response · 200 — The task
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X GET 'https://your-host.telos.app/api/v1/tasks/{id}' \
  -H 'Authorization: Bearer telos_live_…'
PATCH/api/v1/tasks/{id}

Update a task

Parameters
idrequired
path · string (uuid)
Request body · required
  • title?:string
  • description?:string
  • content?:unknown
  • status?:"backlog" | "todo" | "in_progress" | "done" | "cancelled"
  • priority?:"low" | "medium" | "high" | "urgent"
  • opportunityId?:unknown
  • teamId?:unknown
  • workflowId?:string (uuid)
  • estimateMinutes?:unknown
  • dueDate?:unknown
Response · 200 — Updated task
  • ok:truerequired
  • data:unknownrequired
  • meta:objectrequired
    • requestId:string (uuid)required
    • timestamp:string (date-time)required
    • version:"v1"required
    • idempotencyKey?:string
  • pagination?:object
    • cursor:unknownrequired
    • hasMore:booleanrequired
  • links:objectrequired
  • actions?:object[]
curl
curl -X PATCH 'https://your-host.telos.app/api/v1/tasks/{id}' \
  -H 'Authorization: Bearer telos_live_…' \
  -H 'Content-Type: application/json' \
  -d '{ /* request body */ }'