Docs
Webhooks & API

API Overview

The Blox REST API — base URL, request and response formats, error handling, and rate limits.

The Blox REST API lets you programmatically manage workspaces, sites, pages, forms, collections, and blog content — and configure outbound webhooks. Anything you build manually in the dashboard can be automated through the API.

This section covers everything a developer needs:

The API and webhooks require a plan that includes the Webhooks & API feature (typically the higher tiers). If your workspace doesn't include it, the Webhooks & API area shows a locked overlay — its upgrade prompt is titled "API & Webhooks," the same feature under a slightly different name. See Feature Access.


Base URL

All endpoints are served under a single versioned base URL:

https://yourapp.com/api/v1/

Every path in the API Reference is relative to this base.


Request Format

  • Transport: HTTPS only. Plain HTTP requests are redirected to HTTPS before they ever reach the API — there's no way to call it over an unencrypted connection.
  • Authentication: A Bearer token in the Authorization header on every request. Your API key starts with tdc_. See Authentication.
  • Body: Send JSON with Content-Type: application/json for writing/mutation endpoints (e.g. configuring webhooks).
curl -X POST https://yourapp.com/api/v1/webhooks \
  -H "Authorization: Bearer tdc_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workspaceId": "ws_abc123",
    "name": "CRM Sync",
    "url": "https://hooks.example.com/tdc",
    "events": ["form.submission.created"]
  }'

Response Format

Successful responses return HTTP 2xx with a JSON envelope indicating ok: true. Most responses carry the resource under a data key; a few action endpoints that don't have a resource to hand back — like deleting a webhook, or queuing a delivery replay — return just ok and a message instead.

{
  "ok": true,
  "data": {
    "id": "site_a1b2c3",
    "name": "Marketing Site",
    "subdomain": "marketing-site.sites.tdcapps.com"
  }
}

A paginated list response:

{
  "ok": true,
  "data": [ { "id": "page_1" }, { "id": "page_2" } ],
  "meta": {
    "page": 1,
    "limit": 20,
    "total": 42,
    "hasMore": true
  }
}

Not every list is paginated. GET /workspaces, GET /sites, and GET /workspaces/:workspaceId/members return their full array directly under data with no meta object. Every other list endpoint (pages, forms, submissions, collections, items, blog posts/authors/categories, webhooks, deliveries) returns meta as shown above.


Error Handling

Errors return a non-2xx status and a flat JSON body containing ok: false, a machine-readable error code, and a human-readable message.

{
  "ok": false,
  "error": "UNAUTHORIZED",
  "message": "Invalid or revoked API key."
}
StatusCodeMeaning
400BAD_REQUESTMalformed JSON, invalid query parameters, or missing required fields.
401UNAUTHORIZEDMissing, malformed, or revoked API key.
403FORBIDDENReserved for role/plan restrictions. Not currently returned by any endpoint — anything visible to your key is also fully usable by it.
404NOT_FOUNDThe resource doesn't exist, or isn't visible to your key.
429RATE_LIMITEDToo many requests — slow down (see below).

There's no JSON shape for an unexpected server failure today. If something goes wrong unexpectedly on our side, you may get a plain-text 500 Internal Server Error instead of the { "ok": false, ... } envelope above — so don't assume every non-2xx response is JSON. Check the response before parsing it.


Rate Limits

Requests are limited to 1,000 per hour, tracked per API key and per source IP together — calling the same key from several different IPs gives each IP its own 1,000/hour bucket. The limiter is a sliding window held in memory on each server instance, so it isn't shared across instances and resets on deploy.

If you send too many requests, the API returns a 429 status with the error code RATE_LIMITED. When this happens, wait a moment and try again. For apps that make lots of requests, add a delay that gets longer after each failed attempt (for example, wait 1 second, then 2, then 4, then 8—this is called "exponential backoff").


Next Steps