DoneThat

Projects

List, read, create, update, and archive DoneThat projects through the REST API.

GET / POST / DELETE/projectsScopes:projects:readprojects:write

The projects endpoint lets you list, read, create, update, and archive DoneThat projects.

GET https://api.donethat.ai/projectsGET https://api.donethat.ai/projects/:idPOST https://api.donethat.ai/projectsPOST https://api.donethat.ai/projects/:idDELETE https://api.donethat.ai/projects/:id

Updates use POST (not PATCH or PUT). Unsupported methods return 405 with { "success": false, "error": "Method Not Allowed" }.

Authentication

Pass your API key in the x-api-key header.

RouteRequired scope
GET /projectsprojects:read (or projects:write)
GET /projects/:idprojects:read (or projects:write)
POST /projectsprojects:write
POST /projects/:idprojects:write
DELETE /projects/:idprojects:write

Keys with projects:write may call all /projects routes above. Use projects:read alone for read-only integrations.

Project object

Returned as project (single) or in the projects array (list):

{
  "id": "project_123",
  "name": "Customer onboarding",
  "description": "Implementation work for new customers",
  "color": "#FFB623",
  "portfolioId": null,
  "teamId": "team_123",
  "private": false,
  "confidential": false,
  "status": "active",
  "createdAt": "2026-05-19T09:00:00.000Z",
  "updatedAt": "2026-05-19T09:10:00.000Z",
  "usedAt": "2026-05-19T09:10:00.000Z",
  "createdBy": "user_123",
  "updatedBy": "user_123"
}

Timestamp fields are ISO 8601 UTC strings or null.

List projects

GET /projects

Query parameters:

ParameterTypeDefaultNotes
sortstringcreatedAtSort key, descending. One of createdAt, updatedAt, usedAt.
includeArchivedbooleanfalsePass true to include archived projects.

Response:

{
  "success": true,
  "projects": [
    {
      "id": "project_123",
      "name": "Customer onboarding",
      "description": null,
      "color": "#FFB623",
      "portfolioId": null,
      "teamId": null,
      "private": false,
      "confidential": false,
      "status": "active",
      "createdAt": "2026-05-19T09:00:00.000Z",
      "updatedAt": "2026-05-19T09:00:00.000Z",
      "usedAt": "2026-05-19T09:00:00.000Z",
      "createdBy": "user_123",
      "updatedBy": "user_123"
    }
  ]
}

Read one project

GET /projects/:id

Returns { "success": true, "project": { ... } }. The API only returns projects owned by you or accessible through an active team membership.

Create a project

POST /projects

Request body:

{
  "name": "Customer onboarding",
  "description": "Implementation work for new customers",
  "color": "#FFB623",
  "team": "team_123_or_exact_team_name",
  "portfolio": "portfolio_123_or_exact_portfolio_name",
  "private": false,
  "confidential": false
}

name is optional. If omitted or blank, DoneThat creates a name like New Project 2026-05-19.

team and portfolio accept either an id or an exact display name you can access. Names are matched case-sensitively after trimming. Pass null or an empty string to clear those fields on update.

Field rules

FieldRules
nameOptional on create (auto-generated if omitted). Max 100 characters when set.
descriptionOptional. Max 2000 characters.
colorOptional. If set, must be exactly one of the allowed hex values below (same palette as in the app). Invalid values return { "success": false, "error": "Invalid color value" }.
team, portfolioOptional. Id or exact display name you can access; case-sensitive.
privateOptional boolean.
confidentialOptional boolean on create only. Cannot be changed on update through this API.
archivedOnly on POST /projects/:id. true archives, false unarchives.

Allowed color values

When provided, color must be exactly one of:

#FFB623, #4BC0C0, #6C63FF, #FF4590, #32D74B, #FFD166, #845EC2, #00C2FF, #FF6B6B, #00B8A9, #FF9F1C, #F9F871, #EF5DA8, #4ECDC4, #00BBF9, #FF9671, #FCBAD3, #A6E3E9, #FFCB77, #D65DB1

Response status 201:

{
  "success": true,
  "project": {
    "id": "project_123",
    "name": "Customer onboarding",
    "status": "active"
  }
}

(Other fields match the Project object above.)

Update or archive a project

POST /projects/:id

Send any subset of editable fields:

{
  "name": "Customer onboarding v2",
  "description": "",
  "color": "#32D74B",
  "team": null,
  "portfolio": null,
  "private": true,
  "archived": true
}

Notes:

  • archived: true archives the project; archived: false unarchives it.
  • An empty body returns the current project without changing it (requires projects:write, which includes read access).
  • team and portfolio can be cleared with null or an empty string.
  • confidential cannot be changed through this API.
  • Omit a field to leave it unchanged.

Response: { "success": true, "project": { ... } }.

Delete a project

DELETE /projects/:id

Not supported. The API returns 403:

{
  "success": false,
  "error": "Deleting projects is not available through the API."
}

Use archived: true on POST /projects/:id to archive instead.

Example

curl -X POST "https://api.donethat.ai/projects" \
     -H "Content-Type: application/json" \
     -H "x-api-key: YOUR_API_KEY" \
     -d '{
       "name": "Customer onboarding",
       "color": "#FFB623"
     }'

Errors

{
  "success": false,
  "error": "API key missing required scope: projects:read"
}