Developer API

Add live STI verification to your platform

One API call. Pass your API key in the X-API-Key header. Returns live verification status that auto-expires when the user is due for retest — so a verified badge always means something current.

Partner with us →See the API
Quick startVerify endpointResponse schemaErrors & status codesAuto-expirationRate limits & pricingBadge embed (free)Badge Display APIOAuth for linked appsPrivacyPartnerships
Partnership inquiry
Interested in a native integration? We work with dating apps on co-branded rollouts.
api@testedclear.com →

Quick start

Apply for an API key below. Pass it in the X-API-Key header with every request.

bash
GET https://testedclear.com/api/v1/verify?token=USER_TOKEN
X-API-Key: tc_live_your_key_here
javascript
const res = await fetch(
  'https://testedclear.com/api/v1/verify?token=USER_TOKEN',
  { headers: { 'X-API-Key': 'tc_live_your_key_here' } }
)
const { verified, panel, tested_date, retest_by } = await res.json()

if (verified) {
  showVerifiedBadge({ panel, tested_date, retest_by })
} else {
  showRetestPrompt()
}

Verify endpoint

GET/api/v1/verify
ParameterRequiredDescription
tokenYesPublic URL token from the user's TestedClear link
formatNojson (default) or badge (HTML embed)

Response schema

json
// 200 OK — verified and within testing window
{
  "verified": true,
  "panel": "Full STI Panel",
  "tested_date": "2026-04-01",
  "retest_by": "2026-07-01",
  "issuer_type": "clinic",
  "status": "current"
}

// 200 OK — retest window has passed
{
  "verified": false,
  "reason": "retest_due",
  "retest_by": "2026-04-01"
}

// 200 OK — user revoked their credential
{
  "verified": false,
  "reason": "revoked"
}

// 404 Not Found — token does not match any credential
{
  "verified": false,
  "reason": "invalid_token"
}

All non-error responses return verified as a boolean — that is the only field you need to gate access on. Treat any non-200 status (other than 404) as a transient failure and retry.

Errors & status codes

Errors are returned as JSON with an error field and the status code in the HTTP response.

StatusWhen it happens
400Missing the `token` query parameter.
401Missing `X-API-Key` header, or key format is not `tc_live_`, `tc_test_`, or `tc_badge_`, or key is not recognized.
403Key has been suspended, or your application status is not approved.
404Token does not match any credential in our system.
429Free-tier monthly limit reached (100 calls). Upgrade to a paid tier.
500Server error. Retry with exponential backoff.

Every error response includes docs and apply URLs so that unfamiliar consumers of the API get pointed to the right place.

Auto-expiration

This is the key differentiator
The API returns verified: false automatically when the user's recommended retest date passes — no action needed from you or the user. A verified badge always means currently within testing window.

Rate limits & pricing

Usage is metered per-month per-key. Each successful call counts as one unit. Calls that return 4xx errors do not count against usage.

TierMonthlyIncluded callsOverage per call
DeveloperFree100Hard cap at 100/month
Starter$1492,000$0.20
Growth$59915,000$0.12
Scale$1,99975,000$0.08

Developer tier is capped — once you hit 100 calls in a month, the endpoint returns 429 until the 1st of next month. Paid tiers allow overage and bill automatically through Stripe.

Badge embed (free)

The simplest integration — an iframe that renders a small verified badge. Uses format=badge on the standard verify endpoint and counts toward your monthly call quota.

html
<iframe
  src="https://testedclear.com/api/v1/verify?token=USER_TOKEN&format=badge"
  width="220" height="60" frameborder="0"
  style="border:none;border-radius:10px;"
></iframe>

Badge Display API

For integrations that want richer badge options (SVG, HTML with display name, JSON for native rendering), use the dedicated Badge Display endpoint. Requires a tc_badge_ key — a separate key class from the verify-API tc_live_ key.

GET/api/v1/badge
ParameterRequiredDescription
tokenYesPublic URL token from the user's TestedClear link
formatNojson (default), html, or svg
javascript
// JSON — render your own badge UI
const res = await fetch(
  'https://testedclear.com/api/v1/badge?token=USER_TOKEN',
  { headers: { 'X-API-Key': 'tc_badge_your_key_here' } }
)
const { verified, display_name, panel, tested_date, retest_by, badge_url } = await res.json()

// SVG — drop-in image tag
// <img src="https://testedclear.com/api/v1/badge?token=USER_TOKEN&format=svg" />

The JSON response includes display_name when the user has set one — useful for rendering a personalized badge alongside a user's profile.

OAuth for linked apps

For apps that want verification status tied to a specific TestedClear user account (rather than a shareable link), use the OAuth 2.0 authorization code flow. The user consents in their TestedClear account, your app receives a long-lived access token, and you can then check verification status without the user ever sharing a link with you.

OAuth is a separate integration pathway — contact api@testedclear.com to onboard as a partner and receive a client_id and client_secret.

1. Redirect the user to authorize

bash
GET https://testedclear.com/api/oauth/authorize
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.com/callback
  &response_type=code
  &state=RANDOM_CSRF_TOKEN

The redirect_uri must exactly match one of the URIs registered with your partnership. After the user consents, they're redirected back with ?code=...&state=... appended.

2. Exchange the code for an access token

bash
POST https://testedclear.com/api/oauth/token
Content-Type: application/json

{
  "grant_type": "authorization_code",
  "code": "AUTH_CODE_FROM_CALLBACK",
  "client_id": "YOUR_CLIENT_ID",
  "client_secret": "YOUR_CLIENT_SECRET",
  "redirect_uri": "https://yourapp.com/callback"
}

Auth codes expire after 10 minutes and are one-shot — they can only be exchanged once. Store the resulting access_token securely on your server.

3. Check verification status

bash
GET https://testedclear.com/api/oauth/me
Authorization: Bearer ACCESS_TOKEN
json
// Verified
{
  "verified": true,
  "panel": "Full STI Panel",
  "tested_date": "2026-04-01",
  "retest_by": "2026-07-01",
  "issuer_type": "clinic"
}

// Retest due
{
  "verified": false,
  "reason": "retest_due",
  "retest_by": "2026-04-01"
}

// No active credential
{
  "verified": false,
  "reason": "no_active_credential"
}

The OAuth endpoint returns the same verification shape as the verify API but tied to the user who consented — no token-sharing required. Same auto-expiration semantics apply.

Privacy

✓ ReturnedVerification status, test panel, test date, retest-by date
✗ Never returnedPhone number, name, email, raw results, user ID

Partnerships

We work with dating apps on deeper integrations — native badge display, user auth flows, and co-branded verification experiences.

Apply for API access
Free tier available. Enterprise pricing for high-volume integrations.