Skip to documentation

Cadylo API v1

Build around the work.

Create issues, read project context, and connect delivery systems with a secure, workspace-scoped REST API.

10
endpoints
120
requests / min
JSON
over HTTPS

Base URL

https://cadylo.app/api/v1

Stable v1
Your first request
export CADYLO_TOKEN="cdl_…"

curl --request GET \
  --url "https://cadylo.app/api/v1/me" \
  --header "Authorization: Bearer $CADYLO_TOKEN"
Scoped credentials · live RBAC · private responses

Credentials

Authentication

Every request is authorized by a personal token tied to one member and one workspace. Tokens keep the member’s live visibility and permissions.

  1. 01

    Open Developer settings

    In a workspace, open Developer and create a personal API token. The secret is shown once.

  2. 02

    Choose the smallest scope

    Read tokens can only use GET. Write tokens can also create issues and comments and update issues, subject to live role permissions.

  3. 03

    Send the bearer header

    Keep the token on your server or in a secret store. Never put it in a URL or expose it to browser code.

Authorization header
Authorization: Bearer cdl_…
Accept: application/json

Credential behavior

  • Revocation and workspace removal take effect immediately.
  • Unused tokens expire after 90 days of inactivity.
  • Browser cross-origin access is not enabled; use a server or CLI.
  • The token can only access resources visible to its owner in https://cadylo.app/api/v1.

One minute setup

Quick start

Export your token, call the introspection endpoint, and confirm the workspace and scope before building the rest of your integration.

Request
export CADYLO_TOKEN="cdl_…"

curl --request GET \
  --url "https://cadylo.app/api/v1/me" \
  --header "Authorization: Bearer $CADYLO_TOKEN"
200 OK
{
  "data": {
    "user": {
      "id": "c03ed56c-fb31-47c5-8f7f-9708060d933a",
      "display_name": "Ada Lovelace",
      "email": "ada@example.com"
    },
    "workspace": {
      "id": "5a6ded09-51ac-4da5-b047-581d0206da43",
      "slug": "acme",
      "name": "Acme"
    },
    "scope": "write",
    "access_revision": 12,
    "workspace_permissions": ["issues.view", "issues.create"],
    "assignments": []
  }
}

Successful responses are JSON and use a top-level data property. List endpoints return an array, and paginated lists also return pagination.next_cursor.

Workspace context

Identity & teams

Inspect the token owner and discover the teams visible to that member.

GET/me

Inspect the current token

Returns the token owner, workspace, scope, live permissions, role assignments, and current access revision.

read scope
Request
curl --request GET \
  --url "https://cadylo.app/api/v1/me" \
  --header "Authorization: Bearer $CADYLO_TOKEN"
200 OK
{
  "data": {
    "user": {
      "id": "c03ed56c-fb31-47c5-8f7f-9708060d933a",
      "display_name": "Ada Lovelace",
      "email": "ada@example.com"
    },
    "workspace": {
      "id": "5a6ded09-51ac-4da5-b047-581d0206da43",
      "slug": "acme",
      "name": "Acme"
    },
    "scope": "write",
    "access_revision": 12,
    "workspace_permissions": ["issues.view", "issues.create"],
    "assignments": []
  }
}
GET/teams

List visible teams

Returns every team the token owner can see in the token workspace.

read scope
Request
curl --request GET \
  --url "https://cadylo.app/api/v1/teams" \
  --header "Authorization: Bearer $CADYLO_TOKEN"
200 OK
{
  "data": [
    {
      "id": "0e879dc8-8cc6-4f35-bdb9-a6ce2c74b410",
      "key": "ENG",
      "name": "Engineering",
      "color": "#7c3aed",
      "created_at": "2026-05-06T08:14:22.000Z"
    }
  ]
}

Delivery context

Projects

Read projects and their current delivery status from the workspace.

GET/projects

List projects

Returns up to 250 visible projects. Filter by status when you only need active or completed work.

read scope

Query parameters

FieldTypeDescription
statusenumbacklog, planned, in_progress, paused, completed, or canceled.
Request
curl --request GET \
  --url "https://cadylo.app/api/v1/projects?status=in_progress" \
  --header "Authorization: Bearer $CADYLO_TOKEN"
200 OK
{
  "data": [
    {
      "id": "7e724a48-e5d7-4389-9215-0a3a103c2f49",
      "name": "Mobile launch",
      "description": "Ship the first public mobile release.",
      "status": "in_progress",
      "health": "on_track",
      "lead_id": "90c15db5-d94b-44ad-9804-ed82554e5d10",
      "team_id": "0e879dc8-8cc6-4f35-bdb9-a6ce2c74b410",
      "start_date": "2026-06-01",
      "target_date": "2026-08-28",
      "url": "https://cadylo.app/acme/project/7e724a48-e5d7-4389-9215-0a3a103c2f49",
      "created_at": "2026-05-12T09:20:18.000Z",
      "updated_at": "2026-07-14T16:42:09.000Z"
    }
  ]
}
GET/projects/{projectId}

