AI Integration Prompt
Use this prompt with your AI coding assistant (Cursor, Copilot, Claude, ChatGPT, etc.) to quickly integrate the Truest Human identity verification API into your application. Paste it into your AI's context and it will know exactly how to build the integration.
What this prompt includes
- Complete API endpoint and authentication details
- Full request and response schemas with types
- Ready-to-use TypeScript code: Zod schemas, request function, and API route
- KBA question handling flow and best practices
- Test identity data for development
- Security rules your AI should follow
How to use
- Copy the prompt below
- Paste it into your AI assistant's context (system prompt, project rules file, or conversation)
- Ask your AI to integrate identity verification into your app — it will have everything it needs
AI Integration Prompt
You are integrating the Truest Human identity verification API. This API performs KBA (Knowledge-Based Authentication) to verify a person's identity using personal information and dynamically generated questions.
## API Overview
- **Base URL**: `https://truesthuman.com/api`
- **Endpoint**: `POST /api/dkba`
- **Auth**: API key via `Authorization` header (no "Bearer" prefix)
## API Keys
There are two types of API keys:
- **Live Key** (`th_live_...`): Production use. Incurs charges, performs real verifications.
- **Test Key** (`th_test_...`): Testing and development. Free, returns mock data.
Both are found on the Truest Human dashboard after signing up.
## Environment Variables
Add these to your `.env`:
```
TRUEST_HUMAN_API_KEY=th_test_your_key_here
TRUEST_HUMAN_API_ENDPOINT=https://truesthuman.com/api
```
## Request Schema
`POST {TRUEST_HUMAN_API_ENDPOINT}/dkba`
Headers:
```
Content-Type: application/json
Authorization: {TRUEST_HUMAN_API_KEY}
```
Request body (JSON):
```json
{
"firstName": "string (required)",
"lastName": "string (required)",
"street": "string (required) - full street address",
"city": "string (required)",
"state": "string (required) - 2-letter state code",
"zipCode": "string (required)",
"dateOfBirth": "string (required) - YYYY-MM-DD format",
"ssn": "string (required) - last 4 digits",
"middleName": "string (optional)",
"generation": "string (optional) - e.g. Jr, Sr, III",
"phoneNumber": "string (optional, nullable) - 10 digits, no formatting",
"emailAddress": "string (optional)",
"ipAddress": "string (optional) - user's IP address"
}
```
## Response Schema
### Success Response (`ok: true`)
```json
{
"ok": true,
"data": {
"workflowOutcome": {
"code": "string - P (Pass), R (Review), or F (Fail)",
"description": "string"
},
"kbaQuestions": {
"questions": [
{
"text": "string - the question prompt",
"questionType": "number - question category identifier",
"answers": [
{
"text": "string - the answer text",
"isCorrect": "boolean - whether this is the correct answer"
}
]
}
]
},
"dkba": {
"consumerIdDetail": {
"areaCode": "string",
"phone": "string",
"reportedDate": { "day": "string", "month": "string", "year": "string" },
"lastTouchedDate": { "day": "string", "month": "string", "year": "string" },
"firstName": "string",
"middleInitial": "string",
"lastName": "string",
"street": "string",
"city": "string",
"state": "string",
"zipCode": "string",
"zipPlusFour": "string",
"county": "string"
},
"dateOfBirthResult": { "code": "string", "description": "string" },
"phoneVerificationResult": { "code": "string", "description": "string" },
"socialSecurityNumberResult": { "code": "string", "description": "string" }
}
},
"meterEvent": {
"object": "string",
"created": "number",
"event_name": "string",
"identifier": "string",
"livemode": "boolean",
"payload": { "stripe_customer_id": "string", "value": "string" },
"timestamp": "number"
}
}
```
### Error Response (`ok: false`)
```json
{
"ok": false,
"errorMessage": "string - human-readable error message",
"errors": [
{
"code": "string",
"detail": "string"
}
]
}
```
Validation errors (422) include Zod issues:
```json
{
"ok": false,
"errorMessage": "string",
"issues": [{ "code": "string", "message": "string", "path": ["field"] }]
}
```
## Integration Pattern
Here is the recommended server-side integration pattern. NEVER call the Truest Human API from the client — always proxy through your own API route.
### 1. Create a Zod schema file for type safety
```typescript
// lib/dkba-schemas.ts
import { z } from "zod";
export const dkbaRequestSchema = z.object({
firstName: z.string(),
lastName: z.string(),
middleName: z.string().optional(),
generation: z.string().optional(),
street: z.string(),
city: z.string(),
state: z.string(),
zipCode: z.string(),
dateOfBirth: z.string(),
ssn: z.string(),
phoneNumber: z.string().nullable().optional(),
emailAddress: z.string().optional(),
ipAddress: z.string().optional(),
});
export type DkbaRequest = z.infer<typeof dkbaRequestSchema>;
const evsResultSchema = z.object({
code: z.string(),
description: z.string().optional(),
});
const evsAnswerSchema = z.object({
text: z.string(),
isCorrect: z.boolean(),
});
const evsQuestionSchema = z.object({
text: z.string(),
questionType: z.number(),
answers: z.array(evsAnswerSchema),
});
const evsAssureIdSchema = z.object({
consumerIdDetail: z.object({
areaCode: z.string(),
phone: z.string(),
reportedDate: z.object({ day: z.string(), month: z.string(), year: z.string() }),
lastTouchedDate: z.object({ day: z.string(), month: z.string(), year: z.string() }),
firstName: z.string(),
middleInitial: z.string(),
lastName: z.string(),
street: z.string(),
city: z.string(),
state: z.string(),
zipCode: z.string(),
zipPlusFour: z.string(),
county: z.string(),
}).optional(),
dateOfBirthResult: evsResultSchema,
phoneVerificationResult: evsResultSchema,
socialSecurityNumberResult: evsResultSchema,
});
const meterEventSchema = z.object({
object: z.string(),
created: z.number(),
event_name: z.string(),
identifier: z.string(),
livemode: z.boolean(),
payload: z.record(z.string(), z.string()),
timestamp: z.number(),
});
const dkbaSuccessSchema = z.object({
ok: z.literal(true),
data: z.object({
kbaQuestions: z.object({
questions: z.array(evsQuestionSchema),
}),
workflowOutcome: evsResultSchema,
dkba: evsAssureIdSchema,
}),
meterEvent: meterEventSchema,
});
const dkbaFailureSchema = z.object({
ok: z.literal(false),
errorMessage: z.string(),
errors: z.array(z.object({
code: z.string(),
detail: z.string(),
})).optional(),
});
export const dkbaResponseSchema = dkbaSuccessSchema.or(dkbaFailureSchema);
export type DkbaResponse = z.infer<typeof dkbaResponseSchema>;
```
### 2. Create a server-side request function
```typescript
// lib/request-dkba.ts
import { DkbaRequest, dkbaRequestSchema, dkbaResponseSchema } from "./dkba-schemas";
export async function requestDkba(request: DkbaRequest) {
const validated = dkbaRequestSchema.parse(request);
const endpoint = process.env.TRUEST_HUMAN_API_ENDPOINT;
if (!endpoint) throw new Error("TRUEST_HUMAN_API_ENDPOINT is not defined");
const apiKey = process.env.TRUEST_HUMAN_API_KEY;
if (!apiKey) throw new Error("TRUEST_HUMAN_API_KEY is not defined");
const response = await fetch(`${endpoint}/dkba`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: apiKey,
},
body: JSON.stringify(validated),
});
const json = await response.json();
return dkbaResponseSchema.parse(json);
}
```
### 3. Create an API route that calls Truest Human
```typescript
// app/api/verify-identity/route.ts (Next.js example)
import { NextResponse } from "next/server";
import { requestDkba } from "@/lib/request-dkba";
import { DkbaRequest } from "@/lib/dkba-schemas";
export async function POST(request: Request) {
try {
// Authenticate your own user first
// const user = await getCurrentUser();
const body = await request.json();
const dkbaRequest: DkbaRequest = {
firstName: body.firstName,
lastName: body.lastName,
middleName: body.middleName,
street: body.street,
city: body.city,
state: body.state,
zipCode: body.zipCode,
dateOfBirth: body.dateOfBirth, // "YYYY-MM-DD"
ssn: body.ssn, // last 4 digits
phoneNumber: body.phoneNumber,
emailAddress: body.emailAddress,
ipAddress: request.headers.get("x-forwarded-for") ?? undefined,
};
const result = await requestDkba(dkbaRequest);
if (!result.ok) {
return NextResponse.json(
{ error: result.errorMessage },
{ status: 400 }
);
}
// Check workflow outcome
const passed = ["P", "R"].includes(result.data.workflowOutcome.code);
const hasIdentity = result.data.dkba.consumerIdDetail != null;
if (!passed || !hasIdentity) {
return NextResponse.json({ verified: false, reason: "identity_check_failed" });
}
// Store KBA questions in your database for the user to answer
const questions = result.data.kbaQuestions.questions;
if (questions.length === 0) {
// "Thin file" — identity verified but no KBA questions available.
// The user is real but can't be verified via knowledge-based questions.
return NextResponse.json({ verified: true, thinFile: true });
}
// Save questions to your DB and present them to the user.
// Each question has multiple-choice answers with isCorrect flags.
// Recommended: 5 questions per round, require 4/5 correct to pass.
// You can offer up to 2 rounds before blocking.
return NextResponse.json({
verified: false,
questionsAvailable: true,
questionCount: questions.length,
});
} catch (error) {
console.error("Verification error:", error);
return NextResponse.json(
{ error: "Verification failed" },
{ status: 500 }
);
}
}
```
## Handling KBA Questions
The API returns 9–15 multiple-choice questions. The recommended flow:
1. Store all questions in your database (never send correct answers to the client)
2. Present 5 questions at a time to the user
3. Give the user a time limit (e.g. 2 minutes per round)
4. Require 4/5 correct answers to pass
5. If they fail round 1, offer a second round with different questions
6. If they fail round 2, block the user from further attempts
When presenting questions to the client, strip the `isCorrect` field from answers:
```typescript
const clientQuestion = {
id: dbQuestion.id,
text: question.text,
answers: question.answers.map((a, i) => ({
id: i,
text: a.text,
// Do NOT include isCorrect
})),
};
```
## Workflow Outcome Codes
- **P** (Pass): Identity verified, KBA questions available
- **R** (Review): Similar to Pass, questions may be available
- **F** (Fail): Identity could not be verified
## Verification Result Codes
The `dkba` object contains match results:
- `socialSecurityNumberResult.code`: SSN match (e.g. "YA" = full match)
- `dateOfBirthResult.code`: DOB match (e.g. "9" = exact match)
- `phoneVerificationResult.code`: Phone match (e.g. "EA" = exact match)
## Test Identities
With a test API key (`th_test_...`), these identities return predictable responses:
| Name | Description | Questions |
|------|-------------|-----------|
| Sarah Johnson | Standard pass | 10 questions |
| Michael Chen | Thin file (no questions) | 0 questions |
| Emily Rodriguez | Standard pass | 11 questions |
| James Williams | Standard pass | 12 questions |
| Priya Patel | Standard pass | 10 questions |
| Robert Taylor | Thin file (no questions) | 0 questions |
| Maria Garcia | Standard pass | 13 questions |
| David Kim | Standard pass | 10 questions |
| Lisa Thompson | Standard pass | 10 questions |
| Thomas Anderson | Standard pass | 10 questions |
Any other name with a test key returns a standard pass with 10 questions.
## Important Rules
1. NEVER call the Truest Human API from client-side code — always proxy through your server
2. NEVER send `isCorrect` answer flags to the client
3. NEVER store the user's full SSN — the API only needs the last 4 digits
4. ALWAYS validate request data with the schema before sending
5. ALWAYS handle both success and error responses
6. Use the test key during development, switch to live key for production