# Authentication

Bureau API uses Bearer token authentication. Obtain your access token from Supabase Auth after signing in to your Bureau account. Include it in the Authorization header on every authenticated request.

Getting your token

Sign in to Bureau and retrieve your session token from the Supabase auth response. The token is a JWT that expires after 1 hour. Use the refresh token to obtain a new access token when needed.

Header Authorization: Bearer YOUR_SUPABASE_ACCESS_TOKEN Content-Type: application/json

Public endpoints (/api/health, /api/pixels, /api/waitlist, /api/track) do not require authentication. The /api/portal-submit endpoint accepts both authenticated and public requests (public submissions are linked by slug). The /api/analytics endpoint requires a valid Bearer token.

# Endpoints

All endpoints are served from https://www.bureau-app.com. Responses are JSON with UTF-8 encoding.

GET /api/health

Returns the current health status of the Bureau API. Use this to verify connectivity and uptime.

Response

200 OK
{ "status": "ok" }

Examples

cURL
JavaScript
curl -X GET https://www.bureau-app.com/api/health
const response = await fetch('https://www.bureau-app.com/api/health'); const data = await response.json(); console.log(data); // { status: "ok" }
POST /api/portal-submit

Submit a new service request through a Bureau portal. This is the main endpoint your clients' portals use to submit briefs.

Parameters

NameTypeDescription
slugrequiredstringYour agency portal slug (e.g. "mon-agence")
clientNamerequiredstringFull name of the client submitting the request
clientEmailrequiredstringClient email address for notifications
servicerequiredstringService type (e.g. "seo-article", "newsletter", "linkedin-post")
briefrequiredstringDetailed brief / instructions for the deliverable

Response

200 OK
{ "ok": true, "ref": "REQ-20260412-A7X3" }

Examples

cURL
JavaScript
curl -X POST https://www.bureau-app.com/api/portal-submit \ -H "Content-Type: application/json" \ -d '{ "slug": "mon-agence", "clientName": "Jean Dupont", "clientEmail": "jean@example.com", "service": "seo-article", "brief": "Article SEO de 1500 mots sur le marketing digital en 2026. Mots-cles: marketing IA, automatisation, ROI." }'
const response = await fetch('https://www.bureau-app.com/api/portal-submit', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ slug: 'mon-agence', clientName: 'Jean Dupont', clientEmail: 'jean@example.com', service: 'seo-article', brief: 'Article SEO de 1500 mots sur le marketing digital en 2026.' }) }); const data = await response.json(); console.log(data); // { ok: true, ref: "REQ-20260412-A7X3" }
GET /api/pixels

Retrieve the tracking pixel IDs configured for the Bureau platform. Returns Meta (Facebook), GA4, and TikTok pixel identifiers.

Response

200 OK
{ "meta": "123456789012345", "ga4": "G-XXXXXXXXXX", "tiktok": "CXXXXXXXXXXXXXXXXX" }

Examples

cURL
JavaScript
curl -X GET https://www.bureau-app.com/api/pixels
const response = await fetch('https://www.bureau-app.com/api/pixels'); const data = await response.json(); console.log(data); // { meta: "123456789012345", ga4: "G-XXXXXXXXXX", tiktok: "CXXXXXXXXXXXXXXXXX" }
POST /api/track

Track a custom event for analytics purposes. Used internally by Bureau landing pages and portals, but available for custom integrations.

Parameters

NameTypeDescription
eventrequiredstringEvent name (e.g. "landing_cta_click", "portal_view", "deliverable_download")
pagerequiredstringPage or context identifier (e.g. "freelance", "portal/mon-agence")

Response

200 OK
{ "ok": true }

Examples

cURL
JavaScript
curl -X POST https://www.bureau-app.com/api/track \ -H "Content-Type: application/json" \ -d '{ "event": "landing_cta_click", "page": "freelance" }'
const response = await fetch('https://www.bureau-app.com/api/track', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ event: 'landing_cta_click', page: 'freelance' }) }); const data = await response.json(); console.log(data); // { ok: true }
POST /api/waitlist

Add a user to the Bureau waitlist. Used on pre-launch pages and gated features to collect interest.

Parameters

NameTypeDescription
emailrequiredstringEmail address of the interested user
firstNamerequiredstringFirst name of the user
agencyNamerequiredstringDesired agency name or brand

Response

200 OK
{ "success": true }

Examples