Retrieve a project

Returns one visible project by UUID.

read scope
Request
curl --request GET \
  --url "https://cadylo.app/api/v1/projects/7e724a48-e5d7-4389-9215-0a3a103c2f49" \
  --header "Authorization: Bearer $CADYLO_TOKEN"
200 OK
{
  "data": {
  "id": "7e724a48-e5d7-4389-9215-0a3a103c2f49",
  "name": "Mobile launch",
  "description": "Ship the first public mobile release.",
  "status": "in_progress",
  "health": "on_track",
  "lead_id": "90c15db5-d94b-44ad-9804-ed82554e5d10",
  "team_id": "0e879dc8-8cc6-4f35-bdb9-a6ce2c74b410",
  "start_date": "2026-06-01",
  "target_date": "2026-08-28",
  "url": "https://cadylo.app/acme/project/7e724a48-e5d7-4389-9215-0a3a103c2f49",
  "created_at": "2026-05-12T09:20:18.000Z",
  "updated_at": "2026-07-14T16:42:09.000Z"
}
}

Core resources

Issues

Find, create, and update the work that moves through your team workflows. Historical issues keep their content after an account is deleted, with creator_id set to null.

GET/issues

List issues

Returns visible issues newest first using stable, cursor-based pagination.

read scope

Query parameters

FieldTypeDescription
statusenumbacklog, todo, in_progress, in_review, done, or canceled.
teamstringTeam key such as ENG. Matching is case-insensitive.
assignee_iduuidReturn issues assigned to this workspace member.
updated_sinceISO 8601Return issues updated at or after this timestamp.
limitintegerPage size from 1 to 100. Defaults to 50.
cursorstringOpaque cursor returned by the previous page.
Request
curl --request GET \
  --url "https://cadylo.app/api/v1/issues?team=ENG&status=in_progress&limit=25" \
  --header "Authorization: Bearer $CADYLO_TOKEN"
200 OK
{
  "data": [
    {
      "id": "4f673866-76c2-4cb2-9366-fce756c31f8d",
      "key": "ENG-42",
      "title": "Add passkey sign-in",
      "status": "in_progress",
      "priority": 2,
      "team": { "id": "0e879dc8-8cc6-4f35-bdb9-a6ce2c74b410", "key": "ENG", "name": "Engineering" },
      "updated_at": "2026-07-15T08:32:17.000Z"
    }
  ],
  "pagination": {
    "next_cursor": "eyJ2IjoxLCJzY29wZSI6Imlzc3Vlc19kZXNjIiw..."
  }
}

Issue objects include the complete resource shape shown by the retrieve endpoint; the example is shortened for readability.

POST/issues

Create an issue

Creates an issue as the token owner. The member must also have permission to create issues in the selected team.

write scope

JSON body

FieldTypeDescription
team_iduuidTeam UUID. Provide exactly one of team_id or team_key.
team_keystringTeam key. Provide exactly one of team_id or team_key.
titlerequiredstringIssue title, from 1 to 255 characters.
descriptionstringMarkdown-capable description, up to 100,000 characters. Defaults to an empty string.
statusenumbacklog, todo, in_progress, in_review, done, or canceled. Defaults to backlog.
priorityinteger0 none, 1 urgent, 2 high, 3 medium, or 4 low. Defaults to 0.
assignee_iduuid | nullWorkspace member to assign, or null.
project_iduuid | nullProject to attach, or null.
estimateinteger | nullEstimate from 0 to 21, or null.
due_datedate | nullISO date in YYYY-MM-DD format, or null.
Request
curl --request POST \
  --url "https://cadylo.app/api/v1/issues" \
  --header "Authorization: Bearer $CADYLO_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "team_key": "ENG",
    "title": "Add passkey sign-in",
    "description": "Support passkeys on web and mobile.",
    "priority": 2,
    "estimate": 5,
    "due_date": "2026-08-15"
  }'
201 Created
{
  "data": {
    "id": "4f673866-76c2-4cb2-9366-fce756c31f8d",
    "key": "ENG-42",
    "number": 42,
    "title": "Add passkey sign-in",
    "description": "Support passkeys on web and mobile.",
    "status": "in_progress",
    "priority": 2,
    "estimate": 5,
    "assignee_id": "90c15db5-d94b-44ad-9804-ed82554e5d10",
    "creator_id": "c03ed56c-fb31-47c5-8f7f-9708060d933a",
    "project_id": "7e724a48-e5d7-4389-9215-0a3a103c2f49",
    "due_date": "2026-08-15",
    "start_date": null,
    "team": {
      "id": "0e879dc8-8cc6-4f35-bdb9-a6ce2c74b410",
      "key": "ENG",
      "name": "Engineering"
    },
    "url": "https://cadylo.app/acme/issue/ENG-42",
    "created_at": "2026-07-11T10:24:08.000Z",
    "updated_at": "2026-07-15T08:32:17.000Z",
    "completed_at": null
  }
}
GET/issues/{issueKey}

