Strike-Age Developer API
This reference documents the actual endpoints currently exposed by the application. For third-party integrations, use the two public endpoints under /api/public/strike-age.
API Keys & Authentication
All public endpoints require a valid x-api-key. Missing or invalid keys return 401.
x-api-key: sa_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
For integrations, send x-api-key on every request. API keys are rate-limited per key.
Verify by badge id: use GET /api/public/verify/<badge_id>. Badge ids are the same identifiers shown in the UI (e.g. ad95f9), with optional VB- prefix.
Docs demo key
For quick exploration, a low-rate demo key is prefilled in the Try It Console. It rotates daily and is restricted to sample data.
/api/public/calculateCalculate strike-adjusted employability age from date inputs. Optionally persist a verification and queue an HTML certificate email when all certificate fields are present.
Include one or more education records in the request body. The API uses the earliest admission date and latest graduation date. Legacy flat date fields are still accepted.
Persistence + certificate email: the API stores a record and returns a badge_id only when you send a valid email, full_name (or fullName), and type set to general (case-insensitive). The server sends the HTML email asynchronously when SMTP is configured. Otherwise the endpoint is calculation-only (no DB write, no badge id).
Badge stability: for the same recipient email under the same API key, the API reuses the same badge_id on subsequent calls (it updates the stored record instead of issuing a new badge).
Email: verification is sent as HTML only (no PDF attachment).
Registered users: if email matches an existing app account (case-insensitive), the API returns 409 with { "error": "Email already exists" } and does not create a verification or send mail.
Zoho Recruit: optional source (zoho / zoho_recruit). When type is general and email, phone, and full_name are all present (with valid certificate inputs), the API persists PublicVerification including phone. DOB + education only → calculate + audit row, no persistence.
BridgeTalent: optional source (bridgetalent / bridge) and flow_step / flowStep (1 or 2). Step 1 returns a server-generated correlation_id for step 2. Step 2 sends the same correlation_id plus email and full_name (resend dob / education as needed). Each successful run writes one audit row; the hit counter is the total audit row count.
Bulk spreadsheet import: use source: "dataset_import" with optional import_row_no, import_dataset_label, and import_metadata (JSON). Rows are stored only in StrikeAgeAuditLog (same as other public calculates), with source DATASET_IMPORT in the database.
Usage metering: each successful calculation (HTTP 200 with strike-age metrics) appends one row to the global strike-age audit log (StrikeAgeAuditLog). Anonymous requests are included. See GET /usage-count for the running total.
Request Body
{
"email": "jane@example.com",
"full_name": "Jane Doe",
"type": "general",
"dob": "2000-04-12",
"education": [
{
"university": "Kenyatta University",
"course": "Computer Science",
"admissionDate": "2017-11-20",
"graduationDate": "2021-10-15"
},
{
"university": "Kenyatta University",
"course": "MSc Data Science",
"admissionDate": "2021-11-15",
"graduationDate": "2023-10-15"
}
]
}cURL Example
curl -X POST "https://tpa-labs.com/api/public/calculate" \
-H "content-type: application/json" \
-H "x-api-key: sa_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-d '{"email":"jane@example.com","full_name":"Jane Doe","type":"general","dob":"2000-04-12","education":[{"university":"Kenyatta University","course":"Computer Science","admissionDate":"2017-11-20","graduationDate":"2021-10-15"},{"university":"Kenyatta University","course":"MSc Data Science","admissionDate":"2021-11-15","graduationDate":"2023-10-15"}]}'Response 200
{
"badge_id": "A1B2C3",
"badge_text": "Verified with A1B2C3",
"badge_url": "https://tpa-labs.com/lookup/A1B2C3",
"certificate_email_queued": true,
"actualAge": 26.1,
"employabilityAge": 23.2,
"strikeYears": 2.8,
"strikeMonths": 10,
"totalStrikeDays": 1021,
"badgeEligible": true
}certificate_email_queued is true only when SMTP is set and certificate email is enabled (not CERTIFICATE_EMAIL_ENABLED=0); otherwise it is false even though the verification is stored.
Response 200 (no store)
{
"actualAge": 26.1,
"employabilityAge": 23.2,
"strikeYears": 2.8,
"strikeMonths": 10,
"totalStrikeDays": 1021,
"badgeEligible": true
}Response 409 (certificate flow, email already registered)
{
"error": "Email already exists"
}Note: /api/public/strike-age/calculate is also supported and returns the same response.
/api/public/verify/[badgeId]Verify a badge id (the same identifier shown in the UI) and retrieve the fields displayed on the Verify Badge page.
Path Param
badgeId: string
cURL Example
curl "https://tpa-labs.com/api/public/verify/ad95f9" \ -H "x-api-key: sa_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Response 200
{
"badge_id": "ad95f9",
"user_id": "8de2ab",
"full_name": "Demo Candidate",
"verified_at": "2026-03-27T04:37:00.010Z",
"actual_age": 26.1,
"employability_age": 23.2,
"strike_years": 2.8,
"badge_eligible": true,
"admission_date": "2017-11-20",
"graduation_date": "2023-10-15",
"university": "Kenyatta University",
"course": "Computer Science",
"education": [
{
"university": "Kenyatta University",
"course": "Computer Science",
"admissionDate": "2017-11-20",
"graduationDate": "2023-10-15"
}
],
"strike_periods": []
}/api/public/candidates/all?limit=50List candidate badges (most recently updated first). Useful for integrations that sync candidates in batches.
Query Params
limit: number (default 50, max 200)
cURL Example
curl "https://tpa-labs.com/api/public/candidates/all?limit=50" \ -H "x-api-key: sa_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Response 200
{
"limit": 50,
"candidates": [
{
"badge_id": "ad95f9",
"user_id": "8de2ab",
"full_name": "Demo Candidate",
"verified_at": "2026-03-27T04:37:00.010Z",
"actual_age": 26,
"employability_age": 23,
"strike_years": 2.8,
"admission_date": "2017-11-20",
"graduation_date": "2023-10-15",
"university": "Kenyatta University",
"course": "Computer Science"
}
]
}/api/public/universitiesReturns the same university list used by the verification flow dropdown.
cURL Example
curl "https://tpa-labs.com/api/public/universities" \ -H "x-api-key: sa_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Response 200
{
"universities": ["Kenyatta University", "Moi University"]
}/api/public/strike-age/usage-countReturns the total number of successful public calculations (one StrikeAgeAuditLog row per successful POST /api/public/calculate with metrics), summed across all API keys.
cURL Example
curl "https://tpa-labs.com/api/public/strike-age/usage-count" \ -H "x-api-key: sa_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Response 200
{
"total_strike_ages_generated": 1234
}/api/public/strike-age/[candidateId]Legacy snapshot endpoint. Prefer /api/public/verify/[badgeId] for new integrations.
Path Param
candidateId: string
cURL Example
curl "https://tpa-labs.com/api/public/strike-age/STRK6A" \ -H "x-api-key: sa_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Errors & Rate Limits
400 Invalid payload401 Invalid / missing auth404 Candidate/key not found429 Rate limit exceeded (returns limit and usage)