Guia para desenvolvedores

Desenvolva com o Trama

A API do Trama é a API JSON em que o app web roda: workspaces, quadros, tarefas, comentários e integrações. Este guia mostra como se autenticar, as partes de que a maioria das integrações precisa e como GitHub, GitLab e GRUPIM se conectam. Todas as operações estão na especificação OpenAPI.

Nesta página

Início rápido

O jeito mais rápido de começar é com um token pessoal. Ele age como você, em tudo o que você acessa no app, então não o deixe em código que você compartilha.

  1. Crie um token pessoal

    Em ConfiguraçõesAPI e MCP, escolha Criar token e copie o token. Ele aparece uma única vez.
  2. Separe a chave e o segredo

    O token é a sua chave de API e o seu segredo unidos por um ponto. Envie a parte antes do primeiro ponto como X-Api-Key e o resto como X-Api-Secret.
  3. Chame a API

    A URL base é https://api.ontrama.com.
Terminal
# Seu token pessoal é KEY.SECRET: separe-o no primeiro ponto
TOKEN="YOUR_PERSONAL_TOKEN"
export TRAMA_KEY="${TOKEN%%.*}"
export TRAMA_SECRET="${TOKEN#*.}"

# Quem sou eu?
curl https://api.ontrama.com/me \
  -H "X-Api-Key: $TRAMA_KEY" -H "X-Api-Secret: $TRAMA_SECRET"

# Os quadros que eu vejo
curl https://api.ontrama.com/boards \
  -H "X-Api-Key: $TRAMA_KEY" -H "X-Api-Secret: $TRAMA_SECRET"

Autenticação

Todos os endpoints, exceto o login, o health check e o servidor OAuth, exigem uma de três credenciais. Todas agem como o mesmo usuário e alcançam os mesmos quadros; o que muda é quanto tempo duram e o que podem fazer.

CredencialEnvie comoValidadePode fazer
Token pessoalX-Api-Key + X-Api-SecretAté você substituí-loTudo o que você pode fazer no app
Access token OAuthAuthorization: Bearer lxt_at_…7 dias, depois é renovadoSó as operações que os scopes dele permitem
JWT do login por e-mailAuthorization: Bearer <jwt>24 horasTudo o que você pode fazer no app

Token pessoal

Scripts e integrações do lado do servidor devem usar um token pessoal. Crie ou substitua o seu em ConfiguraçõesAPI e MCP. O mesmo token também funciona como Bearer token no servidor MCP, que faz a separação para você; a API REST só aceita os dois headers.

Aparece uma vez, vale até ser substituído

O Trama guarda só uma impressão digital do segredo, então um token perdido não pode ser mostrado de novo: substitua-o. Ao substituir, o antigo para de funcionar na hora, para todo script e cliente MCP que o usa. As conexões OAuth não são afetadas.

Quando X-Api-Key está presente, ela é a única credencial que a API considera: um par errado responde 401 mesmo que um header Authorization válido também seja enviado.

Login por e-mail (JWT)

O app web faz login com um código enviado por e-mail. Cada etapa é um POST /login: primeiro com o endereço, depois com o endereço e o código.

Terminal
# 1. Peça um código (aqui, uma resposta 400 quer dizer que o e-mail foi enviado)
curl -X POST https://api.ontrama.com/login \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com"}'

# 2. Troque o código de 6 dígitos por um JWT (201: {"user": {…}, "token": "…"})
curl -X POST https://api.ontrama.com/login \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "otp": "123456"}'

# 3. Use o JWT
curl https://api.ontrama.com/me -H "Authorization: Bearer YOUR_JWT"
  • Os códigos têm 6 dígitos, valem por 10 minutos e só funcionam uma vez. Só o código mais recente vale; cinco tentativas erradas o bloqueiam.
  • O login é limitado a 30 requisições por IP e 10 por endereço a cada 15 minutos; acima disso, a resposta é 429 com Retry-After.
  • POST /logout encerra todos os JWTs emitidos para a conta até então, em todos os dispositivos. Os tokens pessoais continuam funcionando.

OAuth 2.1

O Trama é um servidor de autorização OAuth 2.1, feito para clientes MCP: registro dinâmico de clientes (RFC 7591), metadados do servidor (RFC 8414), metadados do recurso protegido (RFC 9728) e o fluxo authorization code com PKCE (S256). Os clientes são públicos (token_endpoint_auth_method: none). Access tokens (lxt_at_…) duram 7 dias; refresh tokens (lxt_rt_…) são rotacionados a cada uso. Um cliente MCP faz tudo isso sozinho; o guia de MCP mostra o fluxo passo a passo.

