Consultainer Docs

Endpoints

Clients

List and create clients, and list bookings

List clients

GET /api/v1/clients

Any role. Returns every client in the organization, sorted by name, draft clients included. Each has "draft": true when its status is LEAD (someone who booked through Cal.com or Calendly and isn't a client yet).

statusstringquery

ACTIVE, INACTIVE or LEAD to list only those. Anything else answers 422.

shareToken (the secret in the client's all-projects client link, or null) is only included for owner and admin keys. A member's key gets each client without it, here and when creating a client.

curl https://<your-instance>/api/v1/clients \
  -H "Authorization: Bearer ch_live_..."
{
  "clients": [
    {
      "id": "cm9...",
      "name": "Fintra Labs",
      "email": "hello@fintralabs.com",
      "phone": null,
      "address": null,
      "billingEmail": null,
      "paymentTerms": null,
      "status": "ACTIVE",
      "draft": false,
      "createdAt": "2026-08-01T14:02:11.000Z",
      "...": "..."
    }
  ]
}

Create a client

POST /api/v1/clients

Any role. Returns 201 with { "client": { ... } }.

namestringrequired

Up to 200 characters.

emailstring

General contact email. Must be a valid address.

phonestring
Up to 50 characters.
addressstring
Up to 500 characters.
descriptionstring
Up to 2,000 characters.
websitestring

Up to 300 characters. Its icon becomes the client's logo shortly after.

requireClockTimesbooleandefault: false

Time on this client's projects must have a start and end time.

invoiceTimeDetailbooleandefault: false

The client's invoices get a timesheet page, unless an invoice turns it off.

attachInvoicePdfbooleandefault: false

Invoice emails and reminders to this client attach the PDF as well as the link.

statusstringdefault: ACTIVE

ACTIVE or INACTIVE. LEAD answers 422: draft clients only come from bookings.

Only these fields are saved; anything else in the body is ignored. Set the billing email and address, and payment terms in the app or with the MCP update_client tool, and payment methods, invoice reminders and an uploaded logo in the app.

curl -X POST https://<your-instance>/api/v1/clients \
  -H "Authorization: Bearer ch_live_..." \
  -H "Content-Type: application/json" \
  -d '{"name": "Fintra Labs", "email": "hello@fintralabs.com"}'

Errors: 422 with field errors, for example { "error": { "name": ["Name is required"] } } or { "error": { "email": ["Enter a valid email"] } }.

List signed agreements for a client

GET /api/v1/clients/{id}/agreements

Any role. Returns the client's signed agreements (pulled from DocuSign, Documenso or Ironclad), newest signature first: client-wide ones, plus those linked to its projects. Agreements on a confidential project are only included if the key's user can see that project. Agreements that haven't been linked to a client yet aren't returned.

projectIdstringquery

Only that project's agreements.

curl https://<your-instance>/api/v1/clients/cm9.../agreements \
  -H "Authorization: Bearer ch_live_..."
{
  "agreements": [
    {
      "id": "cmv...",
      "provider": "DOCUSIGN",
      "title": "Fintra Labs MSA",
      "status": "completed",
      "signedAt": "2026-03-01T17:04:12.697Z",
      "signers": [{ "name": "Dana Ortiz", "email": "dana@fintralabs.com" }],
      "projectId": null,
      "projectName": null,
      "url": "https://app.docusign.com/documents/details/93be49ab-...",
      "hasSignedCopy": true
    }
  ]
}

url opens the agreement in the provider (the person needs access there). The signed copy itself is only downloadable in the app.

Errors: 404 { "error": "Client not found." } for a client in another organization or that doesn't exist.

GET /api/v1/clients/{id}/vault-links

Any role. Returns the client's credential links — pointers to items in 1Password, Bitwarden or another password manager — sorted by label: client-wide ones, plus those on its projects. Links on a confidential project are only included if the key's user can see that project. Consultainer never stores the secrets, so none are returned; url opens the item in the password manager, which decides whether the person can see it. There's no API to add or change links: owners and admins do that on the client or project page.

projectIdstringquery

Only that project's links (not the client-wide ones).

curl https://<your-instance>/api/v1/clients/cm9.../vault-links \
  -H "Authorization: Bearer ch_live_..."
{
  "vaultLinks": [
    {
      "id": "cmw...",
      "label": "Client AWS root",
      "note": "Break-glass only.",
      "url": "https://start.1password.com/open/i?a=...&v=...&i=...&h=acme.1password.com",
      "provider": "ONEPASSWORD",
      "providerName": "1Password",
      "itemKind": "login",
      "projectId": null,
      "projectName": null,
      "createdAt": "2026-10-14T15:02:11.204Z",
      "updatedAt": "2026-10-14T15:02:11.204Z"
    }
  ]
}

provider is one of ONEPASSWORD, BITWARDEN, KEEPER, DASHLANE, LASTPASS, PROTON_PASS or OTHER. itemKind is login, ssh_key, api_key, document, other or null.

Errors: 404 { "error": "Client not found." } for a client in another organization or that doesn't exist; 404 { "error": "Project not found." } for a projectId that isn't this client's or that the key's user can't see.

List bookings

GET /api/v1/bookings

Meetings booked through Cal.com or Calendly, sorted by start time (up to 500). Owner and admin keys get every booking in the organization; a member's key gets the ones that member hosts.

fromstringquery
ISO date: bookings starting on or after.
tostringquery
ISO date: bookings starting before.
clientIdstringquery
Only this client's bookings.
statusstringquery

SCHEDULED, CANCELLED, RESCHEDULED (moved; the new time is its own booking) or NO_SHOW.

curl "https://<your-instance>/api/v1/bookings?from=2026-10-01&status=SCHEDULED" \
  -H "Authorization: Bearer ch_live_..."
{
  "bookings": [
    {
      "id": "cmv...",
      "provider": "CALCOM",
      "title": "Intro call between Sam and Jane Doe",
      "eventType": "Intro call",
      "startAt": "2026-10-14T17:00:00.000Z",
      "endAt": "2026-10-14T17:30:00.000Z",
      "status": "SCHEDULED",
      "invitee": { "name": "Jane Doe", "email": "jane@globex.com", "phone": null, "timeZone": "Europe/Berlin" },
      "client": { "id": "cmv...", "name": "Globex", "draft": true },
      "joinUrl": "https://app.cal.com/video/...",
      "location": null,
      "answers": [{ "question": "What do you need?", "answer": "A new website" }]
    }
  ]
}

Errors: 422 with the field's message for a from/to that isn't a date or an unknown status.