Docs menu
Guides
API reference
Bonus and withdrawal checks
Screening the sign-up is not the end of the story: abuse shows up when a bonus is claimed or money is paid out. Call POST /api/v1/events/bonus before you pay a bonus and POST /api/v1/events/withdrawal before you pay a withdrawal, and act on the answer, which has the same shape as /verify.
Last updated
How it works
- Screen the sign-up as before, and send your own
accountIdfor the player with it. InlineShield binds the account to that sign-up. - When the player claims a bonus or asks for a withdrawal, your server calls the event endpoint with the
accountId, the player's currentipand, for a withdrawal, the payout account as a fingerprint. - InlineShield compares the event with the sign-up, with the account's linked group, with your other accounts that used the same payout account, and with the IP. It answers with a
decision, anaction, arecommendedAction, ariskScoreand thereasons. - Pay, hold or refuse. A held event waits in Review › Held for up to 72 hours, and the outcome reaches your server by webhook or by polling.
The checks add to what the sign-up screening knows. They only hold or advise, with one exception: an event is BLOCKED when the IP and bot checks of your sign-up rules would block it (see Decision and advice).
Bind a player account to its sign-up
The checks work best when InlineShield knows which sign-up an account came from. There are two ways to tell it:
- Send
accountIdwith the sign-up call: POST /api/v1/verify or POST /api/v1/siteverify. The account is bound to the screening that call recorded. - Send
signupRequestId(therequestId,AUD-…, of the sign-up) with a bonus or withdrawal event, for an account that is not bound yet.
- The first binding stays. A later call with the same
accountIdand another sign-up changes nothing, and so does asignupRequestIdon an event for an account that is already bound. - An
accountIdis 1 to 128 printable characters, and not only white space. Anything else gets400 INVALID_ACCOUNT_IDand nothing is screened. - Accounts are yours alone: the same
accountIdin another InlineShield account is another player. Test keys and live keys have separate accounts, so a test event never meets a live sign-up.
An event for an account with no sign-up bound is still answered. Its reasons say "Sign-up not linked to this account", and nothing that needs the sign-up (its country, its verdict, its linked group) is checked. There is no penalty for that.
Check a bonus claim
Call it before you credit a bonus. Only accountId is required; the more you send, the more it can check.
| Field | Type | Required | Description |
|---|---|---|---|
accountId | string | yes | Your own id for the player account (1 to 128 printable characters). It is stored as you send it, shown masked in the console (the first 2 characters and ***) and sent back in the webhooks. If the account has a sign-up bound to it (by accountId on /verify or /siteverify, or by signupRequestId below), the check compares the event with that sign-up. An unbound account is still answered, with the reason "Sign-up not linked to this account" and no penalty. Anything else gets 400 INVALID_ACCOUNT_ID.at least 1 character; at most 128 characters |
ip | string | no | The player's IP address (IPv4 or IPv6) for this event. Without it the IP checks do not run: the request's own address is your server's, so it is never used. Anything that is not an IP address gets 400 INVALID_IP. |
userAgent | string | no | The player's browser User-Agent. Only this field is read; a scripted HTTP client here counts as an automation signal.at most 1024 characters |
bonusType | string | no | What the player claims, for example welcome or reload. When given, the check for "another account of the same person already claimed this bonus" compares bonuses of this type only; without it any earlier bonus claim counts.at most 40 characters |
amount | number | no | The bonus amount, 0 or more. Stored and shown in the console; it does not change the score.0 to 1000000000000000 |
currency | string | no | The ISO 4217 code of amount: 3 letters, stored in upper case.at most 3 characters; matches ^[A-Za-z]{3}$ |
token | string | no | The player's sign-up /check token (the one the browser script got at sign-up), for the browser's time zone and automation signals. Usable only within its 10-minute life and only if it was not already redeemed with /siteverify. Never run /check on bonus or cashier pages: that records a new sign-up screening, counts against the quota and creates false links. Without a token the event is screened from server-side data only. The event spends the token: a later /siteverify with the same token answers TOKEN_ALREADY_USED. A token of the other mode (test or live) is left unused, and a token that is unknown, used or expired is ignored.at most 512 characters |
signupRequestId | string | no | The requestId (AUD-…) that the sign-up's /verify, /check or /siteverify returned. It binds the account to that sign-up, but only while the account has none yet: the first binding stays. A sign-up of another account, mode or organisation never binds.at most 128 characters |
curl -X POST https://api.inlineshield.io/api/v1/events/bonus \
-H "X-Api-Key: $INLINESHIELD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "player-1042",
"ip": "203.0.113.24",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36",
"bonusType": "welcome",
"amount": 50,
"currency": "EUR"
}'Every field, answer and error: POST /api/v1/events/bonus.
Check a withdrawal
Call it before you pay a withdrawal. accountId, amount and payout are required.
| Field | Type | Required | Description |
|---|---|---|---|
accountId | string | yes | Your own id for the player account (1 to 128 printable characters). It is stored as you send it, shown masked in the console (the first 2 characters and ***) and sent back in the webhooks. If the account has a sign-up bound to it (by accountId on /verify or /siteverify, or by signupRequestId below), the check compares the event with that sign-up. An unbound account is still answered, with the reason "Sign-up not linked to this account" and no penalty. Anything else gets 400 INVALID_ACCOUNT_ID.at least 1 character; at most 128 characters |
ip | string | no | The player's IP address (IPv4 or IPv6) for this event. Without it the IP checks do not run: the request's own address is your server's, so it is never used. Anything that is not an IP address gets 400 INVALID_IP. |
userAgent | string | no | The player's browser User-Agent. Only this field is read; a scripted HTTP client here counts as an automation signal.at most 1024 characters |
amount | number | yes | The withdrawal amount, 0 or more. Stored and shown in the console; it does not change the score.0 to 1000000000000000 |
currency | string | no | The ISO 4217 code of amount: 3 letters, stored in upper case.at most 3 characters; matches ^[A-Za-z]{3}$ |
payout | object | yes | The account the money goes to, as a fingerprint, never as the card number, IBAN or wallet itself. A value that looks like a raw card number or IBAN is refused with 400 RAW_PAYMENT_DATA, whatever type says. InlineShield stores only a keyed hash of the fingerprint. |
payout.type | string | yes | What kind of account it is. The same fingerprint with another type is another payout account.Values: card, iban, wallet, other |
payout.fingerprint | string | yes | Your payment provider's fingerprint of the account (for example Stripe's fp_…), or a value you compute yourself with a secret key. 16 to 128 characters of A-Z, a-z, 0-9, _, -, : and .. It must be the same string every time the same account is used.at least 16 characters; at most 128 characters; matches ^[A-Za-z0-9_\-:.]+$ |
token | string | no | The player's sign-up /check token (the one the browser script got at sign-up), for the browser's time zone and automation signals. Usable only within its 10-minute life and only if it was not already redeemed with /siteverify. Never run /check on bonus or cashier pages: that records a new sign-up screening, counts against the quota and creates false links. Without a token the event is screened from server-side data only. The event spends the token: a later /siteverify with the same token answers TOKEN_ALREADY_USED. A token of the other mode (test or live) is left unused, and a token that is unknown, used or expired is ignored.at most 512 characters |
signupRequestId | string | no | The requestId (AUD-…) that the sign-up's /verify, /check or /siteverify returned. It binds the account to that sign-up, but only while the account has none yet: the first binding stays. A sign-up of another account, mode or organisation never binds.at most 128 characters |
curl -X POST https://api.inlineshield.io/api/v1/events/withdrawal \
-H "X-Api-Key: $INLINESHIELD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "player-2087",
"ip": "203.0.113.24",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36",
"amount": 120,
"currency": "EUR",
"payout": {
"type": "wallet",
"fingerprint": "3f9a1c7e5b2d48a0b6c1e9d4f7a28b35"
}
}'Every field, answer and error: POST /api/v1/events/withdrawal.
Limits on the text fields, as in the API reference: userAgent 1,024 characters, bonusType 40, currency 3, token 512, signupRequestId 128, accountId 128. A longer value gets 400 BAD_REQUEST (INVALID_ACCOUNT_ID for accountId) before anything is screened, stored or counted.
The payout fingerprint and the no-raw-data rule
InlineShield never receives the card number, IBAN or wallet address of a payout account, and refuses it when it is sent. You send a fingerprint of the account instead: your payment provider's fingerprint of the card or bank account (for example Stripe's fp_…), or a value you compute yourself from the account with a secret key that stays with you. It must be the same string every time the same account is used, so that two accounts that pay out to one card are recognised.
payout.typeis one ofcard,iban,walletorother. The same fingerprint under another type is another payout account.payout.fingerprintis 16 to 128 characters of A-Z, a-z, 0-9,_,-,:and.. Anything else gets400 BAD_REQUESTwithfield: "payout".
What is refused
A value that looks like raw payment data gets 400 RAW_PAYMENT_DATA, whatever type says. This check comes before the other payout checks, so a card number with spaces is RAW_PAYMENT_DATA, not BAD_REQUEST.
| Looks like | Refused when |
|---|---|
| A card number | 13 to 19 digits that pass the Luhn check, alone or with the separators space, -, ., _ and : between them. A 16-digit value that fails the Luhn check is not a card number and is accepted as a fingerprint. |
| An IBAN | Two letters, two digits and 11 to 30 letters or digits, after white space is removed and letters are upper-cased (so lower-case IBANs and IBANs with spaces are refused), and its check digits are valid (ISO 7064 mod 97). A value of the same shape with wrong check digits is accepted as a fingerprint. |
The refusal message never repeats the value you sent.
What is stored
- Only a keyed hash: HMAC-SHA256 of your InlineShield account, the payout type and the fingerprint, with a key that only InlineShield's servers hold. The fingerprint itself is never stored or logged.
- The hash includes your account, so the same fingerprint in two InlineShield accounts gives two different hashes: payout accounts are never compared across customers.
- The hash is removed from the stored event after 180 days, with the IP address and User-Agent (the default retention period). Payout accounts are compared over the last 180 days.
Computing it with the SDK
With SDK 1.1.0 or later, payoutFingerprint(type, value, secret) computes the fingerprint on your server: a lower-case hex HMAC-SHA256 of type:normalized value, keyed by a secret key of at least 16 bytes that only you hold. A card is reduced to its digits (no expiry), an IBAN loses its white space and is upper-cased, a wallet is trimmed (and lower-cased for a 0x address), and any other type is trimmed. An unknown type or an empty value throws an error (nothing is sent). The card number, IBAN or wallet address never leaves your server, and the result is 64 characters, which InlineShield accepts. Call it on your server only, never in the browser, and keep the secret the same forever: changing it makes every payout account look new.
import { payoutFingerprint } from '@inlineshield/node';
const fingerprint = payoutFingerprint('card', cardNumber, process.env.PAYOUT_FINGERPRINT_SECRET);from inlineshield import payout_fingerprint
fingerprint = payout_fingerprint("card", card_number, os.environ["PAYOUT_FINGERPRINT_SECRET"])use InlineShield\Client;
$fingerprint = Client::payoutFingerprint('card', $cardNumber, getenv('PAYOUT_FINGERPRINT_SECRET'));The answer
Both endpoints answer 200 with the same fields:
| Field | Type | Required | Description |
|---|---|---|---|
requestId | string | yes | The event's id, starting with EVT-. Use it for support; the webhooks carry it too.matches ^EVT-[0-9A-F]{16}$ |
decision | string | yes | ALLOWED, QUARANTINED (a rule of Settings › Rules held it) or BLOCKED (your sign-up rules would block this IP or client).Values: ALLOWED, QUARANTINED, BLOCKED |
action | string | yes | What to do with the event: ALLOWED → allow (pay), QUARANTINED → hold (do not pay until the review is decided), BLOCKED → block.Values: allow, hold, block |
recommendedAction | string | yes | Advice next to action. Bonus claims: deny_bonus (do not pay this bonus) when another account of the same person already claimed one and the rule "Recommend deny_bonus" is on, or when the score is 50 or more; else review when the claim is held, else allow. Withdrawals: review when held, deny (do not pay) at a score of 70 or more, else allow. Both: block when the decision is BLOCKED.Values: allow, review, deny_bonus, deny, block |
reviewId | string | no | Live holds only (action: "hold"): the review to poll with GET /api/v1/reviews/{reviewId} or wait for in the bonus.approved / bonus.rejected (withdrawal.*) webhook. A held test event has none.matches ^rev_ |
riskScore | number | yes | 0 (lowest risk) to 100.0 to 100 |
reasons | array of string | yes | Plain-language reasons for the result. |
triggers | array of string | yes | Machine-readable signal codes: EVENT_LINKED_TO_FRAUD, EVENT_COUNTRY_CHANGED, EVENT_DATACENTER_OR_VPN_IP, EVENT_TOR_IP, EVENT_TIMEZONE_MISMATCH, EVENT_BOT_SIGNALS, SIGNUP_WAS_FLAGGED, BONUS_ALREADY_CLAIMED_IN_GROUP, PAYOUT_SHARED, PAYOUT_SHARED_WITH_FRAUD, BONUS_THEN_CASHOUT and WITHDRAWAL_VELOCITY; TEST_MAGIC_ADDRESS on a magic test account id. New codes may be added. |
linked | Linked or null | yes | The linked-accounts summary of the account's bound sign-up (see Linked), including the links that a withdrawal with a shared payout account just added (same_payout), or null: no bound sign-up, no links, test mode, or the lookup did not finish within its budget. |
linked.groupId | string or null | yes | The linked-accounts group of this screening, as the console names it. null when there are only possible links (they never form a group). Groups can merge later, and then the merged group keeps one of the ids, so a later screening can report another id for the same people. In rare cases (the links could not be stored) the console has no group with this id.matches ^lg_[A-Za-z0-9_-]{16}$ |
linked.size | integer | yes | The number of screenings in the group, this one included. With only possible links: 1 plus the number of possibly linked screenings.at least 1 |
linked.strength | string | yes | strong when at least one link is strong, otherwise possible.Values: strong, possible |
linked.linkedToFraud | boolean | yes | True when at least one strong link goes to a screening that was BLOCKED or that you reported as fraud (feedback, a rejected review or a mark in the console). It is the condition of the Linked-to-fraud rule (Settings › Rules, off by default), and is reported whether the rule is on or off. |
action:allow(pay),hold(do not pay until the review is decided) orblock.- The
requestIdof an event starts withEVT-. Store it with the payment. - A live hold carries a reviewId; a held test event does not.
Signals and points
Each signal that fires adds its points and a line to reasons, and its code to triggers. The riskScore is the sum, at most 100.
| Trigger | Applies to | When | Points |
|---|---|---|---|
EVENT_LINKED_TO_FRAUD | Both | The sign-up bound to the account is strongly linked to a blocked or reported sign-up (see Linked accounts). This is the linkedToFraud value, whether or not the Linked-to-fraud rule is on. | 40 |
EVENT_COUNTRY_CHANGED | Both | The country of the event IP differs from the country of the sign-up IP. Both must be known. | 15 |
EVENT_DATACENTER_OR_VPN_IP | Both | The event IP is a datacenter (hosting) or VPN address. | 20 |
EVENT_TOR_IP | Both | The event IP is a Tor exit node. It replaces the line above. | 30 |
EVENT_TIMEZONE_MISMATCH | Both | The browser time zone from the token is not used in the country of the event IP. Needs a token and an IP. | 15 |
EVENT_BOT_SIGNALS | Both | The browser behind the token shows headless or automation signals. Needs a token. | 40 |
SIGNUP_WAS_FLAGGED | Both | The bound sign-up was held (QUARANTINED), BLOCKED, or allowed without a bonus (allow_no_bonus). | 15 |
BONUS_ALREADY_CLAIMED_IN_GROUP | Bonus | Another account bound to a sign-up of the same linked group already claimed a bonus, of the same bonusType when you send one. | 40 |
PAYOUT_SHARED | Withdrawal | The payout account was used by at least one other account of yours in the last 180 days. | 30, or 35 when 3 or more accounts in total use it (this one included) |
PAYOUT_SHARED_WITH_FRAUD | Withdrawal | One of those other accounts is bound to a sign-up that was blocked or that you reported as fraud. | 50 |
BONUS_THEN_CASHOUT | Withdrawal | A bonus was claimed on this account less than bonusCashoutHours ago (default 24). | 15 |
WITHDRAWAL_VELOCITY | Withdrawal | 3 or more withdrawals from this account in 24 hours, this one included. | 15 |
- A signal whose facts are not known never fires: no IP, no token, no bound sign-up, or a lookup that did not finish in time (see Time budget).
- Unbound accounts count toward
PAYOUT_SHARED: an account that never had a sign-up bound still counts as another account using the payout account.PAYOUT_SHARED_WITH_FRAUDand thesame_payoutlinks can only come from accounts bound to a sign-up. - Only the
ipin the body is used. The address of the request is your server's, so withoutipthe IP signals (country, datacenter, VPN, Tor, time zone) are unknown.
Decision and advice
| decision | action | When |
|---|---|---|
ALLOWED | allow | No hold rule fired. |
QUARANTINED | hold | A hold rule of Settings › Rules fired. A live hold creates a review. |
BLOCKED | block | The IP and bot checks of your sign-up rules would block this event: a Tor exit node, a datacenter IP, or a headless or scripted client, as far as your sign-up rules block them. The bonus and withdrawal rules themselves never block. |
BLOCKED comes first: an event that your sign-up rules would block is BLOCKED even if a hold rule also fired.
| recommendedAction | Bonus claim | Withdrawal |
|---|---|---|
allow | Not held, score below the deny level. | Not held, score below the deny level. |
review | Held. | Held. |
deny_bonus | Another account of the same person already claimed this bonus and the rule below is on, or the score is 50 or more. Do not pay this bonus. | Never. |
deny | Never. | Not held, and the score is 70 or more. Do not pay without a manual check. |
block | BLOCKED. | BLOCKED. |
A held bonus claim with a score of 50 or more is deny_bonus, not review. Read recommendedAction as well as action: an ALLOWED event can still say deny_bonus or deny.
Rules
In the console, Settings › Rules › Bonus and withdrawal checks has five switches and one number. They hold or advise; nothing is denied automatically.
| Setting | Applies to | Default | Effect |
|---|---|---|---|
holdPayoutSharedWithFraud: Hold a withdrawal whose payout account is shared with a blocked or reported account | Withdrawal | On | Holds the withdrawal when PAYOUT_SHARED_WITH_FRAUD fires. |
holdPayoutSharedMulti: Hold a withdrawal whose payout account is shared with 2 or more other accounts | Withdrawal | On | Holds the withdrawal when the payout account was used by 2 or more other accounts. |
adviseDenyRepeatBonus: Recommend deny_bonus when the same person already claimed a bonus (linked group) | Bonus | On | Sets recommendedAction to deny_bonus when BONUS_ALREADY_CLAIMED_IN_GROUP fires. Advice only: it never holds the claim. |
holdBonusCashout: Hold a withdrawal within bonusCashoutHours of a bonus claim | Withdrawal | Off | Holds the withdrawal when BONUS_THEN_CASHOUT fires. |
holdEventCountryChange: Hold an event when the country changed since sign-up | Both | Off | Holds the event when EVENT_COUNTRY_CHANGED fires. |
bonusCashoutHours | Withdrawal | 24 | The window of BONUS_THEN_CASHOUT, in hours: a whole number from 1 to 720. |
A stored change applies to the next event. An account without stored rules uses the defaults above.
Time budget
The lookups of one event (your rules, the bound sign-up and its links, the token's browser signals, the account's history, the other accounts of the payout account, the bonus claims of the linked group) start together and share one budget of 150 ms. A lookup that fails or has not finished by then is treated as unknown: it never fires a signal, and the reasons say "Some checks did not finish in time; this answer uses what was known."
Binding the account to signupRequestId happens before that clock starts, and the event is stored after it, so a slow lookup never costs you the record.
The token from /check
token is optional. It is the token that /check (the browser script on your sign-up page) gave this player at sign-up, and it lends the event that check's browser signals: the time zone and the automation hints. Without a token the event is screened from server-side data only (the body, the bound sign-up and the account's history), and those two signals are unknown.
- Only the sign-up token works. It can be used only within its 10-minute life, and only if your backend has not already redeemed it with
/siteverify. In practice that means an event sent right after sign-up, for example a welcome bonus claimed at once. - Never run
/checkon your bonus or cashier pages. Each/checkrecords a new sign-up screening: it counts against your quota and creates false links between the player and their own earlier sign-up. - An event spends the token. The unused
/checktoken of your account is redeemed by the event, so a laterPOST /api/v1/siteverifywith the same token answerssuccess: falsewithTOKEN_ALREADY_USED. If you need both, call/siteverifyfirst and screen the event without the token. - A token of the other mode (a test token with a live key, or the other way round) is left unused and ignored. An unknown, expired or already used token is ignored too: the event is still answered.
- A token is single-use for 10 minutes, as for
/siteverify.
Retries and timeouts
- A retried request is a second event. There is no idempotency key: a request you send again is screened and stored again, counts again against your quota, and counts as another withdrawal toward WITHDRAWAL_VELOCITY. Do not retry after a timeout; wait for the webhook instead.
- After a timeout, the webhook decides. If the SDK timed out and failed open (you let the claim or withdrawal through), a later
bonus.heldorwithdrawal.heldwebhook for that event is authoritative: the event was held, so stop or reverse the payout and wait for its*.approvedor*.rejected.
Held events and review
- A held live event has a
reviewId(rev_…). It creates one review, counted once, and sends onebonus.heldorwithdrawal.heldwebhook. - It waits in the console under Review › Held, next to held sign-ups, with a Bonus claim or Withdrawal badge, the amount, the reasons and the account id masked to its first 2 characters and
***. GET /api/v1/reviews/{reviewId}answers for both kinds, with the same fields: GET /api/v1/reviews/{reviewId}.- A review nobody decides within 72 hours is rejected with
decisionReason: "expired". No label is written for that. - Rejecting marks the event's sign-up as fraud. Approving marks it legit, unless the sign-up was blocked or already carries a fraud mark from any source: an approval never clears one, whether it is the approval of an event or of the held sign-up itself. An event whose account has no sign-up bound writes no label.
See Hold and review for the flow.
Webhooks
Eight events: bonus.allowed, bonus.held, bonus.approved, bonus.rejected and withdrawal.allowed, withdrawal.held, withdrawal.approved, withdrawal.rejected. They are signed and retried like the others: see Webhooks.
- They go to every enabled endpoint, whatever its subscriptions. An endpoint that subscribes to the registration events only receives them too.
*.allowedand*.heldare sent when the event is screened (live events only). Nothing is sent for a BLOCKED event.*.approvedand*.rejectedare sent when the review is decided or expires.- Deliveries can arrive in any order. Each delivery is sent and retried on its own, so
bonus.approvedorwithdrawal.approvedcan arrive before the*.heldof the same event. Key your handler onreviewIdandrequestId, not on the order. - The payload carries your own
accountId, the amount and the reasons. It has no IP address and no User-Agent.
bonus.allowed, bonus.held, withdrawal.allowed, withdrawal.held: data
| Field | Type | Required | Description |
|---|---|---|---|
event | string | yes | Values: bonus.allowed, bonus.held, withdrawal.allowed, withdrawal.held |
requestId | string | yes | The requestId the event's answer carried.matches ^EVT-[0-9A-F]{16}$ |
reviewId | string | no | Held events only.matches ^rev_ |
accountId | string | yes | The accountId you sent. |
kind | string | yes | Values: bonus, withdrawal |
decision | string | yes | Never BLOCKED: a blocked event sends no webhook.Values: ALLOWED, QUARANTINED |
action | string | yes | allow for an allowed event, hold for a held one.Values: allow, hold |
recommendedAction | string | yes | As in the answer.Values: allow, review, deny_bonus, deny |
riskScore | number | yes | 0 (lowest risk) to 100.0 to 100 |
reasons | array of string | yes | Plain-language reasons for the result. |
triggers | array of string | yes | The signal codes of the answer (see the answer of the event endpoints). |
amount | number or null | yes | The amount you sent, or null. |
currency | string or null | yes | The currency you sent, in upper case, or null. |
linked | Linked or null | yes | The linked-accounts summary, as in the answer. |
linked.groupId | string or null | yes | The linked-accounts group of this screening, as the console names it. null when there are only possible links (they never form a group). Groups can merge later, and then the merged group keeps one of the ids, so a later screening can report another id for the same people. In rare cases (the links could not be stored) the console has no group with this id.matches ^lg_[A-Za-z0-9_-]{16}$ |
linked.size | integer | yes | The number of screenings in the group, this one included. With only possible links: 1 plus the number of possibly linked screenings.at least 1 |
linked.strength | string | yes | strong when at least one link is strong, otherwise possible.Values: strong, possible |
linked.linkedToFraud | boolean | yes | True when at least one strong link goes to a screening that was BLOCKED or that you reported as fraud (feedback, a rejected review or a mark in the console). It is the condition of the Linked-to-fraud rule (Settings › Rules, off by default), and is reported whether the rule is on or off. |
bonus.approved, bonus.rejected, withdrawal.approved, withdrawal.rejected: data
| Field | Type | Required | Description |
|---|---|---|---|
event | string | yes | Values: bonus.approved, bonus.rejected, withdrawal.approved, withdrawal.rejected |
reviewId | string | yes | matches ^rev_ |
requestId | string or null | yes | The requestId (EVT-…) the held event's answer carried. |
accountId | string or null | yes | The accountId you sent. |
kind | string | yes | Values: bonus, withdrawal |
status | string | yes | Values: approved, rejected |
decisionReason | string or null | yes | operator: decided in the console. expired: nobody decided in time (rejected).Values: operator, expired, null |
decidedAt | string (date-time) or null | yes | |
amount | number or null | yes | |
currency | string or null | yes |
Test mode
A test key behaves as it does for sign-ups: events are screened and stored (shown with "Show test data"), but they never count against the quota, and they create no review, webhook, label or alert and no linked-accounts links. Test events only meet test accounts. See Test mode.
Two magic account ids give a fixed answer without any lookups, with test keys only. The match is exact, and each applies to its own endpoint; on the other endpoint, or with a live key, they are ordinary account ids.
| accountId | Endpoint | decision | action | recommendedAction | riskScore | triggers |
|---|---|---|---|---|---|---|
abuser@test | /events/bonus | ALLOWED | allow | deny_bonus | 40 | BONUS_ALREADY_CLAIMED_IN_GROUP, TEST_MAGIC_ADDRESS |
payout-shared@test | /events/withdrawal | QUARANTINED | hold | review | 35 | PAYOUT_SHARED, TEST_MAGIC_ADDRESS |
The held answer of payout-shared@test has no reviewId: test mode creates no review.
Quota, limits and errors
- Each live event counts once against your monthly quota, like a
/verifyscreening, and live answers carry theX-Quota-*headers. Over the quota, the event endpoints answer402 QUOTA_EXCEEDED. Test keys never count. - Live events are limited per key, like
/siteverify: the key's own per-minute limit (1,200 for a live key as created, 600 for a key without a limit of its own), one bucket for both endpoints. Test keys use a separate bucket of 300 per minute for your account, again for both endpoints together. - Event calls with a test key also count toward the daily test cap of 10,000 per UTC day (then
429 TEST_LIMIT), the one that/verifyand/checkuse. - If the event was screened but could not be stored you get
500 PERSISTENCE_FAILURE, and nothing is counted. Decide in advance whether to pay or wait; see Errors and HTTP codes.
What InlineShield keeps
- Each event is stored for your account: your
accountIdas you sent it, the kind, the amount and currency, thebonusTypeor payout type, the IP address, User-Agent, the keyed payout hash and the result. - After 180 days (the default retention period) the IP address, User-Agent and payout hash are removed from the event; the result stays.
- The console shows the account id masked. Account ids and payout data are never written to InlineShield's logs.
- See Data and privacy for everything else.