Integriere BuildTailor in Minuten
REST-Endpunkte mit Bearer-Token-Auth + signierte Outbound-Webhooks. cURL-, JavaScript- und Python-Beispiele inklusive — und Live-Test direkt aus der Doku.
Quickstart
Drei Schritte vom Account zum ersten erfolgreichen Aufruf.
- 1API-Key erstellenUnter Einstellungen → Integrations einen neuen Schlüssel anlegen. Das Plaintext-Secret wird einmalig angezeigt.
- 2Request sendenAuthorization-Header setzen und einen GET-Request gegen /api/v1/me schießen.
- 3Webhooks abonnierenOptional: Webhook-URL eintragen und Events wählen. Wir signieren jeden Versand per HMAC-SHA256.
# 1) Verifizieren, dass dein Key tickt
curl https://app.buildtailor.com/api/v1/me \
-H "Authorization: Bearer sb_<dein_key>"
# 2) Templates auflisten
curl https://app.buildtailor.com/api/v1/templates?limit=10 \
-H "Authorization: Bearer sb_<dein_key>"Authentifizierung
Alle Endpunkte erwarten einen Bearer-Token im Authorization-Header.
Beim Anlegen eines API-Keys bekommst du einen Plaintext-Token im Format sb_<prefix>_<secret>. Der Server speichert nur den SHA-256-Hash — du musst den Token sicher aufbewahren.
Authorization: Bearer sb_<prefix>_<secret>- read — GET auf Templates, Members, Workspace-Metadaten.
- write — Reserviert für zukünftige POST/PUT/DELETE-Endpunkte (Templates, Invites).
Endpunkte
Alle Endpunkte unter /api/v1. JSON-Responses, paginiert via limit-Parameter.
/api/v1/meGibt das aktive Tenant + Scope-Info des API-Keys zurück. Perfekt für eine 'API-Key gültig?'-Probe.
curl https://app.buildtailor.com/api/v1/me \
-H "Authorization: Bearer sb_<key>"Beispiel-Response
{
"tenant": {
"id": "f9c8…",
"name": "Acme GmbH",
"slug": "acme",
"subscription_tier": "Trial",
"created_at": "2026-…"
},
"api_key": { "id": "8a2b…", "scopes": ["read"] }
}/api/v1/templatesListet alle Mail-Templates des Workspaces. Optional: ?limit=1-100 und ?category=Onboarding|Transactional|Marketing|System|Custom.
curl "https://app.buildtailor.com/api/v1/templates?limit=50&category=Onboarding" \
-H "Authorization: Bearer sb_<key>"Beispiel-Response
{
"data": [
{
"id": "ab12…",
"name": "Willkommens-Mail",
"category": "Onboarding",
"default_locale": "de-DE",
"subject": "Willkommen bei {{workspace_name}}…",
"variables": [
{ "name": "first_name", "label": "Vorname", "example": "Anna" }
],
"is_default": true,
"updated_at": "2026-…"
}
],
"count": 1
}/api/v1/templates/{id}Detail-View eines einzelnen Templates inklusive aller Locale-Übersetzungen (Subject + Markdown-Body).
curl https://app.buildtailor.com/api/v1/templates/ab12… \
-H "Authorization: Bearer sb_<key>"/api/v1/membersListet alle Workspace-Mitglieder mit Rolle, Beitrittsdatum, E-Mail und Anzeigename.
curl https://app.buildtailor.com/api/v1/members \
-H "Authorization: Bearer sb_<key>"BuildTailor · Projekte, Tickets, Attachments
Alle BT-Endpoints teilen sich Auth (Bearer sb_...), Rate-Limit (120 req/min pro Key) und Response-Envelope{ data, page?, limit?, total? }.
/api/v1/projectsProjekte des Workspace listen. Query: ?status=&page=&limit= (max. 100).
curl "https://app.buildtailor.com/api/v1/projects?status=active&limit=50" \
-H "Authorization: Bearer sb_<key>"/api/v1/projectsNeues Projekt anlegen. Body: name (2..200), code?, address?, status?, kind (bau|fm).
curl -X POST https://app.buildtailor.com/api/v1/projects \
-H "Authorization: Bearer sb_<key>" \
-H "Content-Type: application/json" \
-d '{"name":"BV Musterstrasse 12","kind":"bau","status":"active"}'/api/v1/ticketsTickets listen. Query: ?project_id=&status=&priority=&page=&limit=. Sortierung: neueste zuerst.
curl "https://app.buildtailor.com/api/v1/tickets?project_id=<uuid>&status=offen" \
-H "Authorization: Bearer sb_<key>"/api/v1/ticketsNeues Ticket. Body: project_id, title, description?, priority?, trade?, category?, due_date?, assignee_id?, company_id?. Number wird automatisch vergeben.
curl -X POST https://app.buildtailor.com/api/v1/tickets \
-H "Authorization: Bearer sb_<key>" \
-H "Content-Type: application/json" \
-d '{"project_id":"<uuid>","title":"Riss in Aussenwand EG","priority":"hoch","trade":"Rohbau"}'/api/v1/tickets/{id}Teil-Update. Status-Wechsel folgen der State-Machine — ungueltige Uebergaenge = 400 transition_forbidden.
curl -X PATCH https://app.buildtailor.com/api/v1/tickets/<uuid> \
-H "Authorization: Bearer sb_<key>" \
-H "Content-Type: application/json" \
-d '{"status":"in_arbeit","assignee_id":"<uuid>"}'/api/v1/attachmentsAttachments listen. Query: ?project_id=&entity_id=&mime_prefix=&signed_url=true. signed_url=true fuegt zeitlich begrenzte Download-URLs (60s) hinzu.
curl "https://app.buildtailor.com/api/v1/attachments?project_id=<uuid>&mime_prefix=image/&signed_url=true" \
-H "Authorization: Bearer sb_<key>"Webhooks
Outbound POST-Requests an deinen Endpunkt bei wichtigen Workspace-Events.
Jeder Versand trägt eine HMAC-Signatur im X-SaaSBase-Signature Header, identisch zum Stripe-Format:
X-SaaSBase-Signature: t=<unixSeconds>,v1=<hmac-sha256-hex>Signierter Payload ist <unixSeconds>.<rawBody>
Verfügbare Events
Subscribe pro Webhook gezielt nur die Events, die dich interessieren — oder '*' für alle.
| Event | Wann? |
|---|---|
invite.created | Beim Anlegen einer neuen Einladung im Workspace. |
invite.accepted | Wenn jemand die Einladung annimmt und Member wird. |
invite.revoked | Wenn ein Owner/Admin die Einladung widerruft. |
member.role_changed | Wenn die Rolle eines Members geändert wird. |
template.created | Wenn ein neues Mail-Template angelegt wurde. |
template.updated | Wenn ein Template gespeichert wurde (Meta oder Inhalt). |
template.deleted | Wenn ein Template gelöscht wurde. |
bt.project.created | Neues Projekt in BuildTailor angelegt (via UI oder API). |
bt.ticket.created | Neuer Mangel/Ticket angelegt — Payload enthaelt project_id, number, priority, assignee_id, trade. |
bt.ticket.updated | Felder eines Tickets geaendert (kein Status-Wechsel) — Payload enthaelt fields=[...]. |
bt.ticket.status_changed | Status-Wechsel eines Tickets — Payload enthaelt from/to. |
bt.attachment.uploaded | Neues Attachment (Foto etc.) an Ticket oder Kommentar. |
Signatur verifizieren
Im Receiver: Header parsen, HMAC neu berechnen, mit timingSafeEqual vergleichen. Timestamp-Drift > 5 Min verwerfen (Replay-Schutz).
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(",").map(kv => kv.split("=")));
const t = parseInt(parts.t, 10);
if (Math.abs(Math.floor(Date.now() / 1000) - t) > 300) return false;
const expected = createHmac("sha256", secret)
.update(`${t}.${rawBody}`).digest("hex");
const a = Buffer.from(expected, "hex");
const b = Buffer.from(parts.v1, "hex");
return a.length === b.length && timingSafeEqual(a, b);
}Fehlercodes
Standard-HTTP-Codes. Body bei Fehlern: {"error": "<message>"}.
| Status | Meaning | Hint |
|---|---|---|
| 200 | OK | Request erfolgreich. |
| 400 | Bad Request | Ungültige Parameter oder Body. |
| 401 | Unauthorized | Bearer-Token fehlt, ungültig oder widerrufen. Auch: fehlender Scope. |
| 404 | Not Found | Ressource existiert nicht oder gehört nicht zu deinem Tenant. |
| 500 | Server Error | Unerwarteter Fehler. Hilf uns bitte mit Support-Ticket. |
Bereit zum Loslegen?
Hol dir deinen ersten API-Key in 30 Sekunden — und integriere ohne Discovery-Call.