Skip to main content

Quickstart Guide

Get started with the Thirdfort Client API in under 15 minutes. This guide walks you through creating your first check using the client-only verification template.

This quickstart uses the client-only verification check because it removes the need to deal with the consumer journey while testing. It is the quickest way to complete a check and get results - the check completes in seconds rather than waiting for a consumer to complete tasks via the mobile app.

Once you're comfortable with the basics, explore our product guides to learn about other check types like identity verification, source of funds, and KYB checks.

Prerequisites

Before you begin, ensure you have:

  • Thirdfort account with API access enabled
  • Client ID and Client Secret - Contact api@thirdfort.com to obtain your credentials
  • Development environment with curl installed
  • Basic understanding of REST APIs and OAuth 2.0

Note: Self-service credential management will be available from your Thirdfort account in the future.

Base URL

All API requests should be made to:

https://api.thirdfort.dev/client/api

This is the nonproduction environment for testing. Production credentials and URLs will be provided separately.


Step 1: Understand Your Credentials

Your API credentials consist of two parts:

  • Client ID: A unique identifier for your integration (e.g., client_01HQXYZ...)
  • Client Secret: A secret key used to authenticate (keep this secure!)

Security Best Practices

  • Never commit secrets to version control - Use environment variables or secure secret management
  • Rotate credentials regularly - Contact support if you suspect a compromise
  • Use nonproduction credentials for testing - Keep production credentials separate

Environments

  • Nonproduction: https://api.thirdfort.dev/client/api (for testing)
  • Production: Provided separately with production credentials

Step 2: Obtain an Access Token

The Thirdfort Client API uses OAuth 2.0 client credentials flow for authentication. You'll exchange your Client ID and Secret for an access token.

Request

curl -X POST https://creative-jungle-73-staging.authkit.app/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"

Response

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600
}

Using the Access Token

Include the access token in the Authorization header for all API requests:

Authorization: Bearer YOUR_ACCESS_TOKEN

Token Expiry

Access tokens expire after 1 hour (3600 seconds). When a token expires, request a new one using the same process. For production integrations, implement automatic token refresh before expiry.

Common Errors

  • 401 Unauthorized: Invalid Client ID or Secret - verify your credentials
  • 400 Bad Request: Missing or malformed request parameters

Step 3: Find Your Team

Checks are created under a team within your organization. Direct integrators typically have one organization with one or more teams.

List Teams

curl -X GET "https://api.thirdfort.dev/client/api/v1/organizations/{org_id}/teams" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Replace {org_id} with your organization ID (provided by Thirdfort).

Response

{
"teams": [
{
"name": "organizations/NT6bqXp6k47SbagGAUHHG7/teams/gZzg3caveKLhe3VXjRiyXL",
"displayName": "Default Team",
"brand": "organizations/NT6bqXp6k47SbagGAUHHG7/brands/QR8UjxKaEKwXbhX7GsVFkn",
"description": "",
"featureSettings": [],
"featureSetSettings": [],
"roleBindings": []
}
],
"nextPageToken": ""
}
Response Fields
  • teams: Array of team objects
  • name: Full resource name of the team (use this as parent when creating checks)
  • displayName: Human-readable team name
  • brand: Associated brand resource name
  • description: Team description (optional)
  • featureSettings: Feature flags for this team (output only)
  • featureSetSettings: Feature set configurations (output only)
  • roleBindings: User role assignments (output only)
  • nextPageToken: Token for pagination (empty if no more pages)

Extract your team resource name

From the response, note the name field. You'll use this as the parent when creating checks:

organizations/NT6bqXp6k47SbagGAUHHG7/teams/gZzg3caveKLhe3VXjRiyXL
What if I don't have a team yet?

Teams must be created with an associated brand. For the quickstart, we recommend using an existing team or contacting api@thirdfort.com to have a team created for you.

For advanced users: You can create a team programmatically using POST /v1alpha2/teams. Note that team and brand management endpoints are currently only available on v1alpha2 (preview), not v1. This requires:

  1. A brand resource (create via POST /v1alpha2/brands or use existing)
  2. Organization resource name
  3. Display name

Team creation endpoint:

POST /v1alpha2/teams

Required fields:

  • displayName - Team name
  • organization - Organization resource name (e.g., organizations/{org_id})
  • brand - Brand resource name (e.g., organizations/{org_id}/brands/{brand_id})

To list available brands:

