Brigada API
v1.0.0Server-to-server event ingestion API for Brigada MMP. Send conversion and behavioural events from your backend to Brigada for attribution and CAPI forwarding.
Servers
| Environment | Base URL |
|---|---|
| Production | https://api.brigada.onestepsocial.com/v1 |
| Staging | https://api.brigada-staging.onestepsocial.com/v1 |
Authentication
Choose one of two auth options on every request:
Supabase JWT — for dashboard integrations
Authorization: Bearer <supabase_jwt> — the JWT must contain app_metadata.merchant_id.
API key — for programmatic server-to-server access
x-api-key: <key> combined with x-merchant-id: <merchant_id>. The API key is issued from the OneStepSocial dashboard.
Endpoints
Ingest an event
Accepts a single server-side event. Validated, deduplicated, enriched, and forwarded to Meta CAPI and Google Ads API asynchronously via SQS.
Request body — Event (required)
| Field | Type | Required | Description |
|---|---|---|---|
| event_id | string (1–128 chars) | yes | Unique ID for this event. Used for deduplication. |
| merchant_id | string (3–64 chars) | yes | Your merchant identifier. Must match authenticated identity. |
| timestamp | string (date-time) | yes | ISO 8601 UTC timestamp of when the event occurred. |
| event_type | enum | yes | One of the Event Types listed below. |
| user_identity | object | yes | At least one of hashed_email, external_user_id, or device_id. |
| event_data | object | — | Value, currency, user status, package tier, product category, metadata. |
| source | object | — | Platform and originating IP address. |
| attribution | object | — | Media source, campaign, ad set/creative, click IDs, UTMs, deep-link resolution. |
| session_id | string (1–128 chars) | — | Connects multiple events from the same user visit. |
| device | object | — | Device type, OS, browser, model, IDFA/GAID, install referrer. |
| location | object | — | Country (ISO 3166-1 alpha-2), city, region. |
| api_version | enum ['1.0'] | — | API version this payload was built against. |
user_identity — at least one of hashed_email, external_user_id, or device_id is required:
| Field | Type | Required | Description |
|---|---|---|---|
| hashed_email | string (pattern: ^[a-f0-9]{64}$) | — | SHA-256 hex digest of the lowercased, trimmed email address. |
| transaction_id | string (≤128 chars) | — | — |
| external_user_id | string (≤256 chars) | — | — |
| device_id | string (8–128 chars) | — | Stable per-install device identifier, generated and persisted by the Scout SDK before any email/signup identity is known. |
event_data:
| Field | Type | Required | Description |
|---|---|---|---|
| value | number (≥0) | — | — |
| currency | enum: USD, EUR, GBP, CAD, AUD, INR, JPY, MXN | — | — |
| user_status | enum: NEW, RETURNING, DORMANT, AT_RISK | — | — |
| package_tier | enum: FREE, BASIC, PREMIUM, ENTERPRISE, CUSTOM | — | — |
| product_category | string (≤64 chars) | — | — |
| metadata | object (string/number/boolean values, ≤20 keys) | — | — |
source:
| Field | Type | Required | Description |
|---|---|---|---|
| platform | enum: WEB, MOBILE_IOS, MOBILE_ANDROID, API, BACKEND, WEBHOOK | — | — |
| ip_address | string (≤45 chars) | — | — |
attribution — all fields optional; pass what you have, even media_source alone unlocks paid vs. organic splits in the dashboard:
| Field | Type | Required | Description |
|---|---|---|---|
| media_source | string (≤128 chars) | — | Ad network or traffic source (e.g. "facebook", "google", "tiktok", "organic"). |
| campaign | string (≤256 chars) | — | Campaign name or ID from your ad platform. |
| ad_set | string (≤256 chars) | — | Ad set or ad group name. |
| ad_creative | string (≤256 chars) | — | Ad creative name or ID. |
| click_id | string (≤512 chars) | — | Platform click ID (fbclid, gclid, ttclid, etc.) for CAPI matching. |
| utm_source | string (≤256 chars) | — | — |
| utm_medium | string (≤256 chars) | — | — |
| utm_campaign | string (≤256 chars) | — | — |
| deep_link_resolution | object | — | Populated by the Scout SDK when resolving a deferred deep link on install. Requires method (universal_link | none); optional link_id, matched_at. |
device:
| Field | Type | Required | Description |
|---|---|---|---|
| type | enum: DESKTOP, MOBILE, TABLET, OTHER | — | — |
| os | string (≤64 chars) | — | e.g. "iOS 17", "Android 14". |
| browser | string (≤64 chars) | — | e.g. "Safari", "Chrome". |
| model | string (≤128 chars) | — | e.g. "iPhone 15 Pro". |
| idfa | string (≤64 chars) | — | iOS advertising identifier. Only present when ATT consent was granted. |
| gaid | string (≤64 chars) | — | Android advertising identifier. Only present when consent was granted and the OS did not nullify it. |
| install_referrer | object | — | Populated by the Scout SDK from Android's Install Referrer API. Fields: raw, click_timestamp, install_timestamp, source (google_play). |
location — prefer deriving from your server's request IP rather than client-reported values:
| Field | Type | Required | Description |
|---|---|---|---|
| country | string (2 chars) | — | ISO 3166-1 alpha-2 country code (e.g. "US", "GB", "DE"). |
| city | string (≤128 chars) | — | — |
| region | string (≤128 chars) | — | State or region name. |
Example — transaction completed (with attribution)
{
"event_id": "evt-a1b2c3d4",
"merchant_id": "acme-corp",
"timestamp": "2026-05-24T14:00:00Z",
"event_type": "TRANSACTION_COMPLETED",
"user_identity": {
"hashed_email": "a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4"
},
"event_data": {
"value": 99,
"currency": "USD"
},
"attribution": {
"media_source": "facebook",
"campaign": "summer_sale_2026",
"ad_set": "retargeting_us",
"utm_source": "facebook",
"utm_medium": "cpc"
},
"session_id": "sess-abc123xyz",
"device": {
"type": "MOBILE",
"os": "iOS 17",
"browser": "Safari"
},
"location": {
"country": "US",
"city": "New York"
},
"source": {
"platform": "BACKEND"
},
"api_version": "1.0"
}Example — minimal event (no attribution)
{
"event_id": "evt-b2c3d4e5",
"merchant_id": "acme-corp",
"timestamp": "2026-05-24T14:00:00Z",
"event_type": "USER_SIGNUP",
"user_identity": {
"hashed_email": "a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4"
},
"source": {
"platform": "BACKEND"
},
"api_version": "1.0"
}Responses
| Status | Description |
|---|---|
| 202 | Event accepted and queued for processing. Body: { "status": "accepted" }. |
| 400 | Invalid request body or schema validation failure. Body: Error. |
| 401 | Missing or invalid authentication. Body: Error. |
| 403 | merchant_id in body does not match authenticated identity. Body: Error. |
Example 202 response body:
{
"status": "accepted"
}Example error response body (400/401/403):
{
"error": "validation_failed",
"errors": [
"event_type is required",
"user_identity must include one of hashed_email, external_user_id, device_id"
]
}Event Types
event_type must be one of the following values:
TRANSACTION_COMPLETEDTRANSACTION_INITIATEDUSER_LOGINUSER_SIGNUPPRICING_PAGE_VIEWEDFEATURE_COMPARISON_VIEWEDDATA_CONNECT_SUCCESSPAYMENT_METHOD_ADDEDSUBSCRIPTION_TIER_UPGRADESUBSCRIPTION_TIER_DOWNGRADESUPPORT_TICKET_OPENEDMOBILE_INSTALLCUSTOM_EVENTError schema
| Field | Type | Required | Description |
|---|---|---|---|
| error | string | — | — |
| errors | array of strings | — | — |