Persona

Persona

Build a production integration with Persona API

Build a production integration with Persona API

Jun 8, 20264 min readBy Persona Examples

Integrating identity verification into production systems requires careful orchestration of authentication, data normalization, and status tracking across multiple workflows. Persona provides REST APIs and SDKs to embed identity verification, case management, and inquiry workflows into your production systems. Persona's inquiry and case endpoints enable you to generate verification links, track review status, and correlate verification data with your account records. This tutorial walks through a four-stage integration pattern—authentication, inquiry creation, review orchestration, and account relation mapping—using TypeScript.

What this tutorial covers

  • Outcome: You will build a production-ready TypeScript service that generates one-time verification links, marks inquiries for review, updates case status, and retrieves account relations from Persona.
  • Endpoints used: `POST /api/v1/inquiries/%7Binquiry-id%7D/generate-one-time-link`, `POST /api/v1/inquiries/%7Binquiry-id%7D/mark-for-review`, `POST /api/v1/cases/%7Bcase-id%7D/set-status`, `GET /api/v1/accounts/%7Baccount-id%7D/relations`
  • Language: typescript
  • Auth: API key (Authorization header with Bearer token)
  • Estimated implementation time: ~15 minutes

Step 1: Set up Persona API client with authentication

Production integrations with Persona require a typed HTTP client that handles authentication, error recovery, and request logging. Initialize a reusable client that passes your API key securely and provides methods for all four inquiry and case operations.

Initialize authenticated client

You now have a typed, reusable Persona HTTP client that automatically includes authentication headers and handles errors consistently across all API calls.

Step 2: Generate one-time verification links for inquiries

Persona inquiries represent identity verification workflows; generating a one-time link allows you to send a secure URL to end users without exposing inquiry IDs. This approach follows event-driven best practices by decoupling inquiry creation from user-facing verification flows.

Generate one-time link

Response:

json
1const url = 'https://api.withpersona.com/api/v1/inquiries/inquiry-id/generate-one-time-link';
2const options = {
3  method: 'POST',
4  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
5  body: '{}'
6};
7
8try {
9  const response = await fetch(url, options);
10  const data = await response.json();
11  console.log(data);
12} catch (error) {
13  console.error(error);
14}

Step 3: Mark inquiries for manual review in Persona

After an inquiry is submitted, you may detect risk signals or edge cases that require human review; Persona's mark-for-review endpoint escalates inquiries to your compliance team. This gate enforces data quality and enables targeted review workflows without rebuilding case management logic.

Escalate inquiry for review

Response:

json
1const url = 'https://api.withpersona.com/api/v1/inquiries/inquiry-id/mark-for-review';
2const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
3
4try {
5  const response = await fetch(url, options);
6  const data = await response.json();
7  console.log(data);
8} catch (error) {
9  console.error(error);
10}

Step 4: Update case status and retrieve account relations

Cases in Persona represent the overall verification lifecycle; after review, your system updates case status to reflect approval or rejection decisions. Retrieving account relations normalizes data across your database, enabling the four-stage pipeline pattern of authentication, normalization, enrichment, and correlation.

Set case status and fetch relations

typescript
1const token = process.env.PERSONA_API_KEY;
2const caseId = 'case_example123';
3const accountId = 'account_example456';
4
5// Update case status to Approved
6const caseUrl = 'https://api.withpersona.com/api/v1/cases/case-id/set-status';
7const caseOptions = {
8  method: 'POST',
9  headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
10  body: '{"meta":{"status":"Approved"}}'
11};
12
13try {
14  const caseResponse = await fetch(caseUrl, caseOptions);
15  const caseData = await caseResponse.json();
16  console.log('Case status updated:', caseData);
17
18  // Retrieve account relations for normalization
19  const relUrl = 'https://api.withpersona.com/api/v1/accounts/account-id/relations?filter=%7B%22key%22%3A%22string%22%7D';
20  const relOptions = { method: 'GET', headers: { Authorization: `Bearer ${token}` } };
21  const relResponse = await fetch(relUrl, relOptions);
22  const relData = await relResponse.json();
23  console.log('Account relations retrieved:', relData);
24} catch (error) {
25  console.error(error);
26}

