Prize Draw Entries API
Prize Draw Entries API
Enter members into a prize draw and look up their submissions from your own system — a CRM, e-commerce platform, POS or internal app. This surface is part of the Custom API (externalApi).
Typical uses: one entry per purchase, bonus entries for higher spend, or entering every customer who completes a sign-up or survey. The customer never fills in a form; your system decides who qualifies and sends the request.
Base URL
https://us-central1-incentable-app-37d9c.cloudfunctions.net/externalApi/api/v1/external
Authentication & permissions
Use a Bearer API key (inc_…):
Authorization: Bearer YOUR_API_KEY
| Action | Required permission |
|---|---|
| Enter a member | prizeDraws → write |
| Look up a submission | prizeDraws → read |
Set up the integration
- Log in to the Incentable Admin Dashboard and select the program that runs the prize draw (API keys are scoped to a single program).
- Open Integrations and add (or open) a Custom API integration.
- Under Permissions & Configuration → Prize Draws, confirm Read and Write are on. New Custom API keys have both on by default. Permission changes are made by Incentable — contact support if you need one changed.
- Optionally choose a Default Prize Draw on the same card, so requests can omit
prizeDrawId. - Generate the API key and store it securely.
Find the prize draw ID
Open the prize draw in the Admin dashboard, go to the Entries tab and click API. The Prize draw ID is shown with a copy button. The integration's settings page also has an Example body button next to the prize draw endpoint.
Enter a member
POST /prizedraws/entries
Request body
| Field | Type | Required | Description |
|---|---|---|---|
member.email | string | Yes | Entrant email. Used to match or create the member and for the confirmation email. |
member.firstname | string | Yes | First name |
member.lastname | string | Yes | Last name |
member.accountKey | string | No | Your customer id. Matched before email when present. |
member.mobile | string | No | Optional mobile |
prizeDrawId | string | Conditional | Prize draw to enter. Required unless a default is set on the integration. |
quantity | integer | No | Entries in this submission, 1–400 (default 1). Prize draw entry limits also apply. |
externalRef | string | Recommended | Your reference for the submission, such as an order number. Max 255 chars. Unique per prize draw. |
idempotencyKey | string | No | Explicit idempotency key. Max 255 chars. |
metadata | object | No | Free-form data stored on every entry, such as store or order value. Included in entry exports. |
Also accepted: Idempotency-Key header. Resolution order: body idempotencyKey → header → externalRef.
externalRef with every request. If your system retries after a timeout, the reference stops the retry from adding a second set of entries. Without an externalRef or idempotency key there is no duplicate protection.Example
curl -X POST \
"https://us-central1-incentable-app-37d9c.cloudfunctions.net/externalApi/api/v1/external/prizedraws/entries" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prizeDrawId": "YOUR_PRIZE_DRAW_ID",
"member": {
"email": "jane@example.com",
"firstname": "Jane",
"lastname": "Doe",
"accountKey": "CRM-100245"
},
"quantity": 2,
"externalRef": "order-10045",
"metadata": { "store": "Sydney CBD", "orderTotal": 129.95 }
}'
Node.js example
const res = await fetch(
"https://us-central1-incentable-app-37d9c.cloudfunctions.net/externalApi/api/v1/external/prizedraws/entries",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.INCENTABLE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
prizeDrawId: process.env.PRIZE_DRAW_ID,
member: { email: order.email, firstname: order.firstName, lastname: order.lastName, accountKey: order.customerId },
quantity: Math.floor(order.total / 50), // e.g. one entry per $50 spent
externalRef: `order-${order.id}`,
}),
}
);
const body = await res.json();
if (res.status === 201 || res.status === 200) {
// Entered (201) or already entered on an earlier attempt (200)
} else if (res.status === 409 && body.code === "DUPLICATE_EXTERNAL_REF") {
// This order was already entered — safe to treat as done
} else {
console.error(res.status, body.code, body.message);
}
Make sure quantity is at least 1 — if your calculation can produce 0, skip the request rather than sending it.
Success response (201)
{
"data": {
"submissionId": "sub_1aae5cd95fe1b38bcedf",
"prizeDrawId": "YOUR_PRIZE_DRAW_ID",
"quantity": 2,
"totalEntries": 5,
"isTest": false,
"externalRef": "order-10045"
},
"memberId": "memberDocId",
"memberCreated": false,
"message": "Entries created successfully"
}
| Field | Meaning |
|---|---|
data.submissionId | Id of this submission. One submission can hold several entries. |
data.quantity | Entries added by this request. |
data.totalEntries | The member's total entries in this prize draw after this request. |
data.isTest | true if the prize draw is in test mode. |
memberCreated | true if Incentable created a Pending member for this request. |
A replay with the same idempotency key returns 200 with the original payload and adds no entries. A duplicate externalRef in the same prize draw returns 409 with the original submission id in details.submissionId. The same externalRef may be used in a different prize draw.
Behaviour notes
- Member upsert: accountKey → email → create a Pending member.
- Entry rules: the prize draw must be Active and inside its entry period. Per-member and per-submission limits from the prize draw settings apply, and excluded members are rejected. API requests cannot override limits; admins can add entries beyond a limit from the dashboard.
- Weighting: each entry is a separate ticket in the draw, so a member with 5 entries is five times as likely to win as a member with 1.
- Test mode: entries created while the prize draw is in test mode are tagged as test and only used in test draws. Turn test mode off before go-live.
- Email: if the prize draw's Entry received email is on, Incentable emails the entrant after each successful submission.
- Visibility: entries appear on the prize draw's Entries tab with source API. Every request — including rejected ones — is recorded in the integration's Activity log.
Common errors
Errors return a JSON body with error, message and code, and sometimes details.
| Status | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_ERROR | Missing member fields, or bad field types |
| 400 | INVALID_ARGUMENT | quantity is not a whole number |
| 400 | NO_PRIZE_DRAW_SPECIFIED | No prizeDrawId and no default on the integration |
| 400 | REFERENCE_REQUIRED | Braze integrations only: no externalRef, idempotencyKey or Idempotency-Key header |
| 401 | INVALID_API_KEY / MISSING_API_KEY | Key missing, wrong or revoked |
| 403 | PERMISSION_DENIED | Key lacks prizeDraws write (or read for lookups) |
| 404 | NOT_FOUND | Prize draw (or submission) not found in this program |
| 409 | DUPLICATE_EXTERNAL_REF | externalRef already used in this prize draw — details.submissionId has the original |
| 422 | PROMOTION_NOT_ACTIVE | Prize draw is not Active |
| 422 | PROMOTION_NOT_OPEN / PROMOTION_CLOSED | Request is outside the entry period |
| 422 | ENTRANT_EXCLUDED | Member is excluded from this prize draw |
| 422 | LIMIT_EXCEEDED | Over a per-member or per-submission limit — details.limitBreaches lists which |
| 429 | RATE_LIMIT_EXCEEDED | Rate limit reached for the key; retry with backoff |
4XX errors other than 429 will fail again if retried unchanged — fix the request rather than retrying. Retry 429 and 5XX with the same externalRef.
Look up a submission
GET /prizedraws/entries/{id}?prizeDrawId=YOUR_PRIZE_DRAW_ID
{id} may be the submissionId or your externalRef. prizeDrawId can be omitted when the integration has a default prize draw.
curl -X GET \
"https://us-central1-incentable-app-37d9c.cloudfunctions.net/externalApi/api/v1/external/prizedraws/entries/order-10045?prizeDrawId=YOUR_PRIZE_DRAW_ID" \
-H "Authorization: Bearer YOUR_API_KEY"
Example response
{
"data": {
"submissionId": "sub_1aae5cd95fe1b38bcedf",
"prizeDrawId": "YOUR_PRIZE_DRAW_ID",
"memberId": "memberDocId",
"externalRef": "order-10045",
"source": "api",
"quantity": 2,
"validEntries": 2,
"voidEntries": 0,
"isTest": false,
"createdAt": "2026-10-20T00:15:00.000Z"
}
}
voidEntries counts entries an admin has voided since the submission (for example, after a refund). Voided entries are not included in draws.
Test checklist
- Prize draw Active, inside its entry period, and in Test mode
- Custom API key has
prizeDrawswrite (and read if you look up submissions) -
201on a first request; entries visible on the prize draw's Entries tab - Same
externalRefagain returns409, with no new entries - Lookup by
externalRefreturns the submission - Your system handles
422rejections (closed, limit reached, excluded) without retrying - Test mode turned off for go-live
Related guides
- Braze → Prize Draws — the same endpoint from a Braze campaign or Canvas
- API Overview — base URL, auth, getting your API key