curl -X GET "https://api.thirdfort.dev/client/api/v1alpha2/brands" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

For this quickstart, we'll assume you have at least one team available from the ListTeams response.


Step 4: Create Your First Check

Now you'll create a client-only verification check. This check performs AML screening on a subject without requiring them to complete any tasks.

Request

curl -X POST "https://api.thirdfort.dev/client/api/v1/organizations/{org_id}/teams/{team_id}/checks" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"displayName": "Client-only verification for Jane Doe",
"clientReference": "your-reference-123",
"template": "checkTemplates/clientonly-verification-check-v1-0-0",
"params": {
"@type": "type.googleapis.com/thirdfort.client.checks.type.v1.ClientOnlyVerificationCheckParams",
"subject": {
"givenName": "Jane",
"familyName": "Doe",
"dateOfBirth": {
"year": 1990,
"month": 1,
"day": 15
}
},
"address": {
"buildingNumber": "10",
"street": "Downing Street",
"locality": "London",
"postalCode": "SW1A 2AA",
"countryCode": "GBR"
}
}
}'

Understanding the Request

URL Format: /v1/{parent}/checks where {parent} is your team's full resource name in the format organizations/{org_id}/teams/{team_id}

Required Fields:

  • displayName: Human-readable name for the check (e.g., "Client-only verification for Jane Doe")
  • clientReference: Your own reference ID for tracking this check
  • template: The check template ID - checkTemplates/clientonly-verification-check-v1-0-0
  • params: Check-specific parameters (object)
    • @type: Required - Fully qualified type name (e.g., type.googleapis.com/thirdfort.client.checks.type.v1.ClientOnlyVerificationCheckParams)
    • This field tells the API which check type parameters to expect

Subject Parameters:

  • givenName: First name (required)
  • familyName: Last name (required)
  • dateOfBirth: Structured date object with year, month, day (optional but recommended)

Address Parameters:

  • buildingNumber: Building number (required)
  • street: Street name (required)
  • locality: City/town (required)
  • postalCode: Postal/ZIP code (required)
  • countryCode: ISO 3166-1 alpha-3 country code (e.g., "GBR", "USA")

Optional Parameters

You can enhance the check with optional parameters:

{
"params": {
"@type": "type.googleapis.com/thirdfort.client.checks.type.v1.ClientOnlyVerificationCheckParams",
"subject": { ... },
"address": { ... },
"enableOngoingMonitoring": true,
"requireAddressVerification": true,
"requireCcjInsolvency": true
}
}
  • enableOngoingMonitoring: Continuous AML screening monitoring
  • requireAddressVerification: Electronic address matching & verification
  • requireCcjInsolvency: Surface CCJs or insolvency indicators on an individual

Response

{
"name": "organizations/NT6bqXp6k47SbagGAUHHG7/teams/gZzg3caveKLhe3VXjRiyXL/checks/eaa99a49-7c7c-43e0-a929-ec2dddec8a85",
"displayName": "Client-only verification for Jane Doe",
"clientReference": "your-reference-123",
"state": "ACTIVE",
"createTime": "2026-03-06T14:06:59.758655Z",
"updateTime": null,
"template": "checkTemplates/clientonly-verification-check-v1-0-0",
"params": {
"@type": "type.googleapis.com/thirdfort.client.checks.type.v1.ClientOnlyVerificationCheckParams",
"subject": {
"givenName": "Jane",
"otherNames": "",
"familyName": "Doe",
"yearOfBirth": 0,
"address": null,
"dateOfBirth": {
"year": 1990,
"month": 1,
"day": 15
}
},
"address": {
"subBuilding": "",
"buildingNumber": "10",
"buildingName": "",
"street": "Downing Street",
"subLocality": "",
"locality": "London",
"administrativeArea": "",
"postalCode": "SW1A 2AA",
"countryCode": "GBR"
},
"requireAddressVerification": false,
"relationshipType": "",
"enableOngoingMonitoring": false,
"internationalAddressVerificationConsent": false,
"screeningSettings": {
"fuzziness": 0.4,
"searchProfile": ""
},
"requireCcjInsolvency": false
},
"relatedSubjects": [
{
"relationship": "",
"subject": {
"name": "organizations/NT6bqXp6k47SbagGAUHHG7/teams/gZzg3caveKLhe3VXjRiyXL/subjects/2dd55c94-fa23-42b7-93fd-f50c2c436bf4",
"individual": {
"title": "",
"givenName": "Jane",
"familyName": "Doe",
"otherNames": "",
"email": "",
"phoneNumber": "",
"dateOfBirth": {
"year": 1990,
"month": 1,
"day": 15
}
}
}
}
],
"owner": "",
"creator": "partners/thirdfort/integrations/4",
"deleteTime": null,
"purgeTime": null,
"ongoingMonitoring": {
"enabled": false,
"activeUntil": null
},
"notificationRecipient": "partners/thirdfort/integrations/4",
"ownerLabel": ""
}
Response Fields
  • name: Unique resource name of the check (use this for subsequent API calls)
  • displayName: Human-readable name you provided
  • clientReference: Your reference ID
  • state: Current check state (ACTIVE, INACTIVE, CANCELLED, or DELETED)
  • createTime: When the check was created (ISO 8601 timestamp)
  • updateTime: When the check was last updated (null if never updated)
  • template: The check template used
  • params: The parameters you provided (echoed back with defaults filled in)
  • relatedSubjects: Subjects created from the check parameters (output only)
    • Includes a Subject resource with the individual's details
  • owner: Optional owner resource (empty for standalone checks)
  • creator: User who created the check (your integration)
  • deleteTime: When the check was soft-deleted (null if not deleted)
  • purgeTime: When the check will be permanently deleted (null if not deleted)
  • ongoingMonitoring: Ongoing monitoring settings
    • enabled: Whether ongoing monitoring is active
    • activeUntil: When monitoring expires (null if not enabled)
  • notificationRecipient: User who receives notifications (defaults to creator)
  • ownerLabel: Human-readable label for owner (empty for standalone checks)

