Skip to main content

Bulk vouchers issued

Bulk vouchers issued webhook

Triggered when a bulk voucher issuance run processes a batch of customers — for example a scheduled task that issues a voucher to every customer in a defined group ("issue all customers who have not shopped in more than a year a voucher every Friday afternoon").

Unlike the per-shopper webhooks (such as voucher issued), this event summarises the outcome for a whole batch of customers in a single POST. A bulk run is processed in batches of up to 1000 customers, and one webhook is sent per batch, so a large run produces several sequential calls, each with its own batch_offset.

An example of a bulk vouchers issued webhook

{
"chain_id": 1781,
"campaign_id": 2051,
"task_id": "48219",
"identifier": "username",
"batch_offset": 0,
"batch_count": 3,
"results": [
{
"user": "john.smith@example.com",
"r": "issued",
"vkey": "aba92bee8c89e5467e013697cf0cd9ed6fd82c6b14bb37a6a794838f54ee77cc",
"vid": "678599"
},
{
"user": "unknown.person@example.com",
"r": "not_found"
},
{
"user": "regular.shopper@example.com",
"r": "at_limit"
}
]
}

Body fields

The top level of the body describes the batch:

FieldDescription
chain_idThe ID of the chain the bulk run was executed for.
campaign_idThe ID of the campaign that the vouchers were issued against.
task_idThe ID of the task that ran the bulk issuance (sent as a string). 0 if the run was not tied to a task.
identifierThe type of identifier used to look up customers in this run — either username or authentication_point_identifier. This tells you how to interpret each user value in results.
batch_offsetThe zero-based position of this batch within the overall run. The first batch is 0, the next is 1000, and so on. Use it to distinguish and order the batches of a single run.
batch_countThe number of result rows in this batch (the length of results).
resultsAn array with one entry per customer processed in this batch. See below.

Result rows and field names

Each entry in results describes what happened for one customer. Because a batch can contain up to 1000 rows, the per-row field names are deliberately kept short to keep the payload compact:

FieldMeaningDescription
useruserThe customer identifier that was submitted for this row. Interpret it using the top-level identifier field (for example a username/email, or an authentication point identifier).
rresultThe outcome for this customer (see result codes below).
vkeyvoucher keyThe key of the voucher that was issued. Present only when r is issued.
vidvoucher idThe ID of the voucher that was issued. Present only when r is issued.

vkey and vid are omitted entirely for rows that did not result in a voucher (any r other than issued), which keeps those rows as compact as possible.

Result codes

The r field takes one of the following values:

ValueMeaning
issuedA voucher was successfully issued to the customer. vkey and vid are included for these rows.
not_foundNo customer could be matched for the submitted identifier, so no voucher was issued.
at_limitThe customer had already reached the maximum number of rewards allowed for the campaign, so no further voucher was issued.
errorThe voucher could not be issued because of an error while processing the batch.

Verifying the webhook

This webhook is signed in exactly the same way as the other Spaaza webhooks. Spaaza provides a signature in the X-Spaaza-Hmac-SHA256 request header whose value is the base64-encoded HMAC-SHA256 hash of the whole body of the request, using a shared secret. Your code to handle the event should recreate the signature using the shared secret and compare it to the value in the header. See Webhooks and Events for details on configuring a webhook signature key.

Note that, unlike the per-shopper webhooks, this event sends the bare { "chain_id", "campaign_id", ..., "results" } object shown above rather than wrapping it in the standard { "id", "type", "chain_id", "created", "data" } envelope. The signature is computed over that bare body, so verify against the exact bytes you receive.

This webhook is not currently self-service in Console; please get in touch if you would like us to configure it for you.