← All documentation
Getting started

Getting started

Herald is a multi-tenant social-publishing API. Connect your accounts once, then publish to any of them from a single authenticated request.

Base URL

https://api.herald.leiritech.com

Every endpoint is under /v1. JSON in, JSON out, UTC ISO-8601 timestamps.

Authentication

Create an API key in the dashboard (Developer → API keys) and send it as a bearer token on every request:

curl https://api.herald.leiritech.com/v1/me \
  -H "Authorization: Bearer hld_xxxxxxxxxxxxxxxxxxxxxxxx"
{ "tenant_id": "…", "tenant_name": "Acme" }

The key resolves to exactly one tenant; every response is scoped to that tenant — there is no cross-tenant access. 401 unauthorized if the key is missing, invalid, or revoked.

The publishing model in 30 seconds

  1. Connect an account → it gets a Herald UUID (GET /v1/accounts).
  2. Upload media (optional) → POST /v1/media returns a media id.
  3. Publish → POST /v1/posts with targets (account UUIDs), text, optional media_ids, and a mode (now / schedule / draft).
  4. Track → poll GET /v1/posts/{id} (per-target status + permalink) or subscribe a webhook and get post.published / post.failed pushed to you.

One post can fan out to several networks at once; each target succeeds or fails independently (partial success is normal).

Errors

Failures return an appropriate 4xx/5xx and this shape:

{ "error": { "code": "validation_error", "message": "A video is required when publishing to YouTube or TikTok." } }
HTTPcodeMeaning
401unauthorizedmissing/invalid/revoked API key
404not_foundno such account/post for this tenant
409conflictwrong state (e.g. editing a published post) or network not configured
422validation_errorbad body / unknown network / bad media / per-network rule

Per-target publish failures never fail the whole request. Each failed target carries one of: rate_limited, invalid_media, reauth_required, policy, exchange_failed, unsupported.

Idempotency

Send external_ref on POST /v1/posts — a repeat with the same (tenant, external_ref) returns the original post instead of publishing twice. Use your own internal id.

Pagination

List endpoints (GET /v1/accounts, GET /v1/posts) are cursor-paginated:

  • ?limit — page size (default 25, max 100)
  • ?cursor — pass the next_cursor from the previous response

Each response includes "next_cursor" (opaque string, or null on the last page).

Next

  • API reference — every endpoint with examples.
  • Networks — a page per network with real connect + publish examples and gotchas.
  • SDKs — TypeScript and Python clients.