Developer API
What is the olow API?

A real-time verification endpoint for STI testing credentials. One API call with a user's share token returns the verification status, panel, issuer, and recommended-retest date. Auto-expiration means a verified result is always current. Developer tier is free; paid tiers from $999/mo with no hard cap, BAA available on Enterprise.

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@olow.io →

Quick start

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

bash
GET https://olow.io/api/v1/verify?token=USER_TOKEN
X-API-Key: olow_live_your_key_here
javascript
const res = await fetch(
  'https://olow.io/api/v1/verify?token=USER_TOKEN',
  { headers: { 'X-API-Key': 'olow_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 olow 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 `olow_live_`, `olow_test_`, or `olow_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.
429Tier quota or per-key rate limit exceeded. Developer tier hits this after 150 calls/mo; paid tiers have no hard cap but enforce a per-key rate limit. Upgrade tier or contact sales.
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: falseautomatically 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.

Pricing

Pricing is call-centric and uncapped — each tier comes with a monthly call allowance, and every call past it is billed at the per-call overage rate. There's no hard cap; your platform can verify as many users as it needs to, billed accordingly. olow's verification standard expects at least one call per active user per day, so plan call volume as active users × 30 minimum per month.

TierMonthlyCalls includedOverage / callRevenue-share
DeveloperFree150Upgrade required
Starter$9993,000$0.40
Growth$4,99930,000$0.20
Scale$19,999300,000$0.105% annual
Pro$79,9993,000,000$0.055% annual
EnterpriseCustom · $1M/yr floorCustomCustom8% annual or $1M, whichever greater

Developer tier returns a 429 with tier_quota_exceeded after 150 calls/month — upgrade to a paid tier to lift the limit. Paid tiers have no hard cap — every call past included is billed at the per-call overage rate. Runaway protection: quota alerts at 100/200/500%, per-API-key rate limits, and Stripe payment-failure-pause (402) keep you from being silently billed into the six figures. Scale and Pro include a 5% annual revenue-share true-up; Enterprise uses 8% with a $1,000,000/year minimum floor.

Need Enterprise?
Enterprise is for platforms doing 500,000+ daily-verified users, regulated workloads requiring a custom BAA, dedicated support, or per-region SLAs. Pricing starts at $1,000,000/year or 8% of olow-attributable revenue, whichever is greater. Contact sales →

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 user count.

html
<iframe
  src="https://olow.io/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 olow_badge_ key — a separate key class from the verify-API olow_live_ key.

GET/api/v1/badge
ParameterRequiredDescription
tokenYesPublic URL token from the user's olow link
formatNojson (default), html, or svg
javascript
// JSON — render your own badge UI
const res = await fetch(
  'https://olow.io/api/v1/badge?token=USER_TOKEN',
  { headers: { 'X-API-Key': 'olow_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://olow.io/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 olow user account (rather than a shareable link), use the OAuth 2.0 authorization code flow. The user consents in their olow account, your app receives an access token and refresh 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@olow.io to onboard as a partner and receive a client_id and client_secret. PKCE (RFC 7636) is supported and strongly recommended.

1. Redirect the user to authorize

bash
GET https://olow.io/api/oauth/authorize
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.com/callback
  &response_type=code
  &state=RANDOM_CSRF_TOKEN
  &code_challenge=BASE64URL_SHA256_OF_VERIFIER
  &code_challenge_method=S256

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.

PKCE: generate a random code_verifier of 43–128 chars, derive code_challenge = base64url(sha256(verifier)), send the challenge on the authorize URL and keep the verifier server-side for step 2.

2. Exchange the code for tokens

bash
POST https://olow.io/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",
  "code_verifier": "ORIGINAL_VERIFIER_FROM_STEP_1"
}
json
{
  "access_token": "...",
  "refresh_token": "...",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_expires_in": 2592000,
  "scope": "verify"
}

Auth codes expire after 10 minutes and are one-shot — a code can only be exchanged once. Access tokens are short-lived (15 minutes); use the refresh token to mint new ones. Store both securely on your server.

3. Refresh the access token

bash
POST https://olow.io/api/oauth/token
Content-Type: application/json

{
  "grant_type": "refresh_token",
  "refresh_token": "REFRESH_TOKEN_FROM_STEP_2",
  "client_id": "YOUR_CLIENT_ID",
  "client_secret": "YOUR_CLIENT_SECRET"
}

Refresh tokens are rotated on every use — each refresh returns a new refresh_token and invalidates the prior one. Always store the latest. Refresh tokens live 30 days from issue; after expiry the user must re-consent.

4. Check verification status

bash
GET https://olow.io/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.
I represent the business named above and I agree to the API Partner Terms of Service — including the prohibited-use list (no employment, insurance, lending, housing, immigration, or use against minors — Section 4), payment policy (Section 7), and revenue share on Scale, Pro, and Enterprise tiers (Section 6).