Response:

json
1const caseStatusResponse = await fetch(
2  'https://api.withpersona.com/api/v1/cases/case-id/set-status',
3  {
4    method: 'POST',
5    headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
6    body: '{"meta":{"status":"Approved"}}'
7  }
8).then(r => r.json());
9
10const relationsResponse = await fetch(
11  'https://api.withpersona.com/api/v1/accounts/account-id/relations?filter=%7B%22key%22%3A%22string%22%7D',
12  {method: 'GET', headers: {Authorization: 'Bearer <token>'}}
13).then(r => r.json());
14
15const combined = {
16  caseStatus: caseStatusResponse,
17  accountRelations: relationsResponse
18};
19
20console.log(combined);

Step 5: Implement continuous integration health monitoring

Production observability requires monitoring that Persona API calls succeed, requests complete within SLA, and error rates remain low. Wrap your Persona operations in middleware that logs metrics and emits alerts when thresholds breach.

Add observability middleware

typescript
1const token = process.env.PERSONA_API_TOKEN;
2const SLA_MS = 5000;
3const ERROR_RATE_THRESHOLD = 0.05;
4let totalRequests = 0, failedRequests = 0;
5
6async function monitoredPersonaCall(url: string, options: object): Promise<any> {
7  const startTime = Date.now();
8  totalRequests++;
9  try {
10    const response = await fetch(url, options);
11    const data = await response.json();
12    const duration = Date.now() - startTime;
13    if (duration > SLA_MS) console.warn(`SLA breach: ${duration}ms > ${SLA_MS}ms`);
14    return data;
15  } catch (error) {
16    failedRequests++;
17    const errorRate = failedRequests / totalRequests;
18    if (errorRate > ERROR_RATE_THRESHOLD) console.error(`Alert: error rate ${(errorRate * 100).toFixed(2)}% exceeds ${(ERROR_RATE_THRESHOLD * 100)}%`);
19    throw error;
20  }
21}
22
23const url = 'https://api.withpersona.com/api/v1/inquiries/inquiry-id/generate-one-time-link';
24const options = {
25  method: 'POST',
26  headers: {Authorization: `Bearer ${token}`, 'Content-Type': 'application/json'},
27  body: '{}'
28};
29
30const data = await monitoredPersonaCall(url, options);
31console.log(data);

Your Persona integration now emits structured metrics that feed dashboards and alerts, enabling your team to detect latency spikes or increased error rates before they impact users.

Common pitfalls when using Persona

  • Not normalizing inquiry state early. Store inquiry and case status in your own database immediately after API calls, rather than reading state from Persona on every request. This reduces API load, ensures consistency across your services, and decouples your system from Persona's availability.
  • Polling instead of event-driven updates. If Persona supports webhook notifications for inquiry completion or case status changes, prefer webhooks over polling. Event-driven integrations reduce latency and API overhead, aligning with production best practices for systems like SAP HR that expose event-based services.
  • Treating API keys as secrets without rotation. Rotate Persona API keys regularly and store them in a secrets manager (e.g., AWS Secrets Manager, HashiCorp Vault). Never commit keys to version control; load them from environment variables or secure vaults at runtime.
  • Ignoring schema variability in account relations. Account relations may contain custom fields or non-standard structures across different Persona instances. Validate and map relation data early in your pipeline, and log schema mismatches so your team can adjust mappings before production incidents occur.

Your production integration with Persona is now structured for reliability and observability. Get started with Persona and ship identity verification at scale.

Documentation references

The code examples in this tutorial are grounded in the following docs pages:

Want to streamline identity verification?

See how top tech teams use Withpersona to automate KYC, reduce fraud, and accelerate onboarding securely.

Read More Blog Posts

PersonaPersona

Actionable identity tips for technical leaders

© 2026 Persona. All rights reserved.