Skip to content
API referenceEvents

API reference · App API

Events

Report what your users do, server to server. Registrations are attributed to the link or code that brought the user; later events earn commissions and rewards.

Send events

POST/v1/events

Reports one event, or a batch of up to 500 as { "events": [...] }. Events are stored first and processed right after, so a 202 means received, not yet attributed or paid.

Deduplicated on (eventId, environment): sending an event again returns duplicate and changes nothing, so retry freely after a timeout or a 5xx.

user.registered decides who referred the user. Send it with the attributionKey from POST /v1/attributions and the new appUserId: the key is bound to that user and the referral it stands for wins. Every later event may then carry the key instead of appUserId. Sending the clickId or affiliateCode the user arrived with on user.registered still works too.

AuthSigned request with an app key, fg_live_… or fg_test_…

Request body · one of

Batch

1 to 500 events, processed in order.

eventsarray of objectsrequired1–500 items
Child attributes
eventIdstringrequired≤ 200 chars

Your stable id for this occurrence, e.g. registered:<user id> or order:<order id>. Sending it again is safe: it is accepted once.

typestringrequired≤ 100 chars

Dotted event type, e.g. user.registered. Commission and reward rules trigger on it.

versioninteger≥ 1

Version of your payload for this type. Defaults to 1.

occurredAtstringrequireddate-time

When it happened in your system, ISO 8601 with Z or an offset.

appUserIdstring≤ 200 chars

Your pseudonymous id for the user. Never an email address or phone number. Required unless attributionKey names a user already.

attributionKeystring≤ 100 charsnullable

The key from POST /v1/attributions. On user.registered, with appUserId, it binds the key to the new user and attributes them to that referral. On any event after that it may stand in for appUserId.

clickIdstringuuid

fg_click from the landing URL, universal link or Play install referrer. A value that is not a click id is ignored, never refused.

affiliateCodestring≤ 100 charsnullable

The publisher’s code: fg_ref from the same places, or a code the user typed.

reversesEventIdstring≤ 200 charsnullable

The eventId of the event this one undoes, for refunds and rejections.

amountinteger≥ 0nullable

Integer minor units (cents). Percentage rules pay a share of it.

currencystringnullable

ISO 4217 code in capitals. Send it whenever amount is set.

Matches ^[A-Z]{3}$

metadataobject

Free-form facts about the event. Rules can match on them; country (ISO alpha-2) on a registration picks the market.

Event

Something a user did in your app.

eventIdstringrequired≤ 200 chars

Your stable id for this occurrence, e.g. registered:<user id> or order:<order id>. Sending it again is safe: it is accepted once.

typestringrequired≤ 100 chars

Dotted event type, e.g. user.registered. Commission and reward rules trigger on it.

versioninteger≥ 1

Version of your payload for this type. Defaults to 1.

occurredAtstringrequireddate-time

When it happened in your system, ISO 8601 with Z or an offset.

appUserIdstring≤ 200 chars

Your pseudonymous id for the user. Never an email address or phone number. Required unless attributionKey names a user already.

attributionKeystring≤ 100 charsnullable

The key from POST /v1/attributions. On user.registered, with appUserId, it binds the key to the new user and attributes them to that referral. On any event after that it may stand in for appUserId.

clickIdstringuuid

fg_click from the landing URL, universal link or Play install referrer. A value that is not a click id is ignored, never refused.

affiliateCodestring≤ 100 charsnullable

The publisher’s code: fg_ref from the same places, or a code the user typed.

reversesEventIdstring≤ 200 charsnullable

The eventId of the event this one undoes, for refunds and rejections.

amountinteger≥ 0nullable

Integer minor units (cents). Percentage rules pay a share of it.

currencystringnullable

ISO 4217 code in capitals. Send it whenever amount is set.

Matches ^[A-Z]{3}$

metadataobject

Free-form facts about the event. Rules can match on them; country (ISO alpha-2) on a registration picks the market.

Returns · 202

One entry per event sent, in the order sent.

acceptedarray of objectsrequired
Child attributes
eventIdstringrequired
statusstringrequired

duplicate: this eventId was received before, and nothing was processed twice. rejected: its attributionKey could not be used (see reason); the event was not stored, so the same eventId may be sent again once fixed.

One of accepted duplicate rejected

reasonstring

Why a rejected event was not taken: - unknown_key: no key like it belongs to your app in this environment. - key_expired: the key was never registered, and its attribution window has closed. - key_bound_to_other_user: the key was registered for another appUserId. - key_not_registered: the key is not bound to a user yet. Only user.registered with an appUserId binds it. - key_declined: you declined the key.

One of unknown_key key_expired key_bound_to_other_user key_not_registered key_declined

Errors

400validation_error

The request does not match the schema. details says which fields failed and why.

400renamed_field

An event still sends referralCode, which is now affiliateCode. Nothing is stored; in a batch, details.events lists the positions of those events.

401missing_signature

One of x-fg-key, x-fg-timestamp and x-fg-signature is missing.

401invalid_timestamp

x-fg-timestamp is not Unix time in seconds.

401stale_timestamp

x-fg-timestamp is more than 300 seconds from the server clock. Sign each attempt again, and keep your clock in sync.

401invalid_key

The key id is unknown or revoked, or the app is archived.

401invalid_signature

The signature does not match. Sign the exact bytes you send.

429too_many_attempts

Too many requests with this key in the last minute. Wait Retry-After seconds.

Request
BODY='{"events":[{"eventId":"registered:u_8F2K","type":"user.registered","occurredAt":"2026-11-09T09:30:00Z","appUserId":"u_8F2K","attributionKey":"fga_k7qxa2mpw4ht9bvc3rnd8ezj","metadata":{"country":"SE"}}]}'
TS=$(date +%s)
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$FG_SECRET" | sed 's/^.*= //')

curl -X POST "https://api.flowgroup.se/v1/events" \
  -H "content-type: application/json" \
  -H "x-fg-key: $FG_KEY_ID" \
  -H "x-fg-timestamp: $TS" \
  -H "x-fg-signature: $SIG" \
  --data-raw "$BODY"
202 Accepted
{
  "accepted": [
    {
      "eventId": "registered:u_8F2K",
      "status": "accepted"
    },
    {
      "eventId": "order:o-77120",
      "status": "rejected",
      "reason": "key_not_registered"
    }
  ]
}