EndpointURL
Metadados do servidorGEThttps://api.ontrama.com/.well-known/oauth-authorization-server
Registrar um clientePOSThttps://api.ontrama.com/oauth2/register
Consentimento (no navegador)https://ontrama.com/oauth2/authorize
TokenPOSThttps://api.ontrama.com/oauth2/token
RevogarPOSThttps://api.ontrama.com/oauth2/revoke

São cinco scopes. Um cliente que não pede nenhum recebe todos, os dois de invoices só se você administra um workspace, e você os vê na página de consentimento.

ScopePermite
boards.readVer quadros, tarefas, marcos, etiquetas e documentos que você já acessa, e buscar neles.
boards.writeCriar e alterar tarefas (detalhes, responsáveis, etiquetas, marcos, subtarefas, relações, checklists, links de PR, cronômetro, lançamentos de tempo) e documentos, no que você pode editar.
comments.writeComentar e responder em tarefas e documentos; resolver conversas em documentos.
invoices.readLer invoices, clientes e o tempo registrado de um workspace (admins).
invoices.writeCriar e editar invoices, marcar como enviadas, registrar pagamentos (admins).

Tokens OAuth só alcançam o que o MCP usa

Na API REST, um token OAuth só funciona nas operações abaixo, e só com o scope correspondente. Qualquer outra responde 403 com {"error": "missing_scope"}. Scopes nunca ampliam o seu papel: um token só edita quadros que você pode editar, e os scopes de invoices só alcançam workspaces que você administra.

OperaçãoScope
GET/boardsboards.read
GET/boards/{id}boards.read
GET/boards/{id}/searchboards.read
GET/searchboards.read
GET/boards/{board_id}/tasks/{id}boards.read
POST/boards/{board_id}/tasksboards.write
PUT/boards/{board_id}/tasks/{id}boards.write
PUT…/tasks/{id}/move, /task_users, /taggingsboards.write
PUT…/tasks/{id}/stopwatchboards.write
POST · DELETE…/tasks/{task_id}/relationsboards.write
POST…/tasks/{task_id}/sub_issues, /pull_requestsboards.write
GET · POST · PUT…/tasks/{task_id}/task_checklists, /task_check_itemsboards.read · boards.write
GET · POST · PUT/boards/{board_id}/milestonesboards.read · boards.write
GET · POST/boards/{board_id}/tagsboards.read · boards.write
POST · PUT…/tasks/{task_id}/commentscomments.write
GET/me, /me/tasks, /workspacesboards.read
GET/workspaces/{id}/workspace_documents, …/{id}, …/mentionablesboards.read
POST · PATCH/workspaces/{id}/workspace_documents, …/archive, /restore, /upload_presignboards.write
GET…/workspace_documents/{id}/commentsboards.read
POST · PUT · DELETE…/workspace_documents/{id}/comments, /resolve, /unresolvecomments.write
GET/tasks/{id}, /workspace_documents/{id}boards.read
GET…/tasks/{task_id}/time_entriesboards.read
POST · PUT · DELETE…/tasks/{task_id}/time_entriesboards.write
GET/workspaces/{id}/invoices, …/{id}, /invoice_clients, /time_entriesinvoices.read
POST · PUT/workspaces/{id}/invoicesinvoices.write

Excluir marcos, etiquetas, checklists e links de PR, excluir comentários de tarefas, publicar documentos e excluir ou importar invoices continuam sendo feitos por pessoas, no app.

Você vê e revoga os apps que conectou em ConfiguraçõesApps conectados.

Convenções

  • URL base https://api.ontrama.com. Requisições e respostas são JSON; os caminhos funcionam com ou sem o sufixo .json.
  • Tarefas têm um id numérico e uma chave como ACME-42. Rotas que recebem {id} aceitam qualquer um dos dois; rotas aninhadas ({task_id}) recebem o id numérico.
  • Erros: 401 credenciais ausentes ou inválidas, 403 o seu papel não permite, 404 não encontrado ou não visível para você, 422 validação ({"field": ["message"]} ou {"error": "…"}), 429 limite de requisições atingido, com Retry-After.
  • Limites de requisições: login (acima), registro de clientes OAuth 20 por IP por hora, presigns de upload 60 por usuário por hora, convites 30 por usuário por hora.
  • A especificação em /openapi.yaml é o contrato. A referência da API mostra essa especificação com um console para testar requisições.

Endpoints

Os principais recursos, num relance. As rotas de um quadro começam em /boards/{board_id}.

ÁreaRotas
Conta
GET · PUT/meGET/me/tasksGET/me/api_credentialsGET/me/oauth_clients

/me/tasks lista as tarefas abertas atribuídas a você, em todos os quadros.

