Projects API

Manage projects within your companies. Projects are containers for tasks, phases, and deliverables, organized by client and company.

Templates are a separate resource. Template projects never appear on the Projects endpoints: they are excluded from GET /api/v1/projects, and GET /api/v1/projects/{id} returns 404 Not Found for a template ID. Browse templates via the Project Templates API, and use a template by passing its ID as template_id when creating a project.

The Project Object

{
  "id": 123,
  "title": "Website Redesign",
  "code": "ACME-014",
  "description": "Complete redesign of the company website",
  "is_client": true,
  "is_internal": false,
  "client_project_type": "Process",
  "internal_project_type": "Board",
  "created_at": "2023-01-01T12:00:00.000000Z",
  "updated_at": "2023-01-01T12:00:00.000000Z",
  "client_id": 456,
  "client": {
    "id": 456,
    "title": "Acme Corporation"
  },
  "company": {
    "id": 789,
    "title": "Design Studio Inc"
  },
  "members": [
    { "id": 18, "name": "Ben Johnston" }
  ]
}

Attributes

Attribute Type Description
id integer Unique identifier for the project
title string The project's name
code string|null Optional short reference code for the project (max 32 chars; letters, numbers, spaces and . _ - /). null when not set
description string Description of the project (empty string when not set)
is_client boolean Whether the project has a client-facing space
is_internal boolean Whether the project has an internal space
client_project_type string Layout of the client space: "Process" or "Board"
internal_project_type string Layout of the internal space: "Process" or "Board"
client_id integer ID of the client this project belongs to
client object The client this project belongs to (id, title)
company object The agency company that owns the project (id, title)
members object[] Users with access to the project (id, name)

List Projects

Retrieves a list of projects the authenticated user has access to.

GET /api/v1/projects

Query Parameters

Parameter Type Description
company_id integer Filter projects by specific company ID
client_id integer Filter projects by specific client ID
title string Filter projects by title (partial match)
per_page integer Number of results per page (max 1000)

Example Request

GET /api/v1/projects?company_id=789&per_page=25
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json

Example Response

[
  {
    "id": 123,
    "title": "Website Redesign",
    "description": "Complete redesign of the company website",
    "is_client": true,
    "is_internal": false,
    "client_project_type": "Process",
    "internal_project_type": "Board",
    "created_at": "2023-01-01T12:00:00.000000Z",
    "updated_at": "2023-01-01T12:00:00.000000Z",
    "client_id": 456,
    "client": { "id": 456, "title": "Acme Corporation" },
    "company": { "id": 789, "title": "Design Studio Inc" },
    "members": [ { "id": 18, "name": "Ben Johnston" } ]
  }
]

Get a Project

Retrieves a specific project by ID.

GET /api/v1/projects/{id}

Example Request

GET /api/v1/projects/123
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json

Example Response

{
  "id": 123,
  "title": "Website Redesign",
  "code": "ACME-014",
  "description": "Complete redesign of the company website",
  "is_client": true,
  "is_internal": false,
  "client_project_type": "Process",
  "internal_project_type": "Board",
  "created_at": "2023-01-01T12:00:00.000000Z",
  "updated_at": "2023-01-01T12:00:00.000000Z",
  "client_id": 456,
  "client": { "id": 456, "title": "Acme Corporation" },
  "company": { "id": 789, "title": "Design Studio Inc" },
  "members": [ { "id": 18, "name": "Ben Johnston" } ]
}

Create a Project

Creates a new project. Can be created from scratch or from a template.

POST /api/v1/projects

Request Body

Parameter Type Required Description
title string Yes The project's name
client_id integer Yes ID of the client this project belongs to
code string No Short reference code for tracking the project in other tools (max 32 chars; letters, numbers, spaces and . _ - /)
description string No Detailed description of the project
template_id integer No ID of a template project to create this project from
is_client boolean No Whether to create a client-facing space
is_internal boolean No Whether to create an internal space
client_project_type string No Client space layout: process or todos
internal_project_type string No Internal space layout: process or todos

Example Request (From Template)

POST /api/v1/projects
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Accept: application/json

{
  "title": "Acme Website Redesign",
  "client_id": 456,
  "template_id": 789
}

Example Response

