Skip to main content
The LithoBlocks API lets you manage templates, entities, and organizations programmatically with scope-based authorization. Use it to create and update templates, compile messages, manage entities, and administer your organization. The API supports both compile (get JSON blocks and send from your own system) and send (LithoBlocks posts via its Slack app with full platform features); see Compile vs send for when to use which.

Choose an environment

Use the API URL for your account’s environment; see Environments and availability. Examples use the production API. Production and preview keys, templates, and Slack connections are separate.

API paths and JSON

Documented routes use the /v1 prefix (for example GET /v1/templates, POST /v1/templates/send). New integrations should use these URLs. Older clients may still call the same operations without /v1 (for example GET /templates); those URLs remain supported for backward compatibility but are not listed in the OpenAPI reference. Request and response bodies in the reference use snake_case keys (for example template_id, created_at). During a deprecation window, many inputs still accept legacy camelCase keys (for example templateId). Prefer snake_case for new code. Compile and send use fixed paths with the template id in the JSON body, not in the URL path: POST /v1/templates/compile and POST /v1/templates/send with template_id and data (see each operation in the sidebar for full schemas, including send destinations such as channel_id).

Authentication

All endpoints use LithoBlocks API keys with Bearer authentication.

Getting an API key

  1. Log into your LithoBlocks organization dashboard
  2. Go to Integrations → API Keys
  3. Create an API key and select the scopes you need
  4. Copy the key (it is shown only once)

Using your API key

Send the key in the Authorization header:

Scopes and roles

Scopes are bounded by your organization role. See API keys and scopes for the complete role matrix, including queues, schedules, destinations, interactions, and modals. Every endpoint’s reference page names the scope it requires, and the API enforces exactly that: a key without it receives 403 with the missing scope named in required_scopes. When creating an API key, you can only select scopes your role allows. Use the minimum scopes needed for your use case.

Errors

Every error response is one JSON object with at least three fields: Some errors add more (details, required_scopes, and so on); the reference page for each endpoint shows them. A request that fails validation returns 422 with code: "validation_failed" and the individual issues under error.issues. You can send your own X-Request-Id header (letters, digits, ., _, -, up to 128 characters) and it is echoed back on the response and used as request_id, so your logs and ours line up.

Pagination

Most resource list endpoints accept limit (1–100, default 20) and offset, and return items under data. Some established endpoints also retain their original collection key (templates, versions, logs, results) for compatibility. Check the endpoint schema. The pagination object carries offset, limit and total; older endpoints may also return these values at the top level.

Authoring templates

Templates and versions can be written over the API, which is how an AI agent or a template-as-code workflow maintains them. Every write goes through the same gate the platform uses:
  1. POST /v1/templates/validate is a dry run: send blocks (and optionally sample_data) and get back the blocks as they would be stored, the derived request_format, and either the Slack output or the engine’s errors. Nothing is saved and no credits are spent. Iterate here until valid is true.
  2. POST /v1/templates creates a template and its first version; POST /v1/templates/{id}/versions appends a version to an existing one. Both take a top-level blocks array, fill in any block id or action_id you omit (blk_<uuid> / act_<uuid>, yours are kept), derive request_format from the placeholders, and compile the blocks before persisting; blocks that do not compile are refused with 400 and code: "compilation_failed".
  3. POST /v1/templates/{id}/versions/{version_id}/activate makes a version live, the one that sends use. New versions are never live on creation, and versions are never edited in place. Pass expected_current_version_id to activate only if the version you read is still live (409 current_version_changed otherwise). Every activation is recorded at GET /v1/templates/{id}/activations, which is also how you find the version to roll back to. Activation has its own scope, templates:activate, so a key can be allowed to prepare versions but not to put them live. See Versions, activation and archiving.
GET /v1/templates/block-schema lists the block types, directive operators, placeholder syntax and Slack limits the engine enforces.

Discover template inputs

Use GET /v1/templates/{id}/input-schema for typed data fields, nesting, loop requirements and a JSON Schema. The /input-schema/make variant returns Make parameter definitions for its dynamic editor. Use these for new integrations; request_format remains the legacy example-shaped discovery field. The live (current) version is the default; an explicit version_id must belong to that template.

Rate limits

The authoring endpoints (POST /v1/templates, POST /v1/templates/validate, POST /v1/templates/{id}/versions, …/activate, PATCH /v1/templates/{id}) spend no credits, so they are limited instead: 120 requests per minute per organization, across all keys and sessions the organization uses. Over the limit you receive 429 with code: "rate_limited" and a Retry-After header saying how many seconds to wait. The limit is enforced at the edge and is deliberately permissive: counts converge over a few seconds, so a very short burst can exceed it briefly while sustained load above it is refused. Compile and send are metered by credits and are not subject to this limit.

Idempotency

Compiling spends credits; sending also posts to Slack, so a retry after a timeout could double-charge or double-send. To retry safely, send an Idempotency-Key header, any unique string up to 255 characters, on POST /v1/templates/compile, /send and /send-bulk:
  • The same key with the same body within 24 hours returns the original response again, with Idempotency-Replayed: true, and runs nothing.
  • The same key with a different body returns 409 with code: "idempotency_conflict". Use a new key for a new request.
  • A duplicate that arrives while the first request is still running returns 409 with code: "idempotency_in_progress".
  • A 5xx response is remembered and replayed. An incomplete request remains blocked, including after 24 hours, because Slack may already have accepted it. Contact support to reconcile the outcome; do not change keys to force a retry.
  • Completed responses below 500 may expire after 24 hours. Reusing an expired key may execute a new request; the retention window is not an exactly-once delivery guarantee.
Keys are scoped to your organization and to the endpoint. Without the header, nothing changes.
Never share API keys or commit them to version control. Store them in environment variables and rotate them regularly.

Organization isolation

All API access is scoped to your organization. You can only access resources in the organization where the API key was created. Cross-organization access is not supported.

Endpoints

The LithoBlocks API section in the sidebar lists all endpoints generated from the OpenAPI specification. The interactive playground is disabled. Use the request examples with a key from the matching environment. Start with Send your first API message for a complete request and verification flow.

Next steps

Templates

Build templates in the UI, then manage them via the API.

Quickstart

Get started with templates and Slack.