# 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.
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.
Returns the current health status of the Bureau API. Use this to verify connectivity and uptime.
Response
{
"status": "ok"
}
Examples
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" }
Submit a new service request through a Bureau portal. This is the main endpoint your clients' portals use to submit briefs.
Parameters
| Name | Type | Description |
|---|---|---|
| slugrequired | string | Your agency portal slug (e.g. "mon-agence") |
| clientNamerequired | string | Full name of the client submitting the request |
| clientEmailrequired | string | Client email address for notifications |
| servicerequired | string | Service type (e.g. "seo-article", "newsletter", "linkedin-post") |
| briefrequired | string | Detailed brief / instructions for the deliverable |
Response
{
"ok": true,
"ref": "REQ-20260412-A7X3"
}
Examples
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" }
Retrieve the tracking pixel IDs configured for the Bureau platform. Returns Meta (Facebook), GA4, and TikTok pixel identifiers.
Response
{
"meta": "123456789012345",
"ga4": "G-XXXXXXXXXX",
"tiktok": "CXXXXXXXXXXXXXXXXX"
}
Examples
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" }
Track a custom event for analytics purposes. Used internally by Bureau landing pages and portals, but available for custom integrations.
Parameters
| Name | Type | Description |
|---|---|---|
| eventrequired | string | Event name (e.g. "landing_cta_click", "portal_view", "deliverable_download") |
| pagerequired | string | Page or context identifier (e.g. "freelance", "portal/mon-agence") |
Response
{
"ok": true
}
Examples
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 }
Add a user to the Bureau waitlist. Used on pre-launch pages and gated features to collect interest.
Parameters
| Name | Type | Description |
|---|---|---|
| emailrequired | string | Email address of the interested user |
| firstNamerequired | string | First name of the user |
| agencyNamerequired | string | Desired agency name or brand |
Response
{
"success": true
}
Examples
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 }
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
{
"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 -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.
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.
{
"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
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
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
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"
}
}