Skip to content

Quickstart

Turn Shield on, set thresholds that hold, and work the review queue.

Shield is already scoring your live payments at the platform thresholds. Turning it on is how you replace those with your own and unlock everything that acts on a score rather than just reporting it.

Five steps, all of them in live mode.

1. Turn it on

In the Dashboard, Shield shows an activation screen until you activate it. Activating sets nothing else: you start on the platform thresholds that were already applying, and GET /shield/settings returns them.

From the API it is one call.

Activate Shield
curl -X PUT https://api.wajub.com/shield/settings \
  -H "Authorization: sk.xxxxxxxxxxxxxxxx…" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true }'

The response returns the settings as they now stand, including an advanced flag telling you whether rules, lists and automatic 3D Secure are available to you.

2. Set thresholds that are actually accepted

Both thresholds are bounded, and a value outside the bounds is either refused or quietly brought back inside. This is the part that surprises people.

FieldAcceptedWhat happens outside it
block_threshold40 to 100Below 40 or above 100, the request is rejected
block_thresholdNever above the platform'sA value above the platform's block threshold is brought down to it
review_threshold10 to 99Below 10 or above 99, the request is rejected
review_thresholdAlways below blockA value at or above your block threshold is brought down to one under it

So a request asking for a block threshold above the platform's succeeds, and leaves you on the platform's. Read the settings back after writing them rather than assuming what you sent is what applies.

Set your own thresholds
curl -X PUT https://api.wajub.com/shield/settings \
  -H "Authorization: sk.xxxxxxxxxxxxxxxx…" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "block_threshold": 70,
    "review_threshold": 45,
    "auto_3ds_enabled": true,
    "blocklist_enabled": true
  }'

auto_3ds_enabled and blocklist_enabled are stored on any plan and only take effect while you hold Shield Advanced. A stored true on a plan without it reads back as false.

Why 40 is the floor

A payer nobody has met before rarely scores zero, so a block threshold that is too low refuses ordinary new customers, and at 0 it would refuse everyone. Start at the default, look at what got flagged, and adjust from there.

3. Read what it decided

Not from the API. The payment response carries no score, and no webhook fires on a Shield decision. Everything is in the Dashboard.

WhereWhat it holds
Shield, overviewThis month's blocked, flagged and reviewed counts, and the split between them
Shield, reviewsThe queue of flagged payments waiting on you
The payment itselfIts score and the flag codes that produced it

The overview counters can take a few minutes to update. The queue is always current.

4. Work the review queue

The queue holds every flagged payment from the last 90 days that you have not yet closed, newest first, twenty to a page. Each row carries the score, the flag codes, the customer and what a full refund would return.

It also holds the attempts Shield blocked. Those collected nothing, so there is nothing to refund on them. What you can do is let the customer through next time.

Closing a row takes one of four decisions.

DecisionWhat it does
ApproveMarks it reviewed. Nothing else changes
Allow this customerAlso writes an allow rule on their email and phone, so their next payments go through
Block this customerAlso blocklists their email and phone. This payment stays collected
Block and refundThe same, plus a full refund of this payment

Approve and allow this customer are available on every plan. If Shield refused someone you trust, allowing them is how you release them: their next attempt goes through, and Shield, lists shows who you allowed and lets you take it back. The two decisions that block are Shield Advanced, because they write to the blocklist.

Blocking alone leaves you holding the money

A flagged payment was collected. Blocking the customer only protects you from their next attempt. If you have decided a payment is fraud, block and refund is the decision that acts on the one in front of you, and it goes through the ordinary refund flow so you can follow it on the payment page.

5. Know what a block looks like

A blocked payment never reaches a provider. The call returns immediately, the transaction stays pending, and your integration gets a message with a reference.

Response · 403 Forbidden
{
"code": 403,
"status": "Forbidden",
"message": "Payment blocked: transaction risk score too high. Please contact support and reference BLK-K3M9XQ2P."
}

Because the transaction is untouched, the payer can be offered another attempt on the same payment. A retry is scored again, and is usually blocked again unless something about the payer changed.

If you run your own checkout

Wajub's hosted pages and Wajub Components charge from the payer's own browser, and send a small block of browser data with every charge. If you built your own payment page and charge from your server with a secret key, the request comes from your server, not from the payer, and Shield does not see the payer's browser.

To give Shield the payer back, call Wajub.signals() in the payer's browser, send the result to your server, and pass it unchanged as data._client on the charge. Your ip and country blocklist entries need it too.

In the payer's browser
const signals = await Wajub.signals();

// Send it to your server with the order, then on to the charge as data._client.
await fetch('/checkout', { method: 'POST', body: JSON.stringify({ order, signals }) });
Charge with the payer's signals
{
"channel": "card",
"data": {
"payment_method_id": "pm_1PqR8xLkdIwHu7ix0aB3cD4e",
"_client": {
"token": "v1.…",
"timezone": "Africa/Douala",
"language": "fr-CM",
"screen": "1512x982",
"color_depth": 24,
"fingerprint": "9f2c41ab7e05d3c8"
}
}
}

token vouches for the payer's IP address. It is short-lived, so fetch it while the payer is on your payment page. With it, Shield sees the payer as it does on a hosted page. A missing or expired token never makes the charge fail, and Wajub.signals() never rejects: if the token cannot be fetched, the other fields come back alone.

If you cannot run Wajub.js on the page, you may send the payer's address yourself as _client.ip. A declared address is weaker evidence than a token, because anyone can put any address there, and your ip and country blocklist entries and your rules on IP country need the token. Use the token whenever you can.

Every other field is optional. They describe the payer's browser and device, and Shield uses them in its consistency and device checks. fingerprint is what lets Shield recognise the same device across payments: pass the value Wajub.signals() returns, and send the same value for the same device.

What did you think of this content?