TrialShield
Sign inStart free
API reference/v1

TrialShield API v1

Real-time risk scoring for trial signups, post-signup activity, and KYC verification. All endpoints accept and return JSON.

Introduction

TrialShield combines 100+ identity, network, payment, behavior, and content signals into a single 0–100 risk score. The most common integration is two API calls: /v1/verify at signup, and /v1/track for continuous monitoring while the user is on a trial.

All endpoints are hosted at https://trialshield.cc/api/v1.

Quickstart

  1. Create an account and request a free trial.
  2. Once approved, copy your API key from Dashboard → Settings.
  3. Send your first verification:
$ curl https://trialshield.cc/api/v1/verify \ -H "X-API-Key: $TS_KEY" \ -H "Content-Type: application/json" \ -d '{"email":"user@example.com","ip":"1.2.3.4"}'

Authentication

Every customer-facing endpoint accepts the API key in either header. Pick one — both are equivalent.

X-API-Key: ts_xxx... # or Authorization: Bearer ts_xxx...
Server-side only. Your API key must never reach the browser. Always call from a backend.

Plans & limits

Each plan unlocks a feature set and a per-key rate limit. The check happens once per request, before your handler runs.

PlanRate limitFeatures
Free trial30 req/minVerify + Track only. Approved manually.
Starter120 req/minVerify, Track, Monitor, OAuth, Stripe.
Pro600 req/minEverything in Starter plus Graph and Compliance modules.
Enterprise3,000 req/minCustom limits and self-hosted edge SDK.
POST/v1/verify

Verify

Score a signup or login event. Returns a 0–100 risk score, a recommended decision, and the signals that fired. At least one of email, phone or ip is required.

Request body

email
stringEnd-user email. At least one of email, phone or ip is required.
phone
stringE.164 phone number (e.g. +14155550100).
ip
stringEnd-user IPv4/IPv6. Auto-detected from x-forwarded-for if omitted.
deviceFingerprint
objectOptional fingerprint object (id, canvas, webgl, audio, …) from the browser SDK.
organizationId
stringGroup users so members of the same org are exempt from cross-account checks.
oauthProvider
objectOAuth metadata (provider, providerId, createdAt, githubUsername, …) for ghost-account detection.
metadata
objectFree-form context. metadata.payment is read for Stripe card signals.

Response

id
stringUnique evaluation id, used for /feedback and audit lookups.
decision
"ALLOW" | "CHALLENGE" | "DENY"Recommended action based on the score and your rules.
riskScore
number0–100. Higher is riskier. 71+ recommended for block by default.
signals
RiskSignal[]Triggered signals with module, severity, description, value.
breakdown
ScoreBreakdownPer-module subscores plus the configurable weights used.
enrichment
EnrichmentDataResolved metadata about email, phone, IP, device, behavior, graph.
processingTimeMs
numberTotal server-side time for this evaluation.
timestamp
stringISO timestamp the response was emitted.

Example

const res = await fetch("https://trialshield.cc/api/v1/verify", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.TS_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    email:    "user@example.com",
    ip:       req.ip,
    metadata: { signup_source: "organic" },
  }),
});
const result = await res.json();
if (result.decision === "DENY") throw new Error("trial_abuse");
POST/v1/track

Track

Continuous monitoring after signup. Pass any user activity (file upload, AI query, GitHub link, login) and TrialShield resolves identity, fingerprints content, and surfaces duplicate accounts that share the same device, IP, or content.

Request body

userIdrequired
stringYour stable user identifier — the one you want to monitor.
activityTyperequired
ActivityTypeOne of ai_query, file_upload, file_download, project_create, github_link, login, feature_use, export, ...
deviceFingerprint
objectLive device fingerprint captured during the session.
ip
stringSource IP. Auto-detected if omitted.
accountStatus
"trial_active" | "trial_expired" | "paid"Trial state of the user, used to gate enforcement.
metadata
objectfileHash, fileName, projectName, githubLink, query, sessionId — fields used for content fingerprinting.

Response

matchScore
number0–100 current match level vs. existing identity clusters.
status
"OK" | "WARN" | "REVOKE"Suggested enforcement based on your sensitivity setting.
matchedUserId
stringUser id this activity was linked to, if a match was found.
signals
RiskSignal[]Reasons the match score moved.
contentReuse
ContentReuseResult[]Files / projects / GitHub links seen on more than one user.
enforcement
EnforcementActionAction taken (or recommended) when status ≠ OK.
activityId
stringId you can pass to follow-up calls.
POST/v1/monitor

