Developers

API documentation

A reference for the core Trailogs resources: logs, categories, tags, channels, subject types, and subjects. Every request is scoped to a workspace and authenticated with a bearer token.

Overview

The Trailogs API is a JSON REST API served from its own subdomain, versioned under /v1.

Base URL
https://api.trailogs.com/v1

Authentication

Every request must include a personal access token in the Authorization header. Requests without a valid token, or made by a deactivated user, receive a 401 or 403 response.

Example request
curl https://api.trailogs.com/v1/workspaces/{workspace_id}/logs \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Access within a workspace is further scoped by abilities granted to your token's member (e.g. logs:read, subjects:create) and by which channels that member can access. Resources that a token cannot access are returned as 404 rather than 403, so that private resources don't reveal their existence.

Conventions

Identifiers

All resource IDs are UUID strings (e.g. 3fa85f64-5717-4562-b3fc-2c963f66afa6).

Dates

Timestamps are Unix time — integer seconds since the epoch — for both requests and responses (e.g. 1690000000).

Envelope

Successful responses wrap their payload in a top-level data key. Deletes return 204 No Content with an empty body.

Pagination

Logs use cursor-based pagination and Subjects use page-based pagination. Both accept a limit parameter (default 15, max 100). Categories, tags, channels, and subject types are returned unpaginated.

Cursor pagination (logs)
{
  "data": [ ... ],
  "links": {
    "prev": null,
    "next": "https://api.trailogs.com/v1/workspaces/{id}/logs?cursor=eyJ..."
  },
  "meta": {
    "per_page": 15,
    "next_cursor": "eyJ...",
    "prev_cursor": null
  }
}
Page pagination (subjects)
{
  "data": [ ... ],
  "links": { "first": "...", "last": "...", "prev": null, "next": "..." },
  "meta": {
    "current_page": 1,
    "last_page": 4,
    "per_page": 15,
    "total": 52
  }
}

Errors

Errors are returned as JSON with a message field. Validation failures additionally include a field-level errors map. Sending a field the endpoint doesn't accept is itself a validation error.

422 Unprocessable Content
{
  "message": "The given data was invalid.",
  "errors": {
    "name": ["The name has already been taken."]
  }
}
404 Not Found
{
  "message": "Not found."
}
StatusMeaning
401Missing or invalid bearer token.
403Authenticated, but not permitted to perform this action.
404Resource doesn't exist, or you don't have access to it.
422Validation failed, or a business rule (e.g. a name conflict) was violated.
204Request succeeded and there is no content to return (deletes).

Logs

A log is a single recorded event: a title, optional content, a category, an owner, and the point in time it occurred. Logs belong to a channel and can reference tags and subjects.

GET/workspaces/{workspace_id}/logs

List logs

Requires ability logs:read

Returns logs in channels you can access, newest first (ordered by occurred_at descending).

Query parameters

FieldTypeRequiredDescription
searchstringOptionalMatches against the log's title or content.
category_idsuuid[]OptionalFilter to one or more categories.
tag_idsuuid[]OptionalFilter to logs having any of these tags.
subject_idsuuid[]OptionalFilter to logs referencing any of these subjects.
owner_member_idsuuid[]OptionalFilter to logs owned by these workspace members.
fromtimestampOptionalOnly logs that occurred at or after this time.
totimestampOptionalOnly logs that occurred at or before this time.
cursorstringOptionalOpaque cursor from a previous response, for the next page.
limitintegerOptionalPage size, 1–100. Defaults to 15.
GET/logs/{log_id}

Get a log

Requires ability logs:read

Response · 200
{
  "data": {
    "id": "log_uuid",
    "title": "Deployed payments-service v2.3.1",
    "content": "Rolled out with no downtime.",
    "occurred_at": 1690000000,
    "category": { "id": "uuid", "name": "Deployment", "color": "blue" },
    "creator": { "id": "member_uuid", "user": { "id": "uuid", "name": "Ana Perić", "email": "ana@example.com" } },
    "owner": { "id": "member_uuid", "user": { "id": "uuid", "name": "Ana Perić", "email": "ana@example.com" } },
    "participants": [],
    "subjects": [ { "id": "uuid", "name": "payments-service", "type": { "id": "uuid", "name": "Service", "icon": "server", "color": "violet" } } ],
    "tags": [ { "id": "uuid", "name": "release", "color": "green" } ],
    "channel": { "id": "uuid", "name": "deployments" },
    "created_at": 1690000000,
    "updated_at": 1690000000
  }
}
POST/workspaces/{workspace_id}/logs

Create a log

Requires ability logs:create

Body parameters

FieldTypeRequiredDescription
channel_iduuidRequiredChannel the log is posted in. You must have access to it.
titlestringRequiredUp to 500 characters.
contentstringOptionalFree-form body text.
occurred_attimestampOptionalWhen the event happened. Defaults to now.
category_iduuidOptionalMust be visible in the log's channel.
owner_member_iduuidRequiredAn active, human workspace member.
participant_idsuuid[]OptionalOther members involved in the event.
tag_idsuuid[]OptionalMust be global or scoped to the log's channel.
subject_idsuuid[]OptionalSubjects this log relates to. Cannot be archived.
Example request
curl -X POST https://api.trailogs.com/v1/workspaces/{workspace_id}/logs \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "channel_id": "channel_uuid",
    "title": "Deployed payments-service v2.3.1",
    "category_id": "category_uuid",
    "owner_member_id": "member_uuid",
    "tag_ids": ["tag_uuid"],
    "subject_ids": ["subject_uuid"]
  }'

Returns 201 Created with the log on success. Fails with 422 if the channel is archived, the workspace's log limit has been reached, or the category/tags/subjects aren't valid for the target channel.

PATCH/logs/{log_id}

Update a log

