Search
Documentation

← Authoring templates

Published fill endpoints

A published fill endpoint lets an external system POST plain data and receive a finished deck — no Slidura account, no fill builder, no MCP client. You publish a draft from a template, receive a capability token, and hand the URL to whatever system produces the data.

How it works

  1. In the template workspace, open the Usage tab and create an endpoint. Give it a name, optionally set a callback URL and a monthly build cap, then click Publish. Publishing snapshots your current draft — the slide selection, order, and any pre-filled values — as the endpoint’s default_fill. The token (sfe_…) is shown once; copy it.

  2. Your system POSTs to POST /hooks/fills/{token} with a flat payload merged onto the published draft:

    {
      "variables": { "company": "ACME Corp" },
      "fields": {
        "intro_title": "Welcome",
        "s003.body": "Per-slide override on slide s003 only"
      }
    }
    • variables overlays the head-variable bindings (see Variables and typed values).
    • fields uses flat keys that apply the value to every included slide carrying that field; a <slide_id>.<key> form targets one slide only.
    • Unknown field keys → 400 listing valid ones.
    • Omitted blocks default to the published draft; to replace slide selection entirely, pass a slides array in the same schema as a regular fill.json.

    The build runs under the endpoint owner’s account. Defaults, variable interpolation, choice validation, and credit deduction all apply identically to a build started from the fill builder. A 402 response means the owner’s credit balance is too low.

  3. On success the response is 201:

    { "build_id": "…", "status_url": "/hooks/fills/{token}/builds/{build_id}" }

Polling for the result

GET /hooks/fills/{token}/builds/{build_id} returns:

{ "status": "started|built|failed",
  "download_url": "https://…",
  "expires_at": "2025-06-12T14:00:00Z",
  "error_message": null }

download_url is a signed, short-lived URL included when the build is built. Polling this endpoint works without configuring a webhook.

Outbound webhook (optional)

If you set a callback URL when creating the endpoint, Slidura fires a POST to that URL after the build completes or fails:

{ "build_id": "…", "status": "completed|failed",
  "output_filename": "deck.pptx",
  "download_url": "https://…", "expires_at": "…",
  "error_message": null }

The request carries the header X-Slidura-Signature: sha256=<hex> — an HMAC-SHA256 of the raw request body keyed with the endpoint’s webhook_secret (shown in the Usage tab alongside the token). Verify this signature before acting on the payload:

import hashlib, hmac

def verify(secret: str, body: bytes, header: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, header)

SSRF guard: callback URLs must be https and must resolve to a public address (loopback, private, link-local, and reserved ranges are rejected). Slidura makes up to three delivery attempts with linear backoff; failures are logged and do not cause retries beyond that — the status URL remains the authoritative source of truth.

Security note: the token appears in the URL path and will be visible in proxy access logs. Rotate the token (Usage tab → Rotate) if you suspect exposure; the old token is invalidated immediately.

Managing endpoints

The Usage tab in the template workspace lists all endpoints with their prefix, creation date, last-used date, and this-month build count. From there you can enable, disable, rotate the token, or delete an endpoint.

Per-endpoint rate limiting applies (60 requests per hour by default); a cap-exceeded request returns 429. A monthly build cap, if set, returns 429 once reached until the calendar month rolls over.