Docs menu
Guides
API reference
Hold and review flow
A QUARANTINED screening is held: you create the account as pending, someone decides it in the console Review queue, and InlineShield tells your server the outcome by webhook or when you ask for the review's status.
Last updated
The flow
- The screening answers
action: "hold"with areviewId(rev_…). Create the account as pending and store the reviewId with it. - The review waits in the console under Review. Someone approves or rejects it.
- InlineShield sends
signup.approvedorsignup.rejectedto every enabled webhook endpoint, whatever its subscriptions. Activate or remove the account. - A review nobody decides within 72 hours expires: it is rejected with
decisionReason: "expired", andsignup.rejectedis sent.
Webhook or polling
Prefer the webhook: see Webhooks for the payloads and the signature check. Polling is the fallback: GET /api/v1/reviews/{reviewId} answers pending, approved or rejected, limited to 60 requests per minute per key and never counted against the quota.
# Response: { reviewId, status: "pending" | "approved" | "rejected", decisionReason, decidedAt, expiresAt }. Prefer the webhook; poll only as a fallback (limit 60 requests/min per key). 404 = unknown review.
curl https://api.inlineshield.io/api/v1/reviews/$REVIEW_ID \
-H "X-Api-Key: $INLINESHIELD_API_KEY"// Node 18+. Response: { reviewId, status: "pending" | "approved" | "rejected", decisionReason, decidedAt, expiresAt }. Prefer the webhook; poll only as a fallback (limit 60 requests/min per key). 404 = unknown review.
const r = await fetch('https://api.inlineshield.io/api/v1/reviews/' + encodeURIComponent(reviewId), {
headers: { 'X-Api-Key': process.env.INLINESHIELD_API_KEY },
signal: AbortSignal.timeout(3000)
});
if (r.ok) {
const review = await r.json();
console.log(review.status); // 'pending' | 'approved' | 'rejected'
}# Response: { reviewId, status: "pending" | "approved" | "rejected", decisionReason, decidedAt, expiresAt }. Prefer the webhook; poll only as a fallback (limit 60 requests/min per key). 404 = unknown review.
import os, requests
from urllib.parse import quote
r = requests.get(
"https://api.inlineshield.io/api/v1/reviews/" + quote(review_id, safe=""),
headers={"X-Api-Key": os.environ["INLINESHIELD_API_KEY"]},
timeout=3,
)
if r.status_code == 200:
status = r.json()["status"] # "pending" | "approved" | "rejected"<?php
// Response: { reviewId, status: "pending" | "approved" | "rejected", decisionReason, decidedAt, expiresAt }. Prefer the webhook; poll only as a fallback (limit 60 requests/min per key). 404 = unknown review.
$ch = curl_init('https://api.inlineshield.io/api/v1/reviews/' . rawurlencode($reviewId));
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['X-Api-Key: ' . getenv('INLINESHIELD_API_KEY')],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 3,
]);
$body = curl_exec($ch);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($body !== false && $http === 200) {
$review = json_decode($body, true);
$status = $review['status']; // 'pending' | 'approved' | 'rejected'
}// Java 11+. Response: { reviewId, status: "pending" | "approved" | "rejected", decisionReason, decidedAt, expiresAt }. Prefer the webhook; poll only as a fallback (limit 60 requests/min per key). 404 = unknown review.
HttpRequest req = HttpRequest.newBuilder(URI.create("https://api.inlineshield.io/api/v1/reviews/" + URLEncoder.encode(reviewId, StandardCharsets.UTF_8)))
.timeout(Duration.ofSeconds(3))
.header("X-Api-Key", System.getenv("INLINESHIELD_API_KEY"))
.GET().build();
HttpResponse<String> resp = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
if (resp.statusCode() == 200) {
String json = resp.body(); // parse "status": pending | approved | rejected
}// Response: { reviewId, status: "pending" | "approved" | "rejected", decisionReason, decidedAt, expiresAt }. Prefer the webhook; poll only as a fallback (limit 60 requests/min per key). 404 = unknown review.
using var req = new HttpRequestMessage(HttpMethod.Get, "https://api.inlineshield.io/api/v1/reviews/" + Uri.EscapeDataString(reviewId));
req.Headers.Add("X-Api-Key", Environment.GetEnvironmentVariable("INLINESHIELD_API_KEY"));
var resp = await http.SendAsync(req); // reuse one HttpClient with a 3 s timeout
if (resp.IsSuccessStatusCode)
{
var review = await resp.Content.ReadFromJsonAsync<JsonElement>();
var status = review.GetProperty("status").GetString(); // "pending" | "approved" | "rejected"
}Fields and errors: GET /api/v1/reviews/{reviewId}.
recommendedAction on the decision
signup.rejected carries recommendedAction: "block". signup.approved carries require_kyc when the held sign-up had signals that call for identity checks before payout, else allow.
Trying the flow
Test mode creates no reviews: a held test screening has no reviewId, and no signup.* webhook can follow it. To try a real hold end to end, use Setup › Send a test signup in the console. It runs one sign-up through screening with your own keys and does not count against your quota; when it is held you get a real reviewId to approve or reject in Review.