Requires ability logs:update

Partial update — send only the fields you want to change.

Body parameters

FieldTypeRequiredDescription
titlestringOptionalUp to 500 characters.
contentstringOptionalFree-form body text.
occurred_attimestampOptionalWhen the event happened.
category_iduuidOptionalCannot be an archived category unless unchanged.
owner_member_iduuidOptionalAn active, human workspace member.
participant_idsuuid[]OptionalReplaces the full participant list.
tag_idsuuid[]OptionalReplaces the full tag list.
subject_idsuuid[]OptionalReplaces the full subject list. New entries cannot be archived.

Returns 200 with the updated log. Fails with 422 if the log's channel is archived.

DELETE/logs/{log_id}

Delete a log

Requires ability logs:delete

Permanently deletes the log. Returns 204 No Content. Fails with 422 if the log's channel is archived.

Categories

Categories classify logs. A category is either workspace-global or scoped to a single channel.

GET/workspaces/{workspace_id}/categories

List categories

Requires ability categories:read

Returns non-archived categories: workspace-global ones plus any scoped to channels you can access, ordered by name.

Response · 200
{
  "data": [
    {
      "id": "uuid",
      "channel": null,
      "name": "Deployment",
      "description": "Releases and rollouts",
      "color": "blue",
      "logs_count": 128,
      "archived_at": null,
      "created_at": 1690000000,
      "updated_at": 1690000000
    }
  ]
}
GET/categories/{category_id}

Get a category

Requires ability categories:read

Returns a single category with its logs_count. Returns 404 if the category is scoped to a channel you cannot access.

Tags

Tags are freeform labels applied to logs. Like categories, a tag is either workspace-global or scoped to a channel.

GET/workspaces/{workspace_id}/tags

List tags

Requires ability tags:read

Returns workspace-global tags plus tags scoped to channels you can access, ordered by name.

Response · 200
{
  "data": [
    {
      "id": "uuid",
      "channel": { "id": "uuid", "name": "deployments" },
      "name": "release",
      "color": "green",
      "logs_count": 47,
      "created_at": 1690000000,
      "updated_at": 1690000000
    }
  ]
}
GET/tags/{tag_id}

Get a tag

Requires ability tags:read

Returns 404 if the tag is scoped to a channel you cannot access.

Channels

Channels group related logs, similar to a chat channel. They can be public or private, and one channel per workspace is marked as the default.

GET/workspaces/{workspace_id}/channels

List channels

Requires ability channels:read

Returns non-archived channels you can access, with the default channel first, then alphabetically.

Response · 200
{
  "data": [
    {
      "id": "uuid",
      "name": "deployments",
      "description": "Release and deployment activity",
      "is_private": false,
      "is_default": false,
      "archived_at": null,
      "created_at": 1690000000,
      "updated_at": 1690000000
    }
  ]
}
GET/workspaces/{workspace_id}/channels/archived

List archived channels

Requires ability channels:read

Same shape as above, restricted to archived channels you can access.

Subject types

Subject types define the kind of thing a subject represents — e.g. User, Service, or Customer — and how it's displayed (icon and color).

GET/workspaces/{workspace_id}/subject-types

List subject types

Requires ability subject-types:read

Response · 200
{
  "data": [
    {
      "id": "uuid",
      "name": "Service",
      "icon": "server",
      "color": "violet",
      "subjects_count": 12,
      "created_at": 1690000000,
      "updated_at": 1690000000
    }
  ]
}

icon is one of:user | contact | building2 | handshake | briefcase_business | folder_kanban | package | server | database | app_window | bot | code2 | key_round | map_pin | globe2 | car | file_text | ticket | message_square | workflow | target | lightbulb | crown | warehouse | factory | shapes

GET/subject-types/{subject_type_id}

Get a subject type

Requires ability subject-types:read

Subjects

A subject is a specific entity that logs can reference — a particular service, customer, or user — typed by a subject type.

GET/workspaces/{workspace_id}/subjects

List subjects

Requires ability subjects:read

Returns non-archived subjects, most recently updated first.

Query parameters

FieldTypeRequiredDescription
searchstringOptionalMatches against the subject name or ID.
pageintegerOptionalPage number, starting at 1.
limitintegerOptionalPage size, 1–100. Defaults to 15.
Response · 200
{
  "data": [
    {
      "id": "uuid",
      "type": { "id": "uuid", "name": "Service", "icon": "server", "color": "violet" },
      "name": "payments-service",
      "logs_count": 34,
      "archived_at": null,
      "created_at": 1690000000,
      "updated_at": 1690000000
    }
  ],
  "meta": { "current_page": 1, "last_page": 1, "per_page": 15, "total": 1 }
}
GET/subjects/{subject_id}

Get a subject

Requires ability subjects:read

POST/workspaces/{workspace_id}/subjects

Create a subject

Requires ability subjects:create

Body parameters

FieldTypeRequiredDescription
type_iduuidRequiredA subject type in this workspace.
namestringRequiredDisplay name for the subject.
Example request
curl -X POST https://api.trailogs.com/v1/workspaces/{workspace_id}/subjects \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type_id": "subject_type_uuid",
    "name": "payments-service"
  }'
PATCH/subjects/{subject_id}

Update a subject

Requires ability subjects:update

Body parameters

FieldTypeRequiredDescription
namestringOptionalDisplay name for the subject.

type_id cannot be changed after creation. Fails with 422 if the subject is archived.

DELETE/subjects/{subject_id}

Delete a subject

Requires ability subjects:delete

Returns 204 No Content. Fails with 422 if the subject is still referenced by any logs — remove those references first.

Category, tag, and subject-type colors are one of:gray | red | orange | amber | yellow | lime | green | emerald | teal | cyan | sky | blue | indigo | violet | purple | pink