Check States

  • ACTIVE: The check is actively processing, performing analysis, waiting for data from subjects or third-party providers, or scheduled to run additional verification steps. Active checks may transition back to INACTIVE when processing completes.

  • INACTIVE: The check is not currently performing analysis or waiting for external data. This state indicates the check has completed its current processing cycle and is awaiting further action. Checks can transition from INACTIVE to ACTIVE through actions like enabling ongoing monitoring, reviewing findings, or receiving new data.

  • CANCELLED: The check has been permanently cancelled and will no longer perform any processing. This is a terminal state - cancelled checks cannot be reactivated.

  • DELETED: The check has been soft-deleted and is pending permanent removal. It can be undeleted before the retention period expires.

For client-only verification checks: Checks typically move from ACTIVE to INACTIVE within seconds once processing completes. The INACTIVE state means the check has finished its analysis and results are available.


Step 5: Retrieve Check Results

Client-only verification checks complete very quickly (usually within seconds). You can retrieve the results immediately.

Get Check Status

First, verify the check has completed:

curl -X GET "https://api.thirdfort.dev/client/api/v1/organizations/{org_id}/teams/{team_id}/checks/{check_id}" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response

{
"name": "organizations/01HQXYZ.../teams/01HQABC.../checks/01HQDEF...",
"displayName": "Client-only verification for Jane Doe",
"clientReference": "your-reference-123",
"state": "INACTIVE",
"createTime": "2026-03-06T14:06:59.758655Z",
"updateTime": "2026-03-06T14:07:00.622836Z",
"template": "checkTemplates/clientonly-verification-check-v1-0-0",
...
}

Once state is INACTIVE, you can retrieve the check summary.

Get Check Summary

curl -X GET "https://api.thirdfort.dev/client/api/v1/organizations/{org_id}/teams/{team_id}/checks/{check_id}/checkSummary" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Note: The endpoint is /checkSummary (camelCase), not /summary.

Summary Response