cURL
JavaScript
curl -X POST https://www.bureau-app.com/api/waitlist \ -H "Content-Type: application/json" \ -d '{ "email": "marie@example.com", "firstName": "Marie", "agencyName": "Studio Creatif" }'
const response = await fetch('https://www.bureau-app.com/api/waitlist', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: 'marie@example.com', firstName: 'Marie', agencyName: 'Studio Creatif' }) }); const data = await response.json(); console.log(data); // { success: true }
GET /api/analytics Auth required

Retrieve analytics data for your Bureau agency. Requires a valid Bearer token from Supabase auth. Returns aggregated metrics including revenue, top services, and advanced breakdowns.

Authentication required

This endpoint requires a valid Authorization: Bearer TOKEN header. Unauthenticated requests will receive a 401 Unauthorized response.

Response

200 OK
{ "header": { "totalRevenue": 12450, "activeClients": 23, "deliveriesThisMonth": 87, "avgDeliveryTime": "2.4h" }, "topServices": [ { "name": "seo-article", "count": 42, "revenue": 6300 }, { "name": "newsletter", "count": 28, "revenue": 3360 }, { "name": "linkedin-post", "count": 17, "revenue": 2790 } ], "advanced": { "conversionRate": 0.73, "repeatClientRate": 0.61, "avgOrderValue": 143, "revenueByMonth": [ { "month": "2026-01", "revenue": 2100 }, { "month": "2026-02", "revenue": 3400 }, { "month": "2026-03", "revenue": 4200 } ] } }

Examples

cURL
JavaScript
curl -X GET https://www.bureau-app.com/api/analytics \ -H "Authorization: Bearer YOUR_SUPABASE_ACCESS_TOKEN"
const token = 'YOUR_SUPABASE_ACCESS_TOKEN'; const response = await fetch('https://www.bureau-app.com/api/analytics', { headers: { 'Authorization': `Bearer ${token}` } }); if (!response.ok) { throw new Error(`Auth failed: ${response.status}`); } const data = await response.json(); console.log('Revenue:', data.header.totalRevenue); console.log('Top service:', data.topServices[0].name); console.log('Conversion rate:', data.advanced.conversionRate);

# Rate Limits

Bureau API enforces rate limits to ensure fair usage and platform stability. Limits are applied per IP address.

30

Requests per minute per IP

All endpoints share a single rate limit window. When you exceed the limit, the API responds with 429 Too Many Requests and a Retry-After header indicating how many seconds to wait.

429 Response { "error": "rate_limit_exceeded", "message": "Too many requests. Please retry after 23 seconds.", "retryAfter": 23 }

Best practices

Implement exponential backoff when you receive a 429 response. Cache responses from /api/pixels and /api/health locally to reduce unnecessary calls. If you need higher limits for production integrations, contact us at hello@bureau-app.com.

# Webhooks

Bureau sends outgoing webhook payloads to your configured URL when key events occur. Configure your webhook endpoint in your Bureau dashboard under Settings → Integrations → Webhooks.

Webhook delivery

Webhooks are sent as POST requests with a JSON body. Bureau expects a 2xx response within 10 seconds. Failed deliveries are retried up to 3 times with exponential backoff (30s, 5min, 30min). Each request includes an X-Bureau-Signature header for payload verification.

request.created

Fired when a client submits a new brief through a portal

Use this to trigger automations, send Slack notifications, or sync new requests to your project management tool.

{ "event": "request.created", "timestamp": "2026-04-12T14:32:00Z", "data": { "ref": "REQ-20260412-A7X3", "slug": "mon-agence", "clientName": "Jean Dupont", "clientEmail": "jean@example.com", "service": "seo-article", "brief": "Article SEO de 1500 mots sur le marketing digital en 2026.", "status": "pending" } }

request.delivered

Fired when a deliverable is sent to the client

Triggered after you approve and deliver the AI-generated content. Includes the delivery metadata and payment status.

{ "event": "request.delivered", "timestamp": "2026-04-12T15:10:00Z", "data": { "ref": "REQ-20260412-A7X3", "slug": "mon-agence", "clientName": "Jean Dupont", "clientEmail": "jean@example.com", "service": "seo-article", "status": "delivered", "deliveredAt": "2026-04-12T15:10:00Z", "paymentStatus": "paid", "amount": 250 } }

rating.received

Fired when a client rates a delivered request

Track client satisfaction and trigger follow-up workflows based on the rating score.

{ "event": "rating.received", "timestamp": "2026-04-12T16:45:00Z", "data": { "ref": "REQ-20260412-A7X3", "slug": "mon-agence", "clientName": "Jean Dupont", "clientEmail": "jean@example.com", "rating": 5, "comment": "Excellent travail, exactement ce que je voulais !", "service": "seo-article" } }