Busca
GET/search

Passe q, e board_id para buscar em um só quadro. Cobre quadros, tarefas e comentários que você vê; no máximo 50 resultados.

Notificações
GET/notificationsGET/notifications/unread_countPUT/notifications/mark_all_readGET · PUT/notification_preferences
Workspaces
GET · POST/workspacesGET · PUT/workspaces/{id}…/workspace_users…/workspace_documents…/workspace_activities…/integrations…/invoices
Quadros
GET · POST/boardsGET · PUT · DELETE/boards/{id}PUT/boards/{id}/archivePOST/boards/{id}/share

GET /boards/{id} é o kanban inteiro: colunas, cartões e modelos. Com ?compact=1 vêm sem descrições, atividade e itens de checklist (os cartões trazem contagens).

Partes do quadro
…/board_columns…/tags…/milestones…/board_users
Tarefas
POST/boards/{board_id}/tasksGET · PUT · DELETE…/tasks/{id}PUT…/movePUT…/task_usersPUT…/taggingsPUT…/stopwatch
Dentro de uma tarefa
…/comments…/task_checklists…/task_check_items…/relations…/sub_issues…/pull_requests…/attachments
Terminal
# Crie uma tarefa no fim de uma coluna
curl https://api.ontrama.com/boards/41/tasks \
  -H "X-Api-Key: $TRAMA_KEY" -H "X-Api-Secret: $TRAMA_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"task": {"board_column_id": 310, "name": "Write the release notes",
                "priority": "priority_high"}}'

# Abra uma tarefa pela chave
curl https://api.ontrama.com/boards/41/tasks/ACME-42 \
  -H "X-Api-Key: $TRAMA_KEY" -H "X-Api-Secret: $TRAMA_SECRET"

# Mova-a para outra coluna, logo depois do cartão 7090
curl -X PUT https://api.ontrama.com/boards/41/tasks/ACME-42/move \
  -H "X-Api-Key: $TRAMA_KEY" -H "X-Api-Secret: $TRAMA_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"to_board_id": 41, "to_column_id": 312, "insert_after_task_id": 7090}'

# Comente (o corpo é HTML)
curl https://api.ontrama.com/boards/41/tasks/7104/comments \
  -H "X-Api-Key: $TRAMA_KEY" -H "X-Api-Secret: $TRAMA_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"body": "<p>Shipped in 2.4</p>"}'

Conceitos

Chaves de tarefa

Toda tarefa recebe uma chave formada pelo prefixo do workspace e um número sequencial, como ACME-42. A chave não muda quando o cartão passa por outras colunas e quadros do workspace; mover a tarefa para outro workspace dá a ela uma chave nova. Citar uma chave em uma descrição ou em um comentário relaciona as duas tarefas, quando você pode editar o outro quadro.

  • Ordem. Os cartões de uma coluna são ordenados por um sort_key fracionário. Cartões novos e movidos vão para o fim, a não ser que você passe insert_after_task_id.
  • Prioridade. priority_none, priority_low, priority_medium, priority_high ou priority_urgent. Qualquer outro valor é um 422.
  • Datas e marcos. start_at e due_at (o início não pode ser depois do prazo), e um milestone_id opcional de /boards/{board_id}/milestones, do mesmo quadro. Eles alimentam a visão de planejamento do quadro.

Subtarefas e relações

Uma tarefa pode ter uma tarefa-mãe (parent_id): do mesmo workspace, até 8 níveis de profundidade, sem ciclos e sem modelos. Crie subtarefas com POST …/tasks/{task_id}/sub_issues, enviando name, uma lista de names ou existing_task_id para adotar uma tarefa que já existe. Reordene-as com PUT …/tasks/{id}/reorder_sub_issues.

As relações são related, blocks, blocked_by e duplicate, criadas com POST …/tasks/{task_id}/relations. Quando uma tarefa que bloqueia outras é concluída, os links blocks dela viram related. A outra tarefa precisa estar em um quadro que você pode editar.

Terminal
# Divida uma tarefa em subtarefas
curl https://api.ontrama.com/boards/41/tasks/7104/sub_issues \
  -H "X-Api-Key: $TRAMA_KEY" -H "X-Api-Secret: $TRAMA_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"names": ["Draft the copy", "Review with legal"]}'

# Marque-a como bloqueada por outra tarefa (id ou chave)
curl https://api.ontrama.com/boards/41/tasks/7104/relations \
  -H "X-Api-Key: $TRAMA_KEY" -H "X-Api-Secret: $TRAMA_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"related_task_id": "ACME-7", "relation_type": "blocked_by"}'

Modelos