{
"name": "organizations/NT6bqXp6k47SbagGAUHHG7/teams/gZzg3caveKLhe3VXjRiyXL/checks/eaa99a49-7c7c-43e0-a929-ec2dddec8a85/checkSummary",
"createTime": "2026-03-06T14:07:00.537001Z",
"payload": {
"@type": "type.googleapis.com/thirdfort.client.checks.type.v1.ClientOnlyVerificationCheckSummary",
"overallRecommendation": {
"recommendation": "CONSIDER",
"description": "One or more items require consideration"
},
"addressVerificationCheckResult": ...,
"screeningCheckResult": ...,
"providedSubjectData": {
"givenName": "Jane",
"familyName": "Doe",
"otherNames": "",
"yearOfBirth": 1990,
"address": {
"subBuilding": "",
"buildingNumber": "10",
"buildingName": "",
"street": "Downing Street",
"subLocality": "",
"locality": "London",
"administrativeArea": "",
"postalCode": "SW1A 2AA",
"countryCode": "GBR"
},
"dateOfBirth": {
"year": 1990,
"month": 1,
"day": 15
}
},
"pdfReportUrl": "",
"summaryPdfReportUrl": "",
"ccjInsolvencyCheckResult": null
},
"sourceFindings": [
"organizations/NT6bqXp6k47SbagGAUHHG7/teams/gZzg3caveKLhe3VXjRiyXL/checks/eaa99a49-7c7c-43e0-a929-ec2dddec8a85/findings/KB6J4BVVVWNH3J6"
],
"reportUrl": "https://files.thirdfort.dev/client/downloads/objects/6ff46f10-ae87-42e6-8601-1f0c32ed5ba6",
"summaryReportUrl": "https://files.thirdfort.dev/client/downloads/objects/8df632f9-e3f9-4e9e-88aa-ca449debf3b8"
}
Response Fields

Top-Level Fields:

  • name: Resource name of the check summary
  • createTime: When the summary was created (ISO 8601 timestamp)
  • payload: Check-specific summary data (type varies by check template)
  • sourceFindings: Array of finding resource names that contributed to this summary
  • reportUrl: Download URL for the full PDF report
  • summaryReportUrl: Download URL for the summary PDF report

Payload Fields (for Client-Only Verification):

  • @type: Type identifier for the payload
  • overallRecommendation: Overall check recommendation
    • recommendation: CLEAR, CONSIDER, or FAIL
    • description: Human-readable explanation
  • addressVerificationCheckResult: Address verification results (if requireAddressVerification: true)
  • screeningCheckResult: AML screening results (always included)
  • ccjInsolvencyCheckResult: CCJ/Insolvency results (if requireCcjInsolvency: true)
  • providedSubjectData: The subject data you provided (echoed back)
  • pdfReportUrl: Legacy field (empty string, use top-level reportUrl instead)
  • summaryPdfReportUrl: Legacy field (empty string, use top-level summaryReportUrl instead)

Note: The addressVerificationCheckResult, screeningCheckResult, and ccjInsolvencyCheckResult fields contain detailed results that vary based on the data provided and checks performed. See the full API reference for complete field descriptions.

Understanding the Results

Top-Level Fields:

  • reportUrl: Download link for full PDF report
  • summaryReportUrl: Download link for summary PDF report
  • payload: Check-specific results

Payload Fields:

  • overallRecommendation: Overall check recommendation object

    • recommendation: CLEAR, CONSIDER, or FAIL
    • description: Human-readable explanation
  • screeningCheckResult: AML screening results (sanctions/PEP)

    • Always included in client-only verification checks
  • addressVerificationCheckResult: Address verification results

    • Only present if requireAddressVerification: true
  • ccjInsolvencyCheckResult: CCJ/Insolvency check results

    • Only present if requireCcjInsolvency: true and UK address

Recommendation Values

  • CLEAR: No concerning issues found - proceed with confidence
  • CONSIDER: Anomalies detected that may be explainable - review findings
  • FAIL: Serious anomalies detected, unlikely explainable - high risk

List Findings (If Any)

If the check found any issues (e.g., sanctions matches), you can retrieve detailed findings:

curl -X GET "https://api.thirdfort.dev/client/api/v1/organizations/{org_id}/teams/{team_id}/checks/{check_id}/findings" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response

{
"findings": [
{
"name": "organizations/NT6bqXp6k47SbagGAUHHG7/teams/gZzg3caveKLhe3VXjRiyXL/checks/eaa99a49-7c7c-43e0-a929-ec2dddec8a85/findings/KB6J4BVVVWNH3J6",
"displayName": "John A. Smith",
"description": "",
"state": "UNREVIEWED",
"payload": {
"@type": "type.googleapis.com/thirdfort.client.checks.type.v1.IndividualScreeningCheckSearchResultFinding",
"id": "KB6J4BVVVWNH3J6",
"matchName": "John A. Smith",
"hitTypes": [
"WARNING"
],
"matchTypes": [
"NAME_EXACT"
],
"dateOfBirthVariations": null,
"genderVariations": null,
"nationalityVariations": null,
"countryCodes": [],
"aliases": [
"John A. Smith"
],
"politicalPositions": [],
"associates": [],
"institutions": [],
"mediaItems": [],
"sources": [
{
"title": "Example Sanctions List",
"hitTypes": [
"WARNING"
],
"fields": [
{
"name": "Activation Date",
"value": "01/01/2020"
},
{
"name": "Enforcement Agency",
"value": "Example Agency"
},
...
],
"url": "https://example.com/sanctions-list",
"listingStarted": "2020-01-01T00:00:00Z",
"listingEnded": "2021-01-01T00:00:00Z",
"lastUnreadUpdateTime": null,
"id": "example-sanctions-list"
}
]
},
"sources": [
"ComplyAdvantage"
],
"createTime": "2026-03-06T14:07:00.516804Z"
}
],
"nextPageToken": ""
}
Response Fields
  • findings: Array of finding objects
  • nextPageToken: Token for pagination (empty if no more pages)

