Přehled REST API
Všechny MCP nástroje odpovídají 1:1 REST endpointům. REST API použijte přímo pro CI/CD pipeline, integrace bez MCP, obsluhu webhooků, automatizaci na serveru nebo z jakéhokoli HTTP klienta.
Základní adresa: https://api.briefgate.dev
Požadavky i odpovědi jsou v JSON (Content-Type: application/json). Všechna časová razítka jsou v ISO 8601 a v UTC.
Autentizace
API klíč posílejte v každém požadavku jako Bearer token:
Authorization: Bearer bg_live_xxxxxSpráva API klíčů
POST /v1/keys Vytvořit nový klíč
GET /v1/keys Vypsat všechny klíče
DELETE /v1/keys/:id Zneplatnit klíč
DELETE /v1/keys/current Odvolá klíč, kterým je požadavek podepsaný (volá to logout v MCP balíčku)Vytvoření klíče:
curl -X POST https://api.briefgate.dev/v1/keys \
-H "Authorization: Bearer bg_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "CI/CD pipeline",
"mode": "live",
"scopes": ["intakes:read", "intakes:write"]
}'Režimy klíčů. mode je live (výchozí) nebo test. Testovací klíč (bg_test_…) vidí jen sběry podkladů, které sám vytvořil, a ty nikdy nepošlou klientovi e-mail ani SMS — pozvánky a upomínky se zapíší jako skipped, vše ostatní (portál, webhooky, výsledky) funguje normálně. Hodí se pro CI a zkoušení; samostatná schránka neexistuje, sběr zkontrolujete v dashboardu.
Dostupné scopy: admin, intakes:read, intakes:write, secrets:read. Scope admin zahrnuje všechny ostatní. Správa klíčů samotná je jen pro session: POST /v1/keys, GET /v1/keys i DELETE /v1/keys/:id vyžadují přihlášeného uživatele v dashboardu — API klíč nemůže vytvořit ani vypsat jiné klíče. Jedinou výjimkou je DELETE /v1/keys/current, protože ten odvolává přímo klíč, kterým je požadavek podepsaný.
Formát chyb
Všechny chyby vracejí JSON:
{
"error": "not_found",
"message": "Intake in_8f3k not found or does not belong to this account.",
"request_id": "req_abc123"
}Některé chyby nesou navíc: stabilní slug reason a strojově čitelné params, nebo — u požadavku, který neprošel validací polí — pole details s dvojicemi { path, message }, jedna na každé chybné pole:
{
"error": "unprocessable",
"message": "items.0.constraints: min_count must not exceed max_count",
"reason": "validation_failed",
"params": { "field": "items.0.constraints" },
"details": [
{ "path": "items.0.constraints", "message": "min_count must not exceed max_count" }
],
"request_id": "req_abc123"
}Když se obracíte na podporu, přiložte request_id.
Chybové kódy
| HTTP stav | Hodnota error |
Význam |
|---|---|---|
| 400 | invalid_request |
Vadný JSON, nebo požadavek, který je formálně v pořádku, ale je neplatný vzhledem k aktuálnímu stavu zdroje (třeba odvolání už odvolaného klíče). Podrobnosti jsou v message. |
| 401 | unauthorized |
Chybějící nebo neplatný API klíč. |
| 403 | forbidden |
Klíč nemá pro tuhle operaci potřebný scope. |
| 404 | not_found |
Zdroj neexistuje nebo patří jinému účtu. |
| 409 | conflict |
Zdroj se stejným identifikátorem už existuje (třeba duplicitní idempotency_key v době platnosti). Vrátí stávající zdroj. |
| 410 | gone |
Jednorázová hodnota vypršela a byla smazána — třeba vyplněný secret po uplynutí lhůty na odhalení. Opětovné čtení už odhaleného tajemství tohle NENÍ: to vrátí HTTP 200 s already_revealed: true. |
| 413 | payload_too_large |
Rezervováno pro budoucí použití — žádný endpoint ho nevrací pro příliš velké tělo požadavku. Příliš velký nahraný soubor se odmítne jako 422 unprocessable s nálezem file.too_large. |
| 413 | download_too_large |
Sběr podkladů překračuje limit velikosti pro stažení ZIP (GET /v1/intakes/:id/download) — pro vyzvednutí velkého sběru po jednotlivých položkách viz Stažení všeho v ZIPu. |
| 422 | unprocessable |
Požadavek neprošel validací: chybějící nebo špatně zadané povinné pole, hodnota mimo povolený rozsah, nebo požadavek, který je strukturálně v pořádku, ale významově ne (třeba min_count větší než max_count). Tohle vrací i chybějící povinné pole, ne 400 — které pole, ukazuje details. |
| 429 | rate_limited |
Příliš mnoho požadavků. Před dalším pokusem se řiďte hlavičkou Retry-After (v sekundách). |
| 402 | quota_exceeded |
Vyčerpaná měsíční kvóta na sběry podkladů nebo úložiště. |
| 402 | plan_required |
Funkce není v aktuálním tarifu k dispozici. |
| 500 | internal_error |
Neočekávaná chyba serveru. Je bezpečné to zkusit znovu s rostoucí prodlevou. |
| 503 | service_unavailable |
Databáze je dočasně nedostupná. Řiďte se hlavičkou Retry-After (v sekundách) a zkuste to znovu. |
Intakes
POST /v1/intakes
Založí nový sběr podkladů a pošle klientovi odkaz na jeho portál.
Hlavičky požadavku
| Hlavička | Popis |
|---|---|
Idempotency-Key |
Nepovinná. Jedinečný řetězec (doporučujeme UUID). Když už s tímhle klíčem sběr podkladů vznikl, vrátí se původní (HTTP 200) místo vytvoření duplikátu. |
Hlavní pole požadavku
| Pole | Typ | Povinné | Popis |
|---|---|---|---|
project_name |
string | Ano | Název projektu srozumitelný člověku. |
client.email |
string | Ano | E-mailová adresa klienta. |
client.name |
string | Ano | Jméno klienta pro oslovení — každá pozvánka jím začíná, takže nemůže být prázdné. |
client.language |
string | Ne | cs, sk, pl, de, es, en. Když chybí, použije se default_language účtu, pak angličtina. |
client.phone |
string | Ne | Formát E.164, např. +420601123456. Rezervováno pro SMS upomínky (chase_schedule s kanálem sms, viz Rozvrhy upomínek). |
client.timezone |
string | Ne | Časové pásmo IANA, např. Europe/Prague. Podle něj se řídí respect_quiet_hours a chase_at_time. Výchozí Europe/Prague. |
client.also_notify |
array | Ne | Až 4 další lidé ({ email, name? }), kteří dostanou stejný odkaz na portál a stejné upomínky jako primární klient. Přidat nebo odebrat je jde i po založení přes POST/DELETE /v1/intakes/:id/recipients (viz Příjemci). |
email_copy |
object | Ne | Přebije předmět a úvodní text pro tenhle sběr podkladů. Viz chase.md. |
client_brief |
string | Ne | Informace a kontext pro klienta — zobrazí se v horní části portálu, před požadovanými položkami, jako „Informace od <vaše jméno>". Max 5000 znaků; oříznuté; prázdný řetězec se uloží jako null. Soubory přiložíte přes POST /v1/intakes/:id/brief/files, až sběr podkladů existuje — viz Brief pro klienta. |
items |
array | Ano | Definice položek. Viz item-types.md. Povinné (min. 1) i když je vyplněné template. |
template |
string | Ne | Slug uložené šablony (templates.md). Položky šablony se s items slučují podle key. Každé další pole, které nastavuje settings šablony, se použije jako výchozí hodnota — jen tam, kde ho tenhle požadavek sám nevyplní. |
chase_schedule |
string | Ne | default, gentle, aggressive, custom nebo off. |
chase_interval |
integer | Ne | Jak často upomínat, jen s chase_schedule: "custom". Používá se spolu s chase_interval_unit. Výchozí: každé 3 dny. S jiným rozvrhem vrátí 422. |
chase_interval_unit |
string | Ne | minutes, hours nebo days (výchozí days). Výsledný interval musí být aspoň 5 minut a nejvýš 90 dní. |
respect_quiet_hours |
boolean | Ne | Držet upomínky v okně 8:00–19:00 podle klienta. Výchozí true. |
max_reminders |
integer | string | Ne | Počet upomínek, než se sběr podkladů označí za zaseknutý (1–1000, výchozí 3, nebo "unlimited"). |
chase_at_time |
string | Ne | Místní denní hodina upomínky ve formátu HH:MM. Vyžaduje chase_schedule: "custom" s intervalem v celých dnech. |
due_date |
string | Ne | Datum v ISO 8601, které uvidí klient. |
send |
boolean | Ne | false založí koncept bez odeslání. Odeslat později můžete přes POST /v1/intakes/:id/send. Výchozí true. |
retention |
object | Ne | Jak dlouho držet data po dokončení. { mode: "days"|"on_delivery", days?: number, anonymize?: boolean }. Výchozí: smazat 90 dní po intake.completed. U sběru podkladů s přístupy použijte mode: "on_delivery" — obsah zmizí zhruba 24 hodin po vyzvednutí výsledků. |
folder_id |
string | Ne | Zařadí sběr podkladů do téhle složky — id z GET /v1/folders. Když chybí, sběr podkladů zůstane nezařazený. Musí patřit na váš vlastní účet, jinak 400 invalid_request (reason validation_error). |
Rozvrhy upomínek
| Rozvrh | Upomínky |
|---|---|
default |
za 2, 5 a 9 dní, pak jednou týdně |
gentle |
za 3 a 8 dní, pak jednou za dva týdny (o víkendech nic nepošle, posune na pondělí 8:00) |
aggressive |
za 1, 3 a 5 dní, pak obden |
custom |
Každých chase_interval chase_interval_unit (výchozí každé 3 dny), první jeden interval po pozvánce |
off |
Žádné automatické upomínky |
Odpověď (HTTP 201)
{
"intake_id": "in_8f3kQmR2",
"portal_url": "https://p.briefgate.dev/8f3kqmr2",
"status": "sent",
"items": [
{ "key": "logo", "status": "pending" },
{ "key": "hero_copy", "status": "pending" }
],
"follow_up": {
"recommended": "schedule",
"reason": "No active webhook endpoints are registered on this account.",
"webhook": {
"active_endpoints": 0,
"events": ["item.submitted", "intake.completed"],
"register_with": "manage_webhook"
},
"schedule": {
"check_with": "get_intake_status",
"every_hours": 24,
"until": "2024-03-29T10:22:00Z"
}
}
}follow_up je vždy přítomné a napovídá, jak sledovat postup bez slepého pollování. recommended je "webhook", pokud už aktivní endpoint pokrývá relevantní eventy, nebo "schedule", pokud ne — v tom případě volejte GET /v1/intakes/:id/status každých follow_up.schedule.every_hours hodin až do follow_up.schedule.until, nebo si místo toho zaregistrujte webhook (POST /v1/webhooks, viz Webhooks).
Kompletní příklad s curl
curl -X POST https://api.briefgate.dev/v1/intakes \
-H "Authorization: Bearer bg_live_xxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: bella-napoli-website-2024" \
-d '{
"project_name": "Bella Napoli — Website",
"client": {
"email": "owner@bellanapoli.com",
"name": "Marco Esposito",
"language": "en"
},
"items": [
{
"key": "logo",
"label": "Restaurant logo",
"help": "SVG or PNG, transparent background, minimum 512px.",
"type": "image",
"required": true,
"constraints": {
"formats": ["svg", "png"],
"min_width": 512,
"transparent_background": true
}
},
{
"key": "hero_copy",
"label": "Hero section tagline",
"type": "longtext",
"required": true,
"constraints": { "max_chars": 400 }
},
{
"key": "opening_hours",
"label": "Opening hours",
"type": "structured",
"required": true,
"schema": {
"type": "object",
"required": ["mon_fri", "sat", "sun"],
"properties": {
"mon_fri": { "type": "string" },
"sat": { "type": "string" },
"sun": { "type": "string" }
}
}
},
{
"key": "photos",
"label": "Food and interior photos",
"type": "file_list",
"required": true,
"constraints": {
"formats": ["jpg", "png", "heic"],
"min_count": 5,
"max_count": 15
}
}
],
"chase_schedule": "default",
"due_date": "2024-04-01"
}'GET /v1/intakes
Vypíše sběry podkladů s volitelnými filtry.
Parametry dotazu
| Parametr | Popis |
|---|---|
status |
Filtr podle stavu: draft, sent, in_progress, completed, archived. |
client_email |
Filtr na konkrétního klienta. |
folder_id |
Filtr na jednu složku — id z GET /v1/folders, nebo doslovné none pro sběry podkladů bez složky. |
q |
Hledání podřetězce bez ohledu na velikost písmen v project_name, client.name a client.email (1–100 znaků). Kombinuje se s ostatními filtry. |
limit |
Počet výsledků na stránku (výchozí 20, maximum 100). |
offset |
Posun pro stránkování (výchozí 0). |
Odpověď
{
"intakes": [
{
"intake_id": "in_8f3kQmR2",
"project_name": "Bella Napoli — Website",
"status": "in_progress",
"client": {
"email": "owner@bellanapoli.com",
"name": "Marco Esposito"
},
"portal_url": "https://p.briefgate.dev/8f3kqmr2",
"created_at": "2024-03-15T10:22:00Z",
"progress": { "submitted": 3, "total": 7 }
}
],
"total": 47,
"limit": 20,
"offset": 0
}Poznámka: Každý sběr podkladů odpovídá stejnému snake_case tvaru, jaký se používá všude jinde v tomhle API, navíc s přehledem
progressza daný sběr podkladů — kompletní popis polí najdete u GET /v1/intakes/:id a GET /v1/intakes/:id/status.
GET /v1/intakes/:id
Vrátí kompletní definici sběru podkladů včetně všech definic položek a metadat.
Odpověď
{
"intake": {
"intake_id": "in_8f3kQmR2",
"project_name": "Bella Napoli — Website",
"status": "in_progress",
"mode": "live",
"portal_url": "https://p.briefgate.dev/8f3kqmr2",
"client": {
"email": "owner@bellanapoli.com",
"name": "Marco Esposito",
"phone": null,
"language": "en",
"timezone": "Europe/Rome",
"also_notify": [
{ "email": "chef@bellanapoli.com", "name": "Giulia", "bounced_at": null }
],
"client_bounced_at": null
},
"branding": null,
"folder_id": null,
"chase_schedule": "default",
"chase_interval_minutes": null,
"respect_quiet_hours": true,
"max_reminders": 3,
"chase_at_time": null,
"due_date": "2024-04-01",
"retention": { "mode": "days", "days": 90, "anonymize": true },
"created_at": "2024-03-15T10:22:00Z",
"sent_at": "2024-03-15T10:22:05Z",
"completed_at": null,
"delivered_at": null,
"anonymized_at": null,
"client_last_seen": "2024-03-16T14:05:33Z",
"stalled_at": null,
"purge_at": null,
"client_note": null,
"owner_note": null,
"client_brief": null,
"brief_files": []
},
"items": [
{
"key": "hero_copy",
"type": "longtext",
"assignee": "client",
"label": "Hero section tagline",
"help": null,
"required": true,
"status": "approved",
"value": "Real Napoli-style pizza, right in your neighbourhood.",
"constraints": { "max_chars": 400 },
"options": null,
"pattern": null,
"submitted_at": "2024-03-16T11:00:00Z",
"approved_at": "2024-03-16T11:05:00Z",
"revision_note": null,
"revision_count": 0,
"waiver": { "state": "none", "reason": null, "requested_by": null, "requested_at": null, "decided_at": null },
"client_note": null,
"owner_note": null
}
],
"progress": { "submitted": 2, "total": 4, "outstanding": 2, "percent": 50 },
"owner_tasks": { "done": 0, "total": 0 }
}chase_interval_minutes je normalizovaná hodnota chase_interval/chase_interval_unit; je null, dokud chase_schedule není "custom". Položka typu file, file_list nebo image nese navíc pole files (id, filename, mime, size, width/height, av_status, checksum_sha256) místo smysluplné value — podepsaná adresa se tu nevytváří; stáhněte ji přes GET /v1/intakes/:id/items/:key/files/:fileId (níže) nebo GET /v1/intakes/:id/results. Vlastníkova položka typu select/multiselect ("rozhodnutí") nese navíc objekt decision: { decided_by: "agent"|"owner", value, proposed_value, proposed_rationale }.
brief_files — přílohy k client_brief — je jen v téhle podrobné odpovědi, ne v GET /v1/intakes (dotaz na každý řádek při každém zobrazení seznamu by běžel pro každý sběr podkladů, přitom naprostá většina brief nemá). Každá položka je { id, filename, mime, size, av_status, created_at }, se stejným pravidlem dostupnosti jako u souboru položky (av_status rozhoduje, jestli stažení vůbec půjde). Text i soubory brief spravujete přes Brief pro klienta níže.
PATCH /v1/intakes/:id
Upraví existující sběr podkladů místo jeho mazání a zakládání nového — což dřív bylo jediné možné řešení a klientovi to poslalo novou pozvánku. Všechna pole jsou nepovinná, ale aspoň jedno musí být zadané (jinak 400 invalid_request). null smaže owner_note, client_brief, due_date a chase_at_time; vynechané pole vždy zůstává beze změny.
| Pole | Typ | Poznámky |
|---|---|---|
owner_note |
string | null | Klientovi se nikdy nezobrazí. |
client_brief |
string | null | Informace pro klienta, zobrazí se v horní části portálu — viz client_brief u POST /v1/intakes. null ho smaže; prázdný řetězec se také uloží jako null. |
project_name |
string | |
due_date |
string | null | YYYY-MM-DD. |
chase_schedule |
string | default, gentle, aggressive, custom, off. |
chase_interval / chase_interval_unit |
integer / string | Stejná pravidla jako u POST /v1/intakes — má smysl jen s chase_schedule: "custom". |
chase_at_time |
string | null | HH:MM, vyžaduje interval v celých dnech. |
max_reminders |
integer | "unlimited" |
|
respect_quiet_hours |
boolean | |
client.name, .phone, .language, .timezone |
Bez client.email. Odkaz do portálu a magic token jsou navázané na hlavní adresu — její změna by tady klientův stávající odkaz odřízla. Adresy přidávejte, odebírejte nebo obnovujte přes endpointy pro příjemce. |
|
folder_id |
string | null | Přesune sběr podkladů do téhle složky, nebo null pro přesun mezi nezařazené. Musí patřit na váš vlastní účet (jinak 400 invalid_request, reason validation_error). Nikdy neovlivní status, upomínky ani nic dalšího. |
Změna rytmu u živého sběru podkladů. U sběru podkladů ve stavu sent, in_progress nebo zaseknutého změna kteréhokoli z polí chase_schedule, chase_interval, chase_interval_unit, chase_at_time, max_reminders, respect_quiet_hours, client.timezone nebo due_date zruší všechny ještě naplánované upomínky a naplánuje je znovu podle nového nastavení. Upomínky, které už odešly, se pořád počítají do max_reminders — číslování pokusů se neresetuje.
Odblokování zaseknutého sběru podkladů. Sběru podkladů, kterému došel max_reminders, se upomínání zastaví a nastaví se mu stalled_at (viz Strop upomínek). Zvýšení max_reminders (nebo nastavení na "unlimited") nad počet už odeslaných upomínek stalled_at zruší a automatické upomínání se obnoví. Změna ostatních polí u pořád zaseknutého sběru podkladů uložené nastavení aktualizuje, ale sama o sobě upomínání neobnoví.
U archivovaného sběru podkladů vrátí 409 conflict (reason intake_archived).
Požadavek
{
"chase_schedule": "custom",
"chase_interval": 6,
"chase_interval_unit": "hours",
"max_reminders": 12
}Odpověď je { "intake": { ... } }, stejný tvar jako objekt intake u GET /v1/intakes/:id.
GET /v1/intakes/:id/items/:key/files/:fileId
Stáhne nebo zobrazí náhled jednoho souboru, který nahrál klient. Odpoví HTTP přesměrováním 302 na podepsanou adresu (platnost 24 hodin) místo JSON — použijte ji přímo jako <a href>/<img src>. Vrátí 422 unprocessable, pokud soubor ještě čeká na antivirovou kontrolu nebo byl označen jako infikovaný.
POST /v1/intakes/:id/brief/files
Přiloží soubor k briefu pro klienta — texty a dokumenty, které klientovi předáváte, zobrazí se v horní části portálu před požadovanými položkami (viz client_brief u POST /v1/intakes). multipart/form-data s jedním polem file. Jde přes stejný proces jako klientovo vlastní nahrání: skutečný typ obsahu se rozpoznává, ne jen věří deklarovanému, HEIC se konvertuje na JPEG a antivirová kontrola proběhne dřív, než se soubor uloží — infikovaný soubor se odmítne rovnou (422 unprocessable), ne že by se uložil a skryl.
Brief unese nejvýš 10 souborů; jedenáctý vrátí 422 unprocessable. Počítá se do stejné kvóty úložiště jako všechno ostatní na účtu. U archivovaného sběru podkladů vrátí 409 conflict (reason intake_archived).
Odpověď (HTTP 201)
{
"file": {
"id": "bff_9k2mQ7xR",
"filename": "contract-offer.pdf",
"mime": "application/pdf",
"size": 184320,
"av_status": "clean",
"created_at": "2024-03-15T10:20:00Z"
}
}DELETE /v1/intakes/:id/brief/files/:fileId
Odstraní jednu přílohu briefu a uvolní její bajty z kvóty úložiště. Vrátí 204 No Content. U archivovaného sběru podkladů vrátí 409 conflict (reason intake_archived).
GET /v1/intakes/:id/brief/files/:fileId/url
Stáhne nebo zobrazí náhled jedné přílohy briefu. Stejná konvence jako GET /v1/intakes/:id/items/:key/files/:fileId výše: HTTP přesměrování 302 na podepsanou adresu a 422 unprocessable, dokud soubor čeká na antivirovou kontrolu nebo je označen jako infikovaný.
GET /v1/intakes/:id/status
Lehký stavový endpoint. Vrátí stavy položek, historii upomínek a postup, bez obsahu souborů a podepsaných adres.
Odpověď
progress.total počítá jen to, na co se čeká: prominutá položka i nevyplněná volitelná položka jsou mimo jmenovatel. Díky tomu je percent rovno 100 přesně ve chvíli, kdy se status změní na completed.
{
"status": "in_progress",
"due_date": "2024-04-01",
"client_last_seen": "2024-03-16T14:05:33Z",
"progress": {
"submitted": 2,
"total": 4,
"outstanding": 2,
"percent": 50
},
"items": [
{ "key": "logo", "status": "approved", "submitted_at": "2024-03-16T10:00:00Z", "label": "Restaurant logo", "assignee": "client", "required": true },
{ "key": "hero_copy", "status": "needs_revision", "submitted_at": "2024-03-16T11:00:00Z", "label": "Hero section tagline", "assignee": "client", "required": true },
{ "key": "opening_hours", "status": "pending", "submitted_at": null, "label": "Opening hours", "assignee": "client", "required": true },
{ "key": "photos", "status": "submitted", "submitted_at": "2024-03-16T12:00:00Z", "label": "Food and interior photos", "assignee": "client", "required": true }
],
"chases": [
{ "id": "chs_a1", "channel": "email", "kind": "invite", "scheduled_at": "2024-03-15T10:22:00Z", "sent_at": "2024-03-15T10:22:05Z", "status": "sent", "attempt_no": 1, "missing_items_count": null, "error": null },
{ "id": "chs_a2", "channel": "email", "kind": "reminder", "scheduled_at": "2024-03-17T09:00:00Z", "sent_at": "2024-03-17T09:00:00Z", "status": "sent", "attempt_no": 2, "missing_items_count": 2, "error": null },
{ "id": "chs_a3", "channel": "email", "kind": "reminder", "scheduled_at": "2024-03-20T09:00:00Z", "sent_at": null, "status": "scheduled", "attempt_no": 3, "missing_items_count": null, "error": null }
]
}items[].assignee (client/owner) a .required jsou přítomné vždy; vlastníkova položka typu rozhodnutí nese navíc stejný objekt decision jako je popsaný u GET /v1/intakes/:id. chases[].kind je jedna z hodnot invite, reminder, revision, manual; .status je jedna z scheduled, sent, failed, bounced, complained, cancelled, skipped. scheduled_at udává, kdy je naplánovaná další čekající upomínka — místo odhadování z chase_schedule sledujte tohle.
GET /v1/intakes/:id/results
Vrátí otypované výsledky schválených položek. U souborů a obrázků jsou podepsané adresy s platností 24 hodin.
Jen API klíč — na rozdíl od všech ostatních endpointů kolem sběru podkladů tenhle neakceptuje session z dashboardu. Odhaluje tajemství a posouvá kurzor only_new vázaný na konkrétní API klíč, a obojí dává smysl jen pro agentův vlastní API klíč; dashboard místo toho používá GET /v1/intakes/:id a POST /v1/intakes/:id/items/:key/reveal.
Parametry dotazu
| Parametr | Typ | Popis |
|---|---|---|
only_new |
boolean | Vrátí jen položky schválené od posledního volání tohoto endpointu (sleduje se podle API klíče). |
include_pending |
boolean | Zahrne i položky ve stavu submitted, které ještě nejsou schválené. |
exclude_secrets |
boolean | Vynechá položky typu secret bez jejich odhalení — meta hlásí secret_unavailable: true a jednorázové odhalení zůstává k dispozici. Hodí se pro integrace, které ukládají každou odpověď (Zapier, Make, n8n). |
Odpověď
{
"intake_id": "in_8f3kQmR2",
"status": "in_progress",
"progress": { "submitted": 2, "total": 4, "outstanding": 2, "percent": 50 },
"missing": ["opening_hours"],
"results": {
"logo": { "url": "https://...", "filename": "logo.svg", "mime": "image/svg+xml", "size": 4821, "checksum_sha256": "..." },
"hero_copy": "Real Napoli-style pizza, right in your neighbourhood."
},
"meta": {
"logo": { "type": "image", "status": "approved", "submitted_at": "2024-03-16T10:00:00Z" },
"hero_copy": { "type": "longtext", "status": "approved", "submitted_at": "2024-03-16T11:00:00Z" }
}
}results obsahuje jeden záznam na každou zahrnutou položku, klíčovaný jejím key, ve tvaru podle jejího type — položka secret tu svou hodnotu odhalí přesně jednou (viz níže) a při každém dalším čtení ji meta hlásí místo toho jako { secret_unavailable: true, reason, revealed_at }. missing vypisuje klíče povinných klientských položek, které pořád chybí. Čtení položky secret vyžaduje scope secrets:read (nebo admin); bez něj se položka vynechá z results i meta a meta místo toho nese { secret_unavailable: true, reason: "Scope 'secrets:read' or 'admin' required." }. Položka typu file/file_list, která ještě není dostupná (čeká na antivirovou kontrolu, nebo je infikovaná), se z výpisu souborů podobně vynechá a meta[key].files_pending udává jejich počet.
POST /v1/intakes/:id/items/:key/reveal
Odhalí hodnotu jedné položky typu secret. Jen session — způsob, jakým dashboard čte přístupový údaj; API klíč musí místo toho použít GET /v1/intakes/:id/results se scopem secrets:read, a zavolat to smí jen vlastník účtu (jiný člen týmu dostane 403 forbidden, reason secrets_owner_only). Stejně jako u /results se hodnota uvolní přesně jednou.
Odpověď (první odhalení)
{ "key": "admin_password", "value": "hunter2", "first_reveal": true, "expires_at": "2024-03-23T10:00:00Z" }Odpověď (už odhaleno — HTTP 200, ne chyba)
{ "key": "admin_password", "value": null, "already_revealed": true, "revealed_at": "2024-03-16T10:05:00Z", "message": "This credential was already revealed. Secrets are shown once and cannot be shown again." }POST /v1/intakes/:id/items
Přidá položky do existujícího sběru podkladů. Klientovi přijde e-mail.
Tělo požadavku
{
"items": [
{
"key": "favicon",
"label": "Favicon",
"type": "image",
"required": true,
"constraints": { "formats": ["png","svg"], "min_width": 32 }
}
]
}Odpověď
{
"intake_id": "in_8f3kQmR2",
"items_added": [
{ "key": "favicon", "status": "pending" }
]
}PATCH /v1/intakes/:id/items/:key
Změní jednu položku u požadavku, který už je u klienta — typ, popisek, nápovědu, povinnost i povolené formáty. Nese zároveň owner_note.
Hodí se, když se ukáže, že pole má špatný tvar: chtěli jste obrázek a klient má logo jen v PDF, nebo to, co jste žádali jako text, je ve skutečnosti soubor. Rozšíření formátů nebo změna typu klienta odblokuje, aniž byste přidávali duplicitní položku a původní promíjeli.
key změnit nejde — pod tím jménem se vracejí výsledky. Přidejte místo toho novou položku.
Pokud klient položku už vyplnil a změna by jeho odpověď zneplatnila, volání skončí 409 item_answer_would_be_discarded a nic se nezmění. Zopakujte ho s discard_submitted_value: true, čímž se odpověď smaže a klient ji vyplní znovu. Změna, po které odpověď dál platí (nový popisek, volnější limit), nezahodí nikdy nic.
Požadavek
{
"type": "file",
"label": "Logo",
"constraints": { "formats": ["svg", "png", "pdf"] }
}POST /v1/intakes/:id/revision
Vyžádá opravu konkrétní položky. Platí jen tehdy, když je stav položky submitted nebo approved (jinak 409 conflict). Vyžaduje funkci revisions — na tarifu Free není k dispozici (jinak 402 plan_required).
Tělo požadavku
{
"item_key": "logo",
"note": "The logo appears blurry at 320px. Please re-export at minimum 512px, ideally as SVG."
}Odpověď
{
"intake_id": "in_8f3kQmR2",
"item_key": "logo",
"status": "needs_revision",
"client_notified": true
}POST /v1/intakes/:id/items/:key/done
Odškrtnutí vlastního úkolu — položky vytvořené s "assignee": "owner".
Tělo požadavku
{
"done": true
}done je nepovinné a výchozí hodnota je true. Pošlete false pro znovuotevření úkolu.
Odpověď
{
"key": "call_client",
"done": true,
"status": "approved"
}Přijímají se jen vlastní úkoly. Klientská položka vrátí 400 — tu odpověď dává klient v portálu. Odškrtnutí úkolu nikdy sběr podkladů nedokončí ani nedoručí: vlastní úkoly jsou záměrně mimo postup klienta.
POST /v1/intakes/:id/items/:key/received-outside
Označí klientskou položku jako přijatou mimo BriefGate — klient poslal soubor e-mailem, předal ho na schůzce nebo jiným kanálem. Od té chvíle se položka počítá jako hotová, takže sběr podkladů může skončit, i když portálem nic nepřišlo. Pokud šlo o poslední chybějící položku, sběr se dokončí úplně stejně, jako by klient klikl na „Odeslat podklady“: spustí se webhook intake.completed a odejde volitelný děkovný e-mail.
Tělo požadavku
{
"note": "Poslala e-mailem 5. 9."
}note je nepovinná — krátká připomínka, kde podklad ve skutečnosti je. Zobrazuje se u položky v dashboardu, klient ji nikdy nevidí.
Odpověď
{
"key": "logo",
"status": "approved",
"received_outside": true,
"intake_status": "completed"
}Přijímají se jen klientské položky; vlastní úkol vrátí 400 — ten se odškrtává přes /done. Položka, která už je schválená nebo prominutá, vrátí 409 (nejdřív zrušte prominutí), stejně jako archivovaný sběr podkladů. Každá položka v GET /v1/intakes/:id i ve výsledcích nese received_outside a received_outside_note, takže agent, který čte výsledky, ví, že podklad existuje, ale v BriefGate uložený není.
DELETE /v1/intakes/:id/items/:key/received-outside
Zruší označení. Položka se vrátí mezi ty, na které se čeká od klienta, a ukazatel postupu se odpovídajícím způsobem sníží; sběr podkladů, který se tímto označením dokončil, se znovu otevře stejně jako při zrušení prominutí. Pokud položka označená nebyla, vrátí 404.
POST /v1/intakes/:id/items/:key/answer
Rozhodne o rozhodnutí — vlastníkově položce typu select/multiselect, která volitelně nese agentovu vlastní navrhovanou odpověď (items[].proposed, viz POST /v1/intakes). value se ověřuje proti vlastním options položky, stejně jako u klientské odpovědi.
Záměrně jen session. API klíč tohle zavolat nemůže: ten drží AGENT, a přijetí by mu umožnilo potvrdit vlastní návrh a mít výsledek zaznamenaný jako decided_by: "owner" — přesně tomu má oddělení návrhu od odpovědi zabránit. Položka, která není rozhodnutím, vrátí 400 invalid_request.
Požadavek
{ "value": "29" }Odpověď
{ "key": "attendee_count", "value": "29", "status": "approved", "decided_by": "owner" }POST /v1/intakes/:id/items/:key/waive
Vlastník položku rovnou uzavře ("tohle mít nebudeme"). Přímo prominout smí jen vlastník — klient v portálu může prominutí jen navrhnout, o kterém pak vlastník rozhodne endpointem níže.
Požadavek
{ "reason": "Client doesn't have a logo yet; using a text wordmark instead." }reason je nepovinný. Odpověď je { "item": { ... } }, stejný tvar položky jako u GET /v1/intakes/:id.
POST /v1/intakes/:id/items/:key/waive/decision
Vlastník přijme nebo zamítne prominutí, které navrhl klient. Vrátí 409 conflict, pokud u položky žádný návrh na prominutí nečeká na rozhodnutí.
Požadavek
{ "accept": true, "note": "Confirmed with the client by phone." }Přijetí přesune položku do stavu waived; zamítnutí nechá její stav beze změny, ale zruší příznak čekání na vlastníka, takže se znovu upomíná jako každá jiná nevyřízená položka. note je jen pro auditní log. Odpověď je { "item": { ... } }.
DELETE /v1/intakes/:id/items/:key/waive
Vrátí prominutí zpátky do stavu pending a zahodí přitom hodnotu, odeslání i poznámku k opravě, které položka měla — klienta je tak jako tak potřeba požádat znovu. Pokud sběr podkladů dosáhl stavu completed, znovu se otevře na in_progress a naplánují se upomínky. Odpověď je { "item": { ... } }.
POST /v1/intakes/:id/recipients
Přidá dalšího člověka ke sběru podkladů, který už byl odeslán. Dostane stejný odkaz na portál a stejné budoucí upomínky jako primární klient; samotné volání e-mail neposílá — pošlete ho přes POST /v1/intakes/:id/send nebo .../chase. Nejvýš 4 další příjemci (5 celkem včetně primárního klienta); 409 conflict (reason recipient_exists), pokud už adresa na sběru podkladů je.
Požadavek
{ "email": "chef@bellanapoli.com", "name": "Giulia" }Odpověď (HTTP 201)
{
"intake_id": "in_8f3kQmR2",
"also_notify": [
{ "email": "chef@bellanapoli.com", "name": "Giulia", "bounced_at": null }
]
}DELETE /v1/intakes/:id/recipients/:email
Odebere dalšího příjemce (adresu URL-encodujte). Primárního klienta takhle odebrat nejde — na jeho změnu použijte PATCH /v1/intakes/:id, nebo založte sběr podkladů znovu přes POST /v1/intakes — při pokusu vrátí 400 invalid_request (reason recipient_is_primary). Při úspěchu vrací HTTP 204, 404 not_found, pokud adresa na sběru podkladů není.
POST /v1/intakes/:id/recipients/:email/reinstate
Zruší příznak odrazu na jedné adrese (URL-encodujte ji), ať jde o hlavní nebo další příjemce — pro odraz, který byl falešný poplach, nebo schránku, kterou klient mezitím opravil a požádal o opětovné zařazení. Pokud předtím nebyl nikdo, koho by šlo upomínat (odrazily se všechny adresy), a sběr podkladů je sent nebo in_progress, automatické upomínání se obnoví.
Vrátí 404 not_found (reason recipient_not_found), pokud adresa na sběru podkladů není, 409 conflict (reason recipient_not_bounced), pokud se nikdy neodrazila.
Odpověď (HTTP 200)
{
"email": "owner@bellanapoli.com",
"bounced_at": null,
"still_chasing": true
}still_chasing říká, jestli tahle adresa bude opravdu dostávat další automatické upomínky — false, pokud je sběr podkladů completed, archived, zaseknutý, nebo má chase_schedule nastavené na "off".
GET /v1/intakes/preview
Jen session. Vykreslí, co klient skutečně uvidí ve své schránce — předmět a jméno odesílatele — ještě předtím, než se cokoli odešle, podle aktuálního brandingu účtu. Hodí se na odhalení chybějícího jména odesílatele nebo špatného jazyka dřív, než to uvidí skutečný klient.
Parametry dotazu: language (výchozí je default_language účtu), project_name (výchozí je lokalizovaný zástupný text).
Odpověď
{
"language": "en",
"from_name": "Marco @ Bella Napoli (via BriefGate)",
"subject": "Marco needs a few things from you — Bella Napoli — Website",
"sender_name": "Marco @ Bella Napoli",
"using_fallback_sender_name": false
}POST /v1/intakes/:id/chase
Ručně odešle upomínku mimo automatický rozvrh.
Tělo požadavku
{
"channel": "email"
}channel je nepovinný: "email" (výchozí) nebo "sms". SMS vyžaduje funkci sms (na tarifu Free není k dispozici) a kladný zůstatek SMS kreditů — jinak 402 plan_required, nebo 402 quota_exceeded (reason sms_credits). Rate limit je 1 ruční upomínka na sběr podkladů za hodinu a 20 na účet za hodinu (429 rate_limited, reason manual_chase_intake/manual_chase_account), bez ohledu na kanál.
POST /v1/intakes/:id/send
Odešle klientovi sběr podkladů ve stavu konceptu. Platí jen tehdy, když je status roven draft (jinak 409 conflict). Rate limit je 30 pozvánek na účet za hodinu (429 rate_limited, reason intake_invites) — stejný limit, do kterého se počítá i POST /v1/intakes, když odesílá rovnou.
POST /v1/intakes/:id/archive
Uzavře sběr podkladů, aniž by ho smazal. Funguje z libovolného stavu (draft, sent, in_progress, completed); když je sběr už archivovaný, vrátí 409 conflict (reason intake_archived). Tělo požadavku je prázdné.
Vedlejší efekty:
- Zruší všechny naplánované i čekající upomínky.
- Zablokuje další aktivitu:
PATCH /v1/intakes/:id, přidání/úprava položek, waivery i ruční upomínky teď vrací409 conflict(reasonintake_archived) — stejnou chybu, jakou tyto endpointy vrací u už archivovaného sběru. - V klientském portálu magický odkaz dál funguje — klient stále vidí vše, co už odeslal, a
statusje"archived"— ale odeslání položky, nahrání souboru, poznámka, waiver i dokončení jsou odmítnuty se stejnou409/intake_archived. - Vyšle webhook
intake.archived(viz Webhooks) a zapíše záznam do audit loguintake.archived.
Nic se nemaže: řádek, jeho položky, soubory i historie zůstávají přesně tak, jak byly, a GET /v1/intakes/:id sběr dál vrací. Vrací { intake } — stejný jednotlivý objekt intake jako PATCH /v1/intakes/:id, ne celý balík z GET /v1/intakes/:id (bez items/progress/owner_tasks) — s novým stavem archived.
Je to vratný protějšek DELETE /v1/intakes/:id níže, které je nevratné — „odarchivování" momentálně neexistuje.
GET /v1/intakes/:id/download/preflight
Nahlásí, co by obsahoval ZIP ke stažení (níže), aniž by ho generoval — počet bajtů, jestli přesahuje limit velikosti, a kolik přístupů typu secret jde do stažení zahrnout. Co ZIP obsahuje a jak se řeší volba u přístupů popisuje Stažení všeho v ZIPu.
Odpověď
{
"files": 6,
"bytes": 18420531,
"skipped_files": 1,
"secrets": { "total": 2, "unrevealed": 1, "already_revealed": 1 },
"too_large": false,
"max_bytes": 524288000,
"filename": "podklady-bella-napoli-website-in_8f3kQmR2.zip"
}skipped_files počítá nahrané soubory, které ještě čekají na antivirovou kontrolu — do ZIPu se nedostanou a jmenovitě se uvedou v podklady.pdf/podklady.md. secrets.unrevealed udává, kolik položek typu secret by zůstalo dostupných pro jednorázové odhalení, pokud je při stahování vynecháte; secrets.already_revealed byly odhalené už dřív a vždy se zobrazí jako already revealed on <datum> bez ohledu na include_secrets. too_large odpovídá tomu, jestli by volání stažení níže vrátilo 413.
GET /v1/intakes/:id/download
Stáhne všechny odevzdané položky jako jeden ZIP: podklady.pdf a podklady.md (stejný obsah — jeden pro čtení, druhý pro stroje) se štítkem, typem, stavem, odevzdanou hodnotou, rozhodnutími a důvody prominutí u každé položky, plus jednu podsložku pro každou položku se soubory, obsahující klientovy soubory přesně tak, jak byly odevzdané.
Parametry dotazu
| Parametr | Typ | Popis |
|---|---|---|
include_secrets |
boolean | Odhalí a zahrne hodnoty položek typu secret do podklady.pdf. Výchozí false. Nikdy neovlivní podklady.md, který hodnoty secret nikdy nenese. |
Přijímá session z dashboardu nebo API klíč se scopem intakes:read (nebo admin), stejně jako čtení sběru podkladů. include_secrets=true navíc vyžaduje vlastní session vlastníka účtu, nebo klíč se scopem secrets:read/admin; jiný volající dostane 403 forbidden, reason secrets_owner_only. Zahrnutí přístupů spotřebuje jednorázové odhalení každého dosud neodhaleného — stejně jako GET /v1/intakes/:id/results nebo POST /v1/intakes/:id/items/:key/reveal — viz Trezor na přístupy. Položka odhalená už dřív se v obou případech zobrazí jako already revealed on <datum> místo hodnoty.
Vrací application/zip s hlavičkou Content-Disposition: attachment; filename="podklady-<projekt>-<id sběru podkladů>.zip". Nad limitem velikosti hlášeným v max_bytes z preflight endpointu se odmítne s 413 download_too_large. Zaznamená se jako audit event intake.downloaded.
DELETE /v1/intakes/:id
Trvale smaže sběr podkladů i všechny nahrané soubory. Akce je nevratná. Při úspěchu vrací HTTP 204.
Clients
Adresář lidí, kterým tento účet poslal sběr podkladů. Neexistuje pro to žádná tabulka klientů — je to pohled na intakes, seskupený case-insensitive podle e-mailu, takže zná i klienty z doby před vznikem tohoto endpointu a nemůže se rozejít s tím, co bylo doopravdy odesláno. Cena za to je stejná jako u každého pohledu: překlepnutá adresa se stane vlastní položkou a zmizí, jen když se smažou sběry podkladů, které ji nesou.
GET /v1/clients Vypíše klienty odvozené z minulých sběrů podkladůGET /v1/clients
Vypíše klienty, nejaktivnější první.
Parametry dotazu
| Parametr | Popis |
|---|---|
q |
Case-insensitive hledání podřetězce ve jméně a e-mailu klienta (1–100 znaků). |
limit |
Počet výsledků na stránku (výchozí 20, max 100). |
offset |
Posun stránkování (výchozí 0). |
Odpověď
{
"clients": [
{
"email": "jan@firma.cz",
"name": "Jan Novák",
"language": "cs",
"phone": null,
"timezone": "Europe/Prague",
"folder_id": "fld_a1b2c3",
"last_intake_id": "int_x9y8z7",
"last_intake_at": "2026-09-18T10:00:00.000Z",
"intake_count": 3
}
],
"total": 1,
"limit": 20,
"offset": 0
}name, phone a folder_id mohou být null, pokud je poslední sběr podkladů nikdy nevyplnil. name, language, phone, timezone a folder_id pocházejí z posledního sběru podkladů daného klienta; intake_count a last_intake_at/last_intake_id se počítají přes všechny jeho sběry podkladů. Výsledky jsou řazené podle intake_count sestupně, pak podle last_intake_at sestupně.
Poznámka: Přijímá session z dashboardu nebo API klíč se scopem
intakes:read, stejně jako GET /v1/intakes — API klíč vidí jen klienty ze sběrů podkladů ve svém vlastním režimu (test/live).
Folders
Jedna úroveň organizace sběrů podkladů, sdílená všemi na účtu — ne po jednotlivých uživatelích, a klient ji nikdy neuvidí: portál se o složce sběru podkladů nikdy nedozví. Pro zařazení použijte folder_id u POST /v1/intakes a PATCH /v1/intakes/:id, pro filtrování nebo hledání v seznamu folder_id/q u GET /v1/intakes.
GET /v1/folders Vypíše všechny složky
POST /v1/folders Založí složku
PATCH /v1/folders/:id Přejmenuje nebo přeřadí složku
DELETE /v1/folders/:id Smaže složkuGET /v1/folders
Vypíše všechny složky na účtu, seřazené podle sort_order a pak podle name.
Odpověď
{
"folders": [
{ "id": "fld_9k2mQxR7", "name": "Website projects", "sort_order": 0, "intake_count": 4, "created_at": "2024-03-01T09:00:00Z" },
{ "id": "fld_2wq8LpN3", "name": "Archived clients", "sort_order": 1, "intake_count": 0, "created_at": "2024-03-10T14:30:00Z" }
]
}intake_count počítá sběry podkladů, které v ní jsou zařazené, pořád existují a nejsou součástí smazaného účtu.
POST /v1/folders
Založí novou složku.
Požadavek
{ "name": "Website projects" }name se ořízne o bílé znaky a musí mít 1–80 znaků. Názvy složek jsou na účtu jedinečné bez ohledu na velikost písmen — duplicita vrátí 409 conflict (reason folder_exists).
Odpověď (HTTP 201) je objekt složky, stejný tvar jako jedna položka v GET /v1/folders.
PATCH /v1/folders/:id
Přejmenuje složku, změní její sort_order, nebo obojí. Všechna pole jsou nepovinná, ale aspoň jedno musí být zadané (jinak 400 invalid_request).
{ "name": "Website projects 2024" }Přejmenování na název, který už na účtu používá jiná složka, vrátí 409 conflict (reason folder_exists). Odpověď je aktualizovaný objekt složky.
DELETE /v1/folders/:id
Smaže složku. Každý sběr podkladů, který v ní byl zařazený, se přesune mezi nezařazené (folder_id se nastaví na null) — samotné sběry podkladů i jejich soubory zůstávají nedotčené. Při úspěchu vrací HTTP 204.
Templates
Uloží definici sběru podkladů jako znovupoužitelnou šablonu, ať u opakujících se typů projektů nemusíte znovu zadávat položky — ani žádné další nastavení. Úplný přehled polí a pravidlo „nastavení jsou výchozí hodnoty" viz templates.md.
GET /v1/templates Vypsat všechny šablony
POST /v1/templates Vytvořit šablonu z pole definic položek, volitelně i s nastavenímVytvoření šablony
POST /v1/templates vyžaduje přihlášenou session z dashboardu, ne API klíč — jako agent šablonu momentálně vytvořit nejde. Povinná jsou name a items; description, language a settings jsou nepovinné.
curl -X POST https://api.briefgate.dev/v1/templates \
-H "Cookie: bg_session=..." \
-H "Content-Type: application/json" \
-d '{
"name": "Restaurant Website",
"items": [...],
"settings": {
"chase_schedule": "custom",
"chase_interval": 5,
"chase_interval_unit": "days",
"due_in_days": 14
}
}'Slug šablony pak v define_intake (nebo POST /v1/intakes) předáte jako "template": "web-restaurant" místo ručního výčtu items — items je v požadavku povinné i tak (viz známé omezení v templates.md). Každé nastavení, které šablona nese, se použije jako výchozí hodnota: doplní jen pole, která požadavek na založení sběru sám nevyplnil, a due_in_days se v okamžiku založení přepočítá na skutečné due_date.
Webhooks
BriefGate spouští webhooky při změnách stavu sběru podkladů. Každý obsah nese event, intake_id a timestamp a k tomu pole patřící dané události.
Každá cesta níže potřebuje na API klíči scope admin (endpoint dostává všechny události na celém účtu) — intakes:read/intakes:write nestačí. Session z dashboardu smí seznam číst, ale endpoint zaregistrovat, odebrat, otestovat nebo zopakovat doručení smí jen vlastník účtu (jiný člen dostane 403 forbidden).
GET /v1/webhooks Vypsat nastavené endpointy
POST /v1/webhooks Zaregistrovat nový endpoint
DELETE /v1/webhooks/:id Odebrat endpoint
GET /v1/webhooks/:id/deliveries Historie doručení (posledních 100 pokusů)
POST /v1/webhooks/:id/test Poslat na endpoint testovací událost
POST /v1/webhooks/:id/deliveries/:deliveryId/retry Ručně zopakovat jedno doručeníRegistrace webhooku
curl -X POST https://api.briefgate.dev/v1/webhooks \
-H "Authorization: Bearer bg_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/webhooks/briefgate",
"events": ["intake.completed", "item.submitted"]
}'Podpisové tajemství generuje BriefGate a vrátí ho jednou v odpovědi — vy ho neposíláte. Přidáním "format": "slack" nebo "format": "discord" se místo na váš server doručuje do chatového kanálu.
Každý požadavek webhooku BriefGate podepisuje pomocí HMAC-SHA256 v hlavičce X-BriefGate-Signature. Než obsah zpracujete, ověřte podpis svým secret.
Události
| Událost | Spustí se, když |
|---|---|
item.submitted |
Klient nahrál nebo vyplnil položku. |
intake.completed |
Byly odeslány všechny povinné položky. |
client.viewed |
Klient otevřel svůj portál. |
chase.bounced |
Upomínka se natvrdo odrazila nebo byla nahlášena jako spam. |
intake.stalled |
Sběr podkladů vyčerpal povolený počet upomínek, aniž by byl dokončen. |
intake.overdue |
Uplynul termín a povinné položky pořád chybí (spustí se jednou za sběr podkladů). |
intake.archived |
Sběr podkladů byl archivován přes POST /v1/intakes/:id/archive. |
Tahle sedmice je jediná přijímaná; cokoli jiného se při registraci endpointu odmítne. Obsahy jednotlivých událostí najdete v webhooks.md.
Zopakování doručení
Když endpoint nevrátil 2xx, BriefGate ho už zkusil znovu podle automatického rozvrhu (ihned, pak +1 min, +5 min, +30 min, +2 h, +6 h — celkem 6 pokusů), než ho označil jako failed. Tohle stejné doručení zařadí do fronty ručně, přes stejnou cestu jako každé jiné odeslání — kontrola proti SSRF, čerstvě spočítaný podpis, zápis do logu jako každý jiný pokus. attempts se nevynuluje: doručení, které už vyčerpalo všech 6 pokusů, jede dál odtud, kde skončilo, takže tohle koupí přesně jeden pokus navíc, ne nový žebřík — pokud chcete víc, opravte nejdřív endpoint.
curl -X POST https://api.briefgate.dev/v1/webhooks/whe_2f9k/deliveries/whd_9f8e7d6c5b4a/retry \
-H "Authorization: Bearer bg_live_xxxxx"{
"delivery": {
"id": "whd_9f8e7d6c5b4a",
"event": "intake.completed",
"status": "pending",
"attempts": 6,
"response_code": 500,
"error": null,
"next_retry_at": "2026-07-18T09:12:00Z",
"created_at": "2026-07-18T09:11:00Z",
"delivered_at": null
}
}404 not_found, pokud endpoint nebo doručení na tomhle účtu neexistuje. 409 conflict (reason already_delivered), pokud se doručení už povedlo — poslat ho znovu by událost na druhé straně zdvojilo. 409 conflict (reason endpoint_inactive), pokud byl endpoint mezitím vypnutý — nejdřív ho zapněte zpátky.
Účet a fakturace
GET /v1/account Údaje o účtu a aktuální tarif
PATCH /v1/account Změna nastavení účtu (název, výchozí jazyk, retention_days, portal_link_ttl_days a další)
POST /v1/account/logo Nahrání loga zobrazeného v portálu a e-mailech (multipart `file`; jen dashboardová session)
DELETE /v1/account/logo Odstranění loga
POST /v1/account/signature Nahrání podpisu do e-mailů (vizitka), který se vykreslí na konci každého e-mailu pro vaše klienty (multipart `file`, PNG/JPEG/WebP; jen dashboardová session)
DELETE /v1/account/signature Odstranění podpisu
GET /v1/usage Spotřeba za aktuální období proti limitům tarifu
GET /v1/audit Stránkovaný auditní log akcí API a uživatelů (jen session, jen vlastník účtu)
POST /v1/billing/checkout Založení Stripe Checkout session pro přechod na vyšší tarif
POST /v1/billing/portal Založení session zákaznického portálu Stripe pro správu předplatnéhoOdpověď o spotřebě
{
"period": "2024-03",
"intakes": { "used": 12, "limit": 50 },
"storage_bytes": { "used": 524288000, "limit": 5368709120 }
}Sedadla v týmu. Sedadlo je člověk, který se přihlašuje do dashboardu — klienti žádné nezabírají, protože otevírají jen odkaz, který dostali e-mailem. Každá cesta níže je jen s dashboardovou session; nezavolá je žádný API klíč, ani se scopem admin — kromě přijetí pozvánky, které se místo toho prokáže tokenem pozvánky a session vůbec nepotřebuje. Seznam smí číst kterýkoli přihlášený člen; zvát, rušit pozvánku a odebírat člena smí jen vlastník (jiný dostane 403 forbidden).
GET /v1/team Vypsat členy a čekající pozvánky
POST /v1/team/invites Pozvat e-mail do sedadla (jen vlastník)
DELETE /v1/team/invites/:id Zrušit čekající pozvánku (jen vlastník)
POST /v1/team/invites/accept Přijmout pozvánku — bez session, prokazuje se tokenem
DELETE /v1/team/members/:id Odebrat člena (jen vlastník)GET /v1/team
Vrátí aktuální členy a k tomu pozvánky, které ještě čekají a nevypršely.
Odpověď
{
"members": [
{ "id": "usr_9f3kqmr2", "email": "marco@bellanapoli.com", "name": "Marco Esposito", "role": "owner", "created_at": "2026-01-10T09:00:00Z", "last_login_at": "2026-09-04T08:12:00Z" }
],
"invites": [
{ "id": "tin_7h2jvw4x", "email": "giulia@bellanapoli.com", "role": "member", "created_at": "2026-09-01T10:00:00Z", "expires_at": "2026-09-08T10:00:00Z" }
]
}POST /v1/team/invites
Pozve e-mailovou adresu do koupeného sedadla. Každá pozvánka dává roli member — pozvat druhého vlastníka nejde.
Tělo požadavku
| Pole | Typ | Povinné | Popis |
|---|---|---|---|
email |
string | Ano | Adresa k pozvání. Převede se na malá písmena; max. 320 znaků. |
Odpověď (HTTP 201)
{ "id": "tin_7h2jvw4x", "email": "giulia@bellanapoli.com", "role": "member", "created_at": "2026-09-05T10:00:00Z", "expires_at": "2026-09-12T10:00:00Z" }Pozvánka přijde e-mailem s odkazem platným 7 dní. Další pozvání stejné adresy nahradí tu předchozí — funguje vždy jen ten nejnovější odkaz.
402 quota_exceeded (reason seats), jakmile členové a čekající pozvánky dohromady zaplní kvótu sedadel tarifu — zrušte čekající pozvánku, odeberte člena, nebo si dokupte sedadlo navíc. 400 invalid_request, pokud daná adresa už na tomhle účtu patří členovi. 429 rate_limited (reason team_invites) nad 20 pozvánek na účet za hodinu.
DELETE /v1/team/invites/:id
Zruší čekající pozvánku. 404 not_found, pokud na tomhle účtu neexistuje. 400 invalid_request, pokud už byla přijatá — pak není co rušit. Vrací { "ok": true, "id": "tin_7h2jvw4x" }.
POST /v1/team/invites/accept
Bez autentizace — prokazuje se tokenem pozvánky, stejně jako odkaz na reset hesla. Založí uživatele v roli member, rovnou ho přihlásí a nastaví session cookie.
Tělo požadavku
| Pole | Typ | Povinné | Popis |
|---|---|---|---|
token |
string | Ano | Token z odkazu v e-mailu s pozvánkou. |
name |
string | Ano | Zobrazované jméno nového člena. |
password |
string | Ano | Aspoň 12 znaků. |
Odpověď (HTTP 201)
{
"user": { "id": "usr_2k9fjbrt", "email": "giulia@bellanapoli.com", "name": "Giulia", "role": "member" },
"account": { "id": "acc_8j3nq2mv", "name": "Bella Napoli", "tier": "agency" }
}401 unauthorized („That invitation link is not valid or has expired.") pro token, který je neznámý, už přijatý, nebo propadlý — schválně jedna odpověď pro všechny tři případy, stejně jako u resetu hesla. 400 invalid_request („An account with this email already exists.") pokud pozvaná adresa už jinde má uživatele. 402 quota_exceeded (reason seats), pokud se sedadlo zaplnilo mezi odesláním pozvánky a jejím přijetím — kvóta se ověřuje znovu i tady, ne jen při založení pozvánky.
DELETE /v1/team/members/:id
Odebere člena: uživatele soft-smaže a okamžitě mu ukončí úplně všechny relace. 400 invalid_request, pokud :id je vaše vlastní id („You cannot remove your own account this way.") nebo patří vlastníkovi účtu („The account owner cannot be removed."). 404 not_found, pokud neodpovídá existujícímu členovi na tomhle účtu. Vrací { "ok": true, "id": "usr_2k9fjbrt" }.
Veřejné endpointy
Tyhle endpointy nevyžadují autentizaci a jsou určené ke strojovému zpracování.
| Endpoint | Popis |
|---|---|
GET /pricing.json |
Strojově čitelné tarify, limity a příznaky funkcí. Agent podle nich pozná, jaký tarif doporučit, nebo si před zakládáním sběru podkladů ověří kvótu. |
GET /v1/openapi.json |
Specifikace OpenAPI 3.1 pro celé API. Naimportujte do Postmanu, vygenerujte SDK nebo předejte agentovi, ať si API projde sám. |
GET /healthz |
Liveness sonda. Vrací HTTP 200 s {"status":"ok"}, pokud proces API běží. |
GET /readyz |
Readiness sonda. Vrací HTTP 200 jen tehdy, když je v pořádku proces API i všechny závislosti (databáze, objektové úložiště, poštovní provider). Během nasazování a výpadků vrací HTTP 503. |