Uma tarefa com is_template: true fica fora das colunas e aparece em templates no payload do quadro; ela não tem chave. Crie uma tarefa a partir dela com template_id em POST /boards/{board_id}/tasks: nome, descrição, prioridade, etiquetas e checklists são copiados (com os itens desmarcados). Responsáveis, datas, comentários e anexos não são.

Quem vê o quê

  • Você vê um quadro se é membro dele, admin do workspace dele, membro do workspace quando o quadro é visível para o workspace, ou se simplesmente está logado quando o quadro é público (por link). Tudo o que está dentro de um quadro que você vê pode ser lido.
  • Editar exige o papel de membro, admin ou dono no quadro, ou ser admin do workspace. Gerenciar o quadro (membros, compartilhamento, visibilidade, arquivar, excluir) exige admin ou dono.
  • Um quadro que você não vê responde 404, não 403, para não revelar que ele existe.
  • As invoices de um workspace (…/invoices) são só para os admins dele; qualquer outra pessoa recebe 404. Elas aceitam o seu token pessoal, um JWT ou um token OAuth com invoices.read / invoices.write.

Tempo real

Quadros e notificações se atualizam ao vivo via ActionCable em wss://api.ontrama.com/cable. O socket se autentica só com um JWT, em ?token= ou em um header Bearer; tokens pessoais e tokens OAuth não são aceitos ali.

  • BoardChannel com um board_id envia o quadro inteiro depois de uma mudança, ou uma mensagem curta task_reordered quando só a posição de um cartão mudou. Com compact: true vem o quadro compacto (como ?compact=1). Assinar um quadro que você não vê é recusado.
  • NotificationChannel envia mensagens new_notification para o usuário logado.
board.js
import { createConsumer } from "@rails/actioncable";

const cable = createConsumer(`wss://api.ontrama.com/cable?token=${jwt}`);

cable.subscriptions.create(
  { channel: "BoardChannel", board_id: 41 },
  {
    received(data) {
      const message = JSON.parse(data);
      // O quadro inteiro (no mesmo formato de GET /boards/41) ou
      // { type: "task_reordered", task_id, board_column_id, sort_key }
    },
  },
);

GitHub e GitLab

Vincule pull requests e merge requests a tarefas e deixe que eles movam os cartões conforme avançam. Uma tarefa mostra cada PR vinculado com o status, o estado da revisão e o resultado do CI.

  1. Cole um link (funciona em qualquer lugar)

    Cole a URL de um pull request do github.com ou de um merge request do gitlab.com em qualquer tarefa. Não há nada para configurar; o badge se atualiza quando o workspace estiver conectado. Pela API, é POST …/tasks/{task_id}/pull_requests.
  2. Conecte o workspace

    Um admin do workspace abre Configurações do workspaceIntegrações e conecta o GitHub (instala o GitHub App do Trama nos repositórios que você escolher) ou o GitLab (autorize e depois ative os projetos que quer acompanhar; ativar um projeto adiciona o webhook de merge requests dele). Os repositórios do GitHub começam ativados, e os projetos do GitLab, desativados.
  3. Cite as chaves

    Quando um pull request em um repositório conectado cita uma chave como ACME-42 no título, na descrição ou no nome do branch, o Trama o vincula a essa tarefa. Um PR pode ser vinculado a várias tarefas.
  4. Escolha as colunas de revisão e de concluídas

    No quadro, abra o menu de uma coluna e escolha Usar esta coluna como…Em revisão, e faça o mesmo para Concluído.
Quando o pull request…O cartão…
É aberto ou reaberto (rascunhos também)Vai para a coluna Em revisão
É mergeadoVai para a coluna Concluído, o que também desbloqueia as tarefas que ele bloqueava
É fechado sem mergeFica onde está
Recebe uma revisão ou um resultado de CIContinua na coluna; o badge mostra aprovado / alterações solicitadas e o último check

Os cartões só se movem quando o status muda, não a cada push, e só quando o quadro tem essa coluna definida. As movimentações são feitas em nome do admin que conectou a integração, que precisa ter permissão de edição no quadro.

Terminal
curl https://api.ontrama.com/boards/41/tasks/7104/pull_requests \
  -H "X-Api-Key: $TRAMA_KEY" -H "X-Api-Secret: $TRAMA_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://github.com/acme/website/pull/99"}'

No chat também

Conecte um servidor GRUPIM para publicar atualizações de tarefas em um canal e criar tarefas com slash commands. Veja o guia do GRUPIM.

Próximos passos

Usa um agente de IA? O servidor MCP oferece ao Claude, ao Cursor e a outros clientes a mesma API em forma de ferramentas, com login por OAuth. Sentiu falta de algum endpoint neste guia? A especificação tem todos.