Skip to main content
Early Access — Beta The Elean Public API is currently in beta. Endpoint paths, request/response shapes, and scopes may change before the stable 1.0 release. We will always communicate breaking changes before they go live.

Overview

The Elean Public API lets external clients — automation scripts, AI agents, CLI tools, and third-party integrations — read and write tasks without going through the browser UI. Authentication is handled via API keys tied to a specific workspace.

Base URL

https://api.elean.app/v1/public
All endpoints are relative to this base URL.

Authentication

Every request must include a valid API key. Authorization header (recommended):
Authorization: Bearer el_<your_key>
API keys are created in Workspace Settings → API Keys. Each key carries:
  • Scopes — which operations it may perform (task:read, task:create, task:update)
  • Project scope — access to all projects in the workspace, or restricted to a specific project
  • Expiry — an optional date after which the key stops working
API keys are displayed once at creation time. Copy and store yours securely — it cannot be retrieved again.

Rate Limits

Rate limits are enforced per API key at 60 requests per minute. Exceeding the limit returns 429 Too Many Requests. Per-plan limits will be introduced in a future release.

Scopes

ScopeGrants access to
task:readList tasks, get a task, list comments
task:createCreate tasks, upload attachments
task:updateUpdate tasks, delete tasks, add comments

Endpoints

List statuses

GET /{projectSlug}/statuses Returns all custom task statuses for the project. Use the returned id values as statusId when creating or filtering tasks. Requires task:read. Example request
curl https://api.elean.app/v1/public/my-project/statuses \
  -H "Authorization: Bearer el_a3f9c2e1b8d47f6a9c0e2b5d8f1a4c7e9b2d5f8a1"

List tasks

GET /{projectSlug}/tasks Returns a paginated list of top-level tasks in the given project. Subtasks are excluded. Requires task:read. Query parameters
ParameterTypeDefaultDescription
pageinteger1Page number (1-based)
limitinteger20Results per page, max 100
statusIdUUIDFilter by specific custom status ID (takes precedence over status)
statusstringFilter by status category: todo, in_progress, done
prioritystringFilter by priority: none, low, medium, high, urgent
searchstringSearch in title or external ID (e.g. PROJ-42)
Example request
curl "https://api.elean.app/v1/public/my-project/tasks?status=in_progress&limit=10" \
  -H "Authorization: Bearer el_a3f9c2e1b8d47f6a9c0e2b5d8f1a4c7e9b2d5f8a1"

Get task

GET /{projectSlug}/tasks/{taskId} Returns a single task. Accepts either a UUID or an external ID (e.g. PROJ-42). Requires task:read. Example request
curl https://api.elean.app/v1/public/my-project/tasks/PROJ-42 \
  -H "Authorization: Bearer el_a3f9c2e1b8d47f6a9c0e2b5d8f1a4c7e9b2d5f8a1"

Create task

POST /{projectSlug}/tasks Creates a new task in the given project. Requires task:create. Request body
FieldTypeRequiredDescription
titlestringYesTask title, 1–500 characters
descriptionstringNoPlain text description. Newlines are preserved
prioritystringNonone, low, medium, high, or urgent. Defaults to medium
dueDatestringNoISO 8601 date-time, e.g. 2026-03-15T00:00:00.000Z
statusIdUUIDNoCustom status ID. Defaults to the first todo status if omitted
Example request
curl -X POST https://api.elean.app/v1/public/my-project/tasks \
  -H "Authorization: Bearer el_a3f9c2e1b8d47f6a9c0e2b5d8f1a4c7e9b2d5f8a1" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Fix login bug",
    "description": "Users cannot log in with SSO on Safari.",
    "priority": "high",
    "dueDate": "2026-03-15T00:00:00.000Z"
  }'

Update task

PATCH /{projectSlug}/tasks/{taskId} Updates one or more fields on an existing task. Only the fields you include are changed. Accepts either a UUID or an external ID. Requires task:update. Request body
FieldTypeRequiredDescription
titlestringNoNew task title, 1–500 characters
descriptionstring | nullNoNew description, or null to clear it
prioritystringNonone, low, medium, high, or urgent
dueDatestring | nullNoISO 8601 date-time, or null to clear it
statusIdUUIDNoCustom status ID to assign
Example request
curl -X PATCH https://api.elean.app/v1/public/my-project/tasks/PROJ-42 \
  -H "Authorization: Bearer el_a3f9c2e1b8d47f6a9c0e2b5d8f1a4c7e9b2d5f8a1" \
  -H "Content-Type: application/json" \
  -d '{
    "priority": "urgent",
    "statusId": "018e1b2c-aaaa-0000-0000-000000000002"
  }'