Monitor

Lightweight event log. Useful when you want to feed second-order signals (data exports, suspicious actions) without running the full Track pipeline.

Request body

userIdrequired
stringStable user id to monitor.
eventTyperequired
"api_call" | "feature_use" | "login" | "data_export" | "suspicious_action"Coarse event category.
metadata
objectAnything else you want logged with the event.
organizationId
stringOverride org grouping at runtime.
timestamp
stringISO timestamp. Server uses now() if omitted.
POST/v1/feedback

Feedback

Tell us when our decision was wrong (false positive / false negative). The signal flows back into the model.

evaluationIdrequired
stringThe id from a previous verify response.
isAbuserrequired
booleantrue if the user turned out to be abusive.
notes
stringFree-form context for the review team.
POST/v1/kyc/session

Create KYC session

Generate a hosted verification link for a specific end-user. The link expires after 30 minutes. Document images are purged after 30 days; cryptographic hashes are kept indefinitely for cross-tenant reuse detection.

Request body

userIdrequired
stringYour end-user id (stored as external_user_id).
level
"document_only" | "document_face" | "full"Verification depth. Default: document_face.
redirectUrl
stringWhere to send the end-user after they complete the flow.
metadata
objectFree-form metadata stored on the session.

Response

sessionId
stringUnique session id.
verifyUrl
stringHosted URL the end-user should open to complete the flow.
status
"pending"Initial status.
level
stringVerification level for this session.
expiresAt
stringISO timestamp the link stops working.
GET/v1/kyc/session/{id}

Get KYC session

Poll for the result of a KYC session. Returns status, level, the full result (decision, score, signals) once status is completed, plus timestamps.

DELETE/v1/users/{id}

Delete a user (GDPR / CCPA)

Erase every record we hold for an end-user — risk events, device graph entries, monitoring events, identity anchors, and the user row itself. Resolves id as a TrialShield user UUID by default; pass ?type=email or ?type=phone to look up by hash.

Tenant-scoped: the user must have at least one risk event tied to one of your API keys. Cross-tenant deletes are rejected with 403.

curl -X DELETE "https://trialshield.cc/api/v1/users/{userId}" \ -H "X-API-Key: $TS_KEY"
GET/v1/users/{id}

Export a user (GDPR)

Returns the user record plus all stored events, anchors and risk evaluations as JSON. Same tenant scoping as DELETE.

Decisions

Default thresholds. Override per API key from Settings → Module weights.

ALLOW0–30Low risk. No friction. Default outcome for organic users.
CHALLENGE31–70Step up: email OTP, phone verify, or invisible captcha.
DENY71–100Block + flag for review. The signup or login is rejected.

Risk signals

Every signals[] entry has a module, signal name, severity, and a human description.

module
"EMAIL" | "PHONE" | "IP" | "DEVICE" | "BEHAVIOR" | "GRAPH" | "OAUTH" | "RULES"Which detection module raised the signal.
signal
stringSlug of the specific detector (e.g. DISPOSABLE_EMAIL, VPN_DETECTED, DEVICE_REUSED).
severity
"LOW" | "MEDIUM" | "HIGH" | "CRITICAL"Severity weight applied when computing the score.
description
stringHuman-readable explanation, safe to show in support tools.
value
string | number | booleanOptional payload (e.g. detected ASN, BIN, country).

Errors

Errors come back with an error string and a stable machine-readable code.

CodeHTTPWhen
MISSING_API_KEY401No X-API-Key (or Authorization: Bearer) header was provided.
INVALID_API_KEY401The key was not found.
INACTIVE_API_KEY401The key was deactivated.
PAYMENT_REQUIRED403API key is in pending state. Subscribe or get a free trial approved to activate.
SUBSCRIPTION_INACTIVE403Subscription is canceled, expired or revoked.
TRIAL_EXPIRED403Free trial has ended. Subscribe to keep using the API.
FEATURE_UNAVAILABLE403Endpoint is not available on the current plan.
RATE_LIMIT_EXCEEDED429Plan rate limit reached. Wait or upgrade.
MISSING_INPUT400Required body fields were missing or invalid.

Rate limits

Every key has a per-minute window. The current limit comes from your plan unless you have an override from sales. Exceeded requests return 429 with the code RATE_LIMIT_EXCEEDED. The response includes X-RateLimit-Limit so you can back off.

GET/v1/health

Health

Unauthenticated. Returns {"status":"ok"} when the API is reachable. Use it as your uptime-monitor target.