Retrieve an issue

Returns one visible issue by its human-readable key, such as ENG-42.

read scope
Request
curl --request GET \
  --url "https://cadylo.app/api/v1/issues/ENG-42" \
  --header "Authorization: Bearer $CADYLO_TOKEN"
200 OK
{
  "data": {
    "id": "4f673866-76c2-4cb2-9366-fce756c31f8d",
    "key": "ENG-42",
    "number": 42,
    "title": "Add passkey sign-in",
    "description": "Support passkeys on web and mobile.",
    "status": "in_progress",
    "priority": 2,
    "estimate": 5,
    "assignee_id": "90c15db5-d94b-44ad-9804-ed82554e5d10",
    "creator_id": "c03ed56c-fb31-47c5-8f7f-9708060d933a",
    "project_id": "7e724a48-e5d7-4389-9215-0a3a103c2f49",
    "due_date": "2026-08-15",
    "start_date": null,
    "team": {
      "id": "0e879dc8-8cc6-4f35-bdb9-a6ce2c74b410",
      "key": "ENG",
      "name": "Engineering"
    },
    "url": "https://cadylo.app/acme/issue/ENG-42",
    "created_at": "2026-07-11T10:24:08.000Z",
    "updated_at": "2026-07-15T08:32:17.000Z",
    "completed_at": null
  }
}
PATCH/issues/{issueKey}

Update an issue

Updates one or more editable fields. Unknown fields and empty update objects are rejected.

write scope

JSON body

FieldTypeDescription
titlestringNew title, from 1 to 255 characters.
descriptionstringNew Markdown-capable description, up to 100,000 characters.
statusenumNew status: backlog, todo, in_progress, in_review, done, or canceled.
priorityintegerNew priority: 0 none, 1 urgent, 2 high, 3 medium, or 4 low.
assignee_iduuid | nullWorkspace member to assign, or null.
estimateinteger | nullEstimate from 0 to 21, or null.
due_datedate | nullISO date in YYYY-MM-DD format, or null.
Request
curl --request PATCH \
  --url "https://cadylo.app/api/v1/issues/ENG-42" \
  --header "Authorization: Bearer $CADYLO_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "status": "in_review",
    "assignee_id": "90c15db5-d94b-44ad-9804-ed82554e5d10"
  }'
200 OK
{
  "data": {
    "id": "4f673866-76c2-4cb2-9366-fce756c31f8d",
    "key": "ENG-42",
    "number": 42,
    "title": "Add passkey sign-in",
    "description": "Support passkeys on web and mobile.",
    "status": "in_review",
    "priority": 2,
    "estimate": 5,
    "assignee_id": "90c15db5-d94b-44ad-9804-ed82554e5d10",
    "creator_id": "c03ed56c-fb31-47c5-8f7f-9708060d933a",
    "project_id": "7e724a48-e5d7-4389-9215-0a3a103c2f49",
    "due_date": "2026-08-15",
    "start_date": null,
    "team": {
      "id": "0e879dc8-8cc6-4f35-bdb9-a6ce2c74b410",
      "key": "ENG",
      "name": "Engineering"
    },
    "url": "https://cadylo.app/acme/issue/ENG-42",
    "created_at": "2026-07-11T10:24:08.000Z",
    "updated_at": "2026-07-15T08:32:17.000Z",
    "completed_at": null
  }
}

Conversation

Comments

Read the discussion on an issue or add a comment as the token owner. Historical comments keep their body after an account is deleted, with author set to null.

GET/issues/{issueKey}/comments

List comments

Returns visible comments oldest first with cursor-based pagination.

read scope

Query parameters

FieldTypeDescription
limitintegerPage size from 1 to 100. Defaults to 50.
cursorstringOpaque cursor returned by the previous page.
Request
curl --request GET \
  --url "https://cadylo.app/api/v1/issues/ENG-42/comments?limit=50" \
  --header "Authorization: Bearer $CADYLO_TOKEN"
200 OK
{
  "data": [
    {
      "id": "707ac219-4f91-45c5-8ed9-a0c27e678864",
      "issue_id": "4f673866-76c2-4cb2-9366-fce756c31f8d",
      "body": "The mobile flow is ready for review.",
      "author": {
        "id": "c03ed56c-fb31-47c5-8f7f-9708060d933a",
        "display_name": "Ada Lovelace"
      },
      "created_at": "2026-07-15T09:10:42.000Z",
      "updated_at": "2026-07-15T09:10:42.000Z"
    }
  ],
  "pagination": { "next_cursor": null }
}
POST/issues/{issueKey}/comments