Delete task

DELETE /{projectSlug}/tasks/{taskId} Permanently deletes a task. This action cannot be undone. Accepts either a UUID or an external ID. Requires task:update. Example request
curl -X DELETE https://api.elean.app/v1/public/my-project/tasks/PROJ-42 \
  -H "Authorization: Bearer el_a3f9c2e1b8d47f6a9c0e2b5d8f1a4c7e9b2d5f8a1"
Response
{ "success": true }

List comments

GET /{projectSlug}/tasks/{taskId}/comments Returns all comments on a task, ordered oldest first. Accepts either a UUID or an external ID. Requires task:read. Example request
curl https://api.elean.app/v1/public/my-project/tasks/PROJ-42/comments \
  -H "Authorization: Bearer el_a3f9c2e1b8d47f6a9c0e2b5d8f1a4c7e9b2d5f8a1"
Example response
[
  {
    "id": "018e1b2c-cccc-0000-0000-000000000001",
    "content": "This is ready for review.",
    "authorName": "my-api-key",
    "createdAt": "2026-03-15T10:00:00.000Z",
    "updatedAt": "2026-03-15T10:00:00.000Z"
  }
]

Add comment

POST /{projectSlug}/tasks/{taskId}/comments Adds a comment to a task. The comment is attributed to the API key name. Accepts either a UUID or an external ID. Requires task:update. Request body
FieldTypeRequiredDescription
contentstringYesComment text, 1–10 000 characters
Example request
curl -X POST https://api.elean.app/v1/public/my-project/tasks/PROJ-42/comments \
  -H "Authorization: Bearer el_a3f9c2e1b8d47f6a9c0e2b5d8f1a4c7e9b2d5f8a1" \
  -H "Content-Type: application/json" \
  -d '{ "content": "Deployed to staging." }'

Get attachment

GET /{projectSlug}/tasks/{taskId}/attachments/{attachmentId} Returns attachment details including a presigned download URL valid for 1 hour. Requires task:read.

Upload attachment

POST /{projectSlug}/tasks/{taskId}/attachments Uploads a file and attaches it to a task. Max file size is 10 MB. Send as multipart/form-data with a file field. Requires task:create.

Task object

All task endpoints return tasks in the following shape:
{
  "id": "018e1b2c-3d4e-5f6a-7b8c-9d0e1f2a3b4c",
  "externalId": "PROJ-42",
  "title": "Fix login bug",
  "description": "Users cannot log in with SSO on Safari.",
  "category": "in_progress",
  "status": {
    "id": "018e1b2c-aaaa-0000-0000-000000000002",
    "name": "In Review",
    "color": "#f59e0b",
    "category": "in_progress"
  },
  "priority": "high",
  "dueDate": "2026-03-15T00:00:00.000Z",
  "assignees": [
    { "id": "018e1b2c-0000-0000-0000-000000000099", "name": "Jane Smith" }
  ],
  "attachments": [
    { "id": "018e1b2c-aaaa-bbbb-cccc-000000000001", "filename": "screenshot.png" }
  ],
  "createdAt": "2026-03-01T12:00:00.000Z",
  "updatedAt": "2026-03-02T09:30:00.000Z"
}
FieldTypeDescription
idUUIDUnique identifier
externalIdstringHuman-readable ID, unique within the project (e.g. PROJ-42)
titlestringTask title
descriptionstring | nullPlain text description, or null if empty
categorystringStatus category: todo, in_progress, or done
statusobject | nullFull custom status object { id, name, color, category }
prioritystringOne of none, low, medium, high, urgent
dueDatestring | nullISO 8601 date-time, or null
assigneesarrayList of { id, name } objects
attachmentsarrayList of { id, filename } — use Get Attachment for the download URL
createdAtstringISO 8601 creation timestamp
updatedAtstringISO 8601 last-updated timestamp

Error responses

All errors follow the same shape:
{
  "statusCode": 403,
  "message": "Missing required scope: task:create"
}
StatusMeaning
400 Bad RequestInvalid or missing request fields
401 UnauthorizedAPI key is missing, invalid, or expired
403 ForbiddenKey lacks the required scope, or the project is outside the key’s allowed scope
404 Not FoundProject or task not found within the key’s workspace
429 Too Many RequestsRate limit exceeded