{
  "id": 124,
  "title": "Acme Website Redesign",
  "code": null,
  "description": "",
  "is_client": true,
  "is_internal": false,
  "client_project_type": "Process",
  "internal_project_type": "Board",
  "created_at": "2023-02-01T10:00:00.000000Z",
  "updated_at": "2023-02-01T10:00:00.000000Z",
  "client_id": 456,
  "client": { "id": 456, "title": "Acme Corporation" },
  "company": { "id": 789, "title": "Design Studio Inc" },
  "members": [ { "id": 18, "name": "Ben Johnston" } ]
}

Update a Project

Updates an existing project's information.

PUT /api/v1/projects/{id}

Example Request

PUT /api/v1/projects/123
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Accept: application/json

{
  "title": "Updated Website Redesign",
  "description": "Now includes a blog and careers section"
}

Accepted fields: title and description. Company members may additionally update code, client_id, is_client, is_internal, client_project_type, and internal_project_type. Client-side users are restricted to title and description; any other fields they send are ignored. Send code as an empty string or null to clear it. A project cannot be moved to a client belonging to a different company.

Example Response

{
  "id": 123,
  "title": "Updated Website Redesign",
  "code": "ACME-014",
  "description": "Now includes a blog and careers section",
  "is_client": true,
  "is_internal": false,
  "client_project_type": "Process",
  "internal_project_type": "Board",
  "created_at": "2023-01-01T12:00:00.000000Z",
  "updated_at": "2023-02-01T14:30:00.000000Z",
  "client_id": 456,
  "client": { "id": 456, "title": "Acme Corporation" },
  "company": { "id": 789, "title": "Design Studio Inc" },
  "members": [ { "id": 18, "name": "Ben Johnston" } ]
}

Delete a Project

Deletes a project. Only company members can delete projects.

DELETE /api/v1/projects/{id}

Warning: Deleting a project removes it, along with its phases and tasks, from every API response. Treat this as irreversible — a deleted project can only be recovered from within Outlign. Requires company member permissions.

Example Request

DELETE /api/v1/projects/123
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json

Example Response

204 No Content

Project Info

Every project has a Project Info page — a shared reference page (scope, key contacts, links, standing decisions) visible to both the team and the client. Content is exchanged as Markdown.

GET /api/v1/projects/{id}/project-info
PUT /api/v1/projects/{id}/project-info

The update accepts a content field (Markdown) that replaces the entire page, and requires project-settings permissions (company team members; freelancers can read but not write). Because the page is client-visible, anything written here should be client-appropriate. Attachments, form fields, and embeds in the existing page are preserved on update unless allow_removing_attachments: true is passed.

Example Response

{
  "data": {
    "id": 55,
    "project_id": 123,
    "content": "## Key contacts\n\n- Jane Smith (CEO) — jane@acme.example\n\n## Scope\n\nWebsite redesign including...",
    "updated_at": "2023-01-01T12:00:00.000000Z"
  }
}

List Project Members

Lists the people on a project — agency team members and client members — so tasks can be assigned and mentions resolved by name. Each member carries a side of "team" (agency) or "client"; role is the company role for team members and null for client members.

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

Example Request

GET /api/v1/projects/123/members
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json

Example Response

{
  "data": [
    {
      "id": 12,
      "first_name": "Alex",
      "last_name": "Rivera",
      "name": "Alex Rivera",
      "email": "alex@agency.example",
      "side": "team",
      "role": "manager"
    },
    {
      "id": 48,
      "first_name": "Sam",
      "last_name": "Chen",
      "name": "Sam Chen",
      "email": "sam@client.example",
      "side": "client",
      "role": null
    }
  ]
}

Add Project Members

Adds existing users to a project so it appears in their project list and they can be assigned tasks. Each user must already belong to your agency or to the project's client organisation — inviting brand-new people by email happens in the Outlign app. Newly added members are notified. Users who are already on the project are returned under already_members and left unchanged.

POST /api/v1/projects/{id}/members

Request Body

Field Type Required Description
user_ids array of integers Yes User IDs to add (max 50). Each must already be a member of the agency company or of the project's client

Example Request

POST /api/v1/projects/123/members
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Accept: application/json

{
  "user_ids": [12, 48]
}

Example Response

{
  "data": {
    "added": [ { "id": 48, "name": "Sam Chen" } ],
    "already_members": [12]
  }
}