Skip to main content

Events to your queue or bucket

The same events as the webhooks can reach your infrastructure in two other ways, without exposing an HTTP endpoint:

RouteWhat it is forLatency
SQS queue or SNS topicProcess events almost in real time in your AWS accountSeconds
Daily S3 export (NDJSON)Feed analytics or a data warehouse with the full dayOnce a day
How they are configured today

Neither has its own back-office screen yet: both are configured with the administration API (/api/services/app/...) using an administrator session with the permissions listed. See Admin scopes to automate it with a key.

In the examples, $BASE is your platform's address and $TOKEN your administrator session token.

SQS queue or SNS topic​

A webhook subscription can have your SQS queue or your SNS topic as its destination instead of an HTTPS URL. Fan-out, retries, the delivery log and manual redelivery are the same; only the last step differs.

You need the Webhook Subscriptions permission (Pages.Loyalty.Webhooks) and a plan that includes webhooks.

Prepare AWS​

  1. Create the queue (or topic). .fifo queues and topics are supported.
  2. Create an IAM access key allowed only sqs:SendMessage on that queue (or sns:Publish on that topic).

IncentIA does not fall back to its own AWS identity: the credentials are mandatory.

Create the subscription​

POST /api/services/app/WebhookSubscription/Create:

curl -s -X POST "$BASE/api/services/app/WebhookSubscription/Create" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{
"name": "Events to SQS",
"destinationType": 1,
"targetUrl": "https://sqs.eu-west-1.amazonaws.com/123456789012/incentia-events",
"awsAccessKeyId": "AKIA...",
"awsSecretAccessKey": "...",
"secret": "optional-signing-secret",
"eventTypes": [2, 14, 18]
}'
FieldValue
destinationType0 = HTTP (default), 1 = SQS (AwsSqs), 2 = SNS (AwsSns)
targetUrlSQS: queue URL, https://sqs.<region>.amazonaws.com/<12-digit account>/<queue>. SNS: topic ARN, arn:aws:sns:<region>:<account>:<topic>
awsAccessKeyId, awsSecretAccessKeyRequired with SQS or SNS
secretOptional. If set, every message carries X-Signature
eventTypesList of event types (see Lifecycle events)
  • Only the public AWS partition (aws) is supported. The region comes from the URL or ARN itself.
  • The AWS secret is stored encrypted and cannot be read back. When editing, leave it empty to keep it. Switching to HTTP deletes the credentials.

What you receive​

  • Body: exactly the same JSON an HTTP webhook would receive.
  • Message attributes: the X-Event-Type, X-Timestamp, X-Correlation-Id, X-IncentIA-Idempotency-Key and, with a secret, X-Signature headers, as String attributes with the same name and value. The signature is computed as in Verify the signature.
  • FIFO queues and topics: MessageGroupId is subscription-<id> and MessageDeduplicationId is the idempotency key, so AWS drops a resend it already accepted (5-minute window). Ordering across events is not guaranteed.
  • Always deduplicate by X-IncentIA-Idempotency-Key: deliveries may repeat.

Retries and failures​

AWS responseHandling
Throttling (HTTP 429)Retried, like an HTTP 429
5xx error or no responseRetried, like an HTTP 5xx
Any other 4xx error (no permission, unknown queue or topic, invalid key, message too large)Final failure of that delivery
Destination or credentials that are no longer validFinal failure

Failures count towards the subscription's automatic deactivation, as with HTTP (see Delivery and retries). The delivery log stores only AWS <code> (HTTP <status>), never AWS's text.

Daily S3 export​

Every day a file with all of the previous UTC day's events is dropped in your bucket, with no subscriptions needed. It is a scheduled export of type events.

You need the Scheduled event-stream exports permission (Pages.Exports.Scheduled.Events), in addition to the scheduled exports one. It is checked again for the user who created it on every run.

Content​

NDJSON (UTF-8, one JSON line per event, in order):

{"schemaVersion":1,"eventId":"7b1c...","eventType":"ParticipationCreated","event":"participation.created","occurredAt":"2026-11-01T10:15:02Z","recordedAt":"2026-11-01T10:15:02Z","data":{"attemptId":991,"campaignId":17}}
  • eventId identifies the event: deduplicate by it.
  • event is the dotted name (participation.created); for older events that do not have one, it equals eventType.
  • data is the webhook's data without personal data: names, email, phone, address, date of birth, IP and so on are removed. Identifiers, codes and amounts remain as join keys.
  • An export never carries personal data and does not accept includePii.

Where it lands​

One file per day, idempotent. In your bucket:

{prefix}events/dt=YYYY-MM-DD/events_YYYYMMDD.ndjson

Running it again for the same day overwrites that object with the same content (unless a GDPR erasure scrubbed a row in between). The dt= partition is Hive-compatible.

Create the export​

POST /api/services/app/ScheduledExport/Create:

curl -s -X POST "$BASE/api/services/app/ScheduledExport/Create" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{
"name": "Daily events",
"exportType": "events",
"format": "ndjson",
"cadence": 1,
"runAtUtcHour": 3,
"destination": 4,
"s3": {
"bucket": "my-bucket",
"region": "eu-west-1",
"prefix": "incentia/",
"accessKeyId": "AKIA...",
"secretAccessKey": "..."
},
"isActive": true
}'
FieldNotes
exportTypeevents, with format ndjson (the only one supported)
cadence1 = daily
runAtUtcHourUTC hour to run, 0-23
destination4 = your own bucket (CustomerS3). 2 (IncentIA's private storage with a link, no bucket needed) and 3 (SFTP) also work. The token link (1) is not supported
s3.bucket, s3.regionRegion is required on AWS
s3.serviceUrl, s3.forcePathStyleFor S3-compatible storage: the https:// URL of its endpoint
s3.prefixKey prefix; empty = bucket root
s3.accessKeyId, s3.secretAccessKeyWrite key. The secret is stored encrypted and not returned
campaignId, preset, columnsLeave them empty: it is an account-wide export

Give IncentIA a key that can only s3:PutObject under that prefix. When editing, an empty or *** secret keeps the stored one; changing the bucket, endpoint or key id forces you to enter the secret again.

To run it now, POST /api/services/app/ScheduledExport/RunNow?id=<id>; the history is in GetHistory.

Limits​

  • The source is the events the platform keeps for 14 days by default: a day that was not exported can only be recovered with RunNow the next day, because it always exports the previous day.
  • An S3-compatible endpoint cannot point to internal or private addresses.
  • The Scheduled exports screen (/app/main/loyalty/exports) lists these exports, but its destination selector does not offer your own bucket.