API reference

The three public endpoints the widget uses, their parameters, and their responses — for anyone building a custom client.

GET /api/v1/config

Returns the presentation configuration and custom field definitions for a project. Requires an allowed Origin header. Returns 400 for a malformed key, 404 for an unknown or paused project, 403 for a disallowed origin.

bash
curl 'https://bugloop.ai/api/v1/config?key=bl_pk_…' \
  -H 'Origin: https://acme.com'

POST /api/v1/feedback

Submits one feedback item. Requires an allowed Origin header and a JSON body. Returns 201 on success, 400 with a per-field error list on validation failure, 429 when rate limited, 403 for a disallowed origin, and 400 with `code: "verification"` when the proof of work is missing, expired or already used (the widget fetches a fresh challenge and retries once). A submission that trips the honeypot, time-on-form or link check gets the same 201 as a real report and is discarded.

severity is 1–5 or omitted. designAspect is accepted only when type is design. screenshotToken is the id returned by POST /api/v1/screenshot; it is redeemed once and ignored if it is unknown, already used, or belongs to another project — a report is never rejected because its screenshot went missing.

bash
curl -X POST 'https://bugloop.ai/api/v1/feedback' \
  -H 'Origin: https://acme.com' \
  -H 'Content-Type: application/json' \
  -d '{
    "key": "bl_pk_…",
    "type": "bug",
    "severity": 4,
    "title": "Checkout button does nothing",
    "description": "Clicking Pay on the cart page has no effect in Safari 17.",
    "screenshotToken": "8f1d…",
    "inputMethod": "typed",
    "email": "sam@acme.com",
    "notifyOnResolve": true,
    "pageUrl": "https://acme.com/cart",
    "pageTitle": "Cart",
    "viewport": "1440x900",
    "customFields": { "area": "Checkout", "blocking": true }
  }'

POST /api/v1/screenshot

Stores one image and returns a one-shot token for it. Multipart form data: key, image, width, height. Requires an allowed Origin header and consumes the same rate-limit budget as a submission.

The image type is read from the file's leading bytes and must match the declared Content-Type; only WebP, PNG and JPEG are accepted. Returns 201 with the token, 415 for anything that is not one of those three, 413 above 5 MB, 403 for a disallowed origin, 404 for an unknown or paused key, and 429 when rate limited.

A token that is never redeemed simply expires unused. It is bound to the project it was issued for and can be redeemed exactly once.

bash
curl -X POST 'https://bugloop.ai/api/v1/screenshot' \
  -H 'Origin: https://acme.com' \
  -F 'key=bl_pk_…' \
  -F 'width=1600' \
  -F 'height=900' \
  -F 'image=@screenshot.webp;type=image/webp'

# → 201 { "token": "8f1d…" }

Response shape

A successful submission returns the stored id and the outcome of each configured destination.

json
{
  "ok": true,
  "id": "0f2c…",
  "deliveries": [{ "provider": "github", "status": "success" }]
}

GET /api/health

Liveness and dependency check for uptime monitoring. Returns 200 when the environment is complete and the database answers, 503 otherwise. Reports nothing about your data.