Create a comment

Adds a comment as the token owner. The body must contain between 1 and 10,000 characters.

write scope

JSON body

FieldTypeDescription
bodyrequiredstringComment text, from 1 to 10,000 characters.
Request
curl --request POST \
  --url "https://cadylo.app/api/v1/issues/ENG-42/comments" \
  --header "Authorization: Bearer $CADYLO_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "body": "The mobile flow is ready for review."
  }'
201 Created
{
  "data": {
  "id": "707ac219-4f91-45c5-8ed9-a0c27e678864",
  "issue_id": "4f673866-76c2-4cb2-9366-fce756c31f8d",
  "body": "The mobile flow is ready for review.",
  "author": {
    "id": "c03ed56c-fb31-47c5-8f7f-9708060d933a",
    "display_name": "Ada Lovelace"
  },
  "created_at": "2026-07-15T09:10:42.000Z",
  "updated_at": "2026-07-15T09:10:42.000Z"
}
}

Stable list traversal

Pagination

Issue and comment lists use opaque, signed keyset cursors so new activity does not shift items between numbered pages.

01

Read next_cursor

When more records exist, the response contains a non-null pagination.next_cursor.

02

Pass it back unchanged

Send it as the cursor query parameter and keep the same filters for the next request.

03

Stop at null

A null cursor means the current page is the final page.

Next page
curl --get "https://cadylo.app/api/v1/issues" \
  --header "Authorization: Bearer $CADYLO_TOKEN" \
  --data-urlencode "limit=50" \
  --data-urlencode "cursor=$NEXT_CURSOR"

Predictable failures

Errors & rate limits

Errors use one stable envelope. Authenticated requests share a fixed quota of 120 requests per token every 60 seconds.

Error response
{
  "error": {
    "code": "invalid_request",
    "message": "The request body is not valid JSON"
  }
}
Rate-limit headers
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1784108580
Retry-After: 42
HTTPCodeMeaning
400invalid_requestMalformed JSON, invalid fields, query, or cursor.
401unauthorizedNo bearer token was provided.
401invalid_tokenThe token is malformed, revoked, or no longer valid.
401token_expiredThe token expired by date or after 90 days of inactivity.
403insufficient_scopeA read token attempted a write operation.
403insufficient_permissionThe member cannot perform this operation.
404not_foundThe resource does not exist or is not visible.
409conflictThe resource conflicts with existing data.
413payload_too_largeThe JSON body is larger than 128 KiB.
415unsupported_media_typeA write request is not application/json.
422validation_failedA reference or data constraint is not valid.
429rate_limitedThe fixed request window has been exhausted.
500internal_errorAn unexpected server error occurred.
503service_unavailableThe API is temporarily unavailable.

Wait for reset

On 429, honor Retry-After before retrying.

Never cached

API responses use private, no-store caching headers.

Strict JSON

Unknown body fields and ambiguous list queries are rejected.

Events, delivered

Outbound webhooks

Receive signed HTTPS events when issues, comments, or projects change, without polling the REST API.

issue.createdissue.updatedissue.deletedcomment.createdproject.createdproject.updated

Workspace administrators configure endpoints from Settings → Webhooks. HTTP endpoints must use a publicly reachable HTTPS URL.

Event payload
{
  "id": "7bc4d395-f27d-4d0f-a3a9-8860f15dbb3a",
  "type": "issue.created",
  "created_at": "2026-07-15T09:42:11.000Z",
  "workspace": {
    "slug": "acme",
    "name": "Acme"
  },
  "actor": { "name": "Ada Lovelace" },
  "data": {
    "issue": {
      "id": "4f673866-76c2-4cb2-9366-fce756c31f8d",
      "key": "ENG-42",
      "title": "Add passkey sign-in",
      "status": "backlog"
    }
  }
}
Verify the signature
X-Cadylo-Signature: sha256=<hex>
X-Cadylo-Timestamp: 1784108538
X-Cadylo-Event: issue.created
X-Cadylo-Delivery: 590f5fd8-c5a7-4caf-8e2a-0292ea471b58

signed_payload = timestamp + "." + raw_request_body
hex = HMAC_SHA256(webhook_secret, signed_payload)

Verify before parsing

Compute the HMAC over the timestamp and raw request body, then reject stale timestamps.

Stable delivery ID

Use X-Cadylo-Delivery to make your endpoint idempotent across retries.

Fast acknowledgements

Return any 2xx within 10 seconds; failed deliveries retry up to eight times.

Start building

Turn project signals into reliable workflows.

Create a scoped token in your workspace, confirm it with GET /me, and keep the secret in your server environment.

Open Developer settings