Finding Fields:

  • name: Resource name of the finding
  • displayName: Human-readable name for the finding
  • description: Human-readable description (may be empty)
  • state: Current state of the finding
    • UNREVIEWED - Not yet reviewed
    • DISMISSED - Reviewed and determined not relevant
    • CONFIRMED - Reviewed and confirmed as relevant
    • RETRACTED_BY_PROVIDER - Provider retracted the finding
  • payload: Finding-specific data (type varies by finding type)
  • sources: Array of data source names (e.g., "ComplyAdvantage")
  • createTime: When the finding was created

Note: The payload structure varies depending on the finding type. For screening findings, it includes match details, hit types, sources, and other relevant information. See the full API reference for complete payload schemas.


Downloading PDF Reports

The check summary includes download URLs for both full and summary PDF reports. Download them using your access token:

# Download full PDF report
curl -X GET "https://files.thirdfort.dev/client/downloads/objects/{object_id}" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-o report.pdf

The reportUrl and summaryReportUrl fields contain complete URLs - use them directly without modification.

Example

From the summary response above, extract the reportUrl:

{
"reportUrl": "https://files.thirdfort.dev/client/downloads/objects/6ff46f10-ae87-42e6-8601-1f0c32ed5ba6",
"summaryReportUrl": "https://files.thirdfort.dev/client/downloads/objects/8df632f9-e3f9-4e9e-88aa-ca449debf3b8"
}

Download the full report:

curl -X GET "https://files.thirdfort.dev/client/downloads/objects/6ff46f10-ae87-42e6-8601-1f0c32ed5ba6" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-o full-report.pdf

Download the summary report:

curl -X GET "https://files.thirdfort.dev/client/downloads/objects/8df632f9-e3f9-4e9e-88aa-ca449debf3b8" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-o summary-report.pdf

Important Notes

  • Authentication required: Use the same OAuth 2.0 access token you use for API calls
  • Token expiry: If your token expires, the download will fail with 401 Unauthorized
  • Two report types:
    • reportUrl: Full detailed report
    • summaryReportUrl: Condensed summary report
  • File format: Both URLs return PDF files (binary data)

Next Steps

Congratulations! You've successfully created your first check and retrieved the results. Here's what to explore next:

Explore Other Check Types

  • Identity Verification - Full E2E ID verification with consumer in the flow
  • Source of Funds - Standalone SOF verification with document uploads
  • Identity Document Verification - Verify client-uploaded documents
  • KYB Verification - Know Your Business checks for companies

Learn More

Production Readiness

  • Webhooks: Contact api@thirdfort.com to set up webhook notifications for check status updates
  • Production Credentials: Request production credentials when you're ready to go live
  • Rate Limiting: Review our rate limiting policies (separate guide)

Get Help


Troubleshooting

Common Issues

401 Unauthorized

  • Verify your Client ID and Secret are correct
  • Check that your access token hasn't expired (tokens last 1 hour)
  • Ensure you're using the correct token endpoint: https://creative-jungle-73-staging.authkit.app/oauth2/token

400 Bad Request - "field required"

  • Check that all required fields are included in your request
  • Verify the @type field matches the check template
  • Ensure date formats use structured objects (year, month, day), not strings
  • Verify displayName and clientReference are included

404 Not Found

  • Verify the resource name format is correct
  • Check that the organization ID and team ID exist
  • Ensure you're using the correct endpoint paths:
    • CreateCheck: /v1/{parent}/checks
    • GetCheckSummary: /v1/{check_id}/checkSummary (not /summary)

Check stays in ACTIVE state

  • Client-only checks should complete within seconds
  • If stuck, contact support with the check ID

Last updated: 2026-03-06