Skip to content
leera

For developersREST API & Webhooks · Preview

Connect your workspace. Keep the contract clear.

Build server-side integrations with scoped personal access keys, a versioned REST API, and signed event delivery. The running instance publishes its own OpenAPI reference; check it before using an operation.

The overview

How can I integrate with Leera?

Use the REST API (Preview) for scripts that read and update supported Planner and QA records, Webhooks (Preview) for signed change notifications, MCP for compatible AI clients, and CI tokens for test-run jobs. Access follows the connecting member’s permissions. Operators can disable each surface on their instance.

Choose the interface for your workflow.

REST API (Preview)

A separate versioned contract at /api/rest/v1 for supported Planner and QA resources. Use a REST-bound personal access key and the published OpenAPI schema.

Webhooks (Preview)

Workspace administrators choose events and projects, verify signed delivery, inspect attempts, rotate secrets, and redeliver retained events. Receivers must handle duplicates and out-of-order events.

MCP

Connect compatible AI clients using OAuth or an MCP-bound personal key. MCP has its own tool catalog and supports documents beyond the REST Preview.

CI tokens

Use project CI tokens for automated test-run jobs. They are distinct from personal access keys and do not grant general REST or MCP access.

Good to know

Developer questions

Is the REST API generally available?

The REST API and outbound webhooks are labelled Preview. Responses identify the Preview status. The v1 contract may change during Preview, with changes announced in the changelog. Use your running instance’s reference and test upgrades before production rollout.

Can an existing MCP token call the REST API?

Existing keys remain MCP-only. Create a key with REST selected or explicitly edit its surfaces after confirming your identity. REST accepts personal access keys bound to REST; MCP OAuth tokens and session credentials are not accepted.

Does a key bypass project permissions?

No. Scopes and selected projects narrow the member’s access. Current membership, module access, project permissions, and workspace isolation also apply. Deactivating the owner or revoking a key stops access.

Are webhook deliveries ordered or exactly once?

Neither is guaranteed. Verify each request, deduplicate by webhook-id, queue it durably, and return 2xx quickly. Use retained redelivery and incremental API sync to recover after downtime.

Are documents and attachments part of REST Preview?

Document content, attachment uploads, service accounts, and third-party OAuth REST applications are outside this Preview. MCP provides its separately documented document tools.

Build a reliable integration.

REST authentication and recovery

In Personal settings → API, create an expiring key bound to REST. Select the minimum scopes and projects your integration needs. Powerful keys require your password or an emailed confirmation code. Copy the one-time secret into your server’s secret manager.

Use the base URL shown by your instance, ending in /api/rest/v1. Send Authorization: Bearer with the personal key over HTTPS. Keep tokens out of browser code and URLs. Keys act as their owner; plan for ownership changes before a member leaves.

Follow next_cursor until has_more is false. For ticket sync use updated_since with order=updated_at:asc. The server keeps its sync_until timestamp fixed across pages and defers newer changes to the next sync. Finish all pages before saving sync_until as your next updated_since checkpoint. Subtract an overlap for long transactions and deduplicate by ID and updated_at. Numeric IDs remain stable when a project key changes.

Send a unique Idempotency-Key on create requests and reuse it for identical retries. Receipts last 24 hours. A different request with the same key returns 409. Honor Retry-After for in-flight requests and 429 responses.

Read application/problem+json errors by code. Keep X-Request-Id for diagnostics. Default per-replica limits are 120 requests and 60 writes per minute per key, and 600 per minute per workspace; operators can tune them. Inspect response headers and use bounded retries for temporary failures.

Preview responses carry X-API-Status: preview. Monitor the changelog and validate your client against the instance’s OpenAPI schema when upgrading. Generate your own client if useful; official SDKs are outside this Preview.

Webhook verification and redelivery

Keep the whsec_ secret on the receiver. Verify the original body bytes before JSON parsing. The Standard Webhooks libraries validate the signature and timestamp; use their default replay window and synchronize your receiver’s clock.

Node.js verification
import { Webhook } from 'standardwebhooks';

// rawBody is the exact request body, before JSON parsing.
const verifiedEvent = new Webhook(process.env.WEBHOOK_SECRET).verify(
  rawBody,
  {
    'webhook-id': request.headers['webhook-id'],
    'webhook-timestamp': request.headers['webhook-timestamp'],
    'webhook-signature': request.headers['webhook-signature'],
  },
);
// Persist verifiedEvent and webhook-id atomically before returning 2xx.

Adapt the request and body variables to your server framework. Return an error for verification failure.

Python verification
import os
from standardwebhooks.webhooks import Webhook

# raw_body is the exact received body as bytes.
verified_event = Webhook(os.environ['WEBHOOK_SECRET']).verify(
    raw_body,
    dict(request.headers),
)
# Deduplicate and persist verified_event before acknowledging delivery.

Adapt the request and body variables to your server framework. Return an error for verification failure.

Go verification
import (
    "os"
    standardwebhooks "github.com/standard-webhooks/standard-webhooks/libraries/go"
)

verifier, err := standardwebhooks.NewWebhook(os.Getenv("WEBHOOK_SECRET"))
if err != nil { return err }
// body is the exact request body as []byte.
if err := verifier.Verify(body, request.Header); err != nil {
    return err // Reject the request; do not process its JSON.
}
// Deduplicate by request.Header.Get("webhook-id") and persist durably.

Adapt the request and body variables to your server framework. Return an error for verification failure.

After verification, atomically record webhook-id with your work queue. Ignore IDs already processed, persist the event, and respond with 2xx promptly. Event order is not guaranteed. Retries and manual redelivery preserve the event ID and payload and use a fresh timestamp and signature.

During rotation both the current and previous secret sign deliveries for 24 hours. Update the receiver with the new secret before the overlap expires. Retain idempotency records for at least your redelivery window.

Use the endpoint delivery log to inspect attempts and redeliver failed events after repairing a receiver. Retained redelivery cannot recover events that were never emitted or are past retention; use updated_since API sync and deduplicate by resource ID and updated_at.

Events describe committed changes. Repeated writes in one transaction are coalesced into the final resource snapshot and net field changes. Project deletion does not emit child deletion events; deleting a ticket does not emit separate events for its removed comments. If data.truncated_fields lists omitted large text, fetch the resource through the API.

Library documentation: Node.js, Python, Go.