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
curlinstalled - 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 objectsname: Full resource name of the team (use this as parent when creating checks)displayName: Human-readable team namebrand: Associated brand resource namedescription: 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:
- A brand resource (create via
POST /v1alpha2/brandsor use existing) - Organization resource name
- Display name
Team creation endpoint:
POST /v1alpha2/teams
Required fields:
displayName- Team nameorganization- 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 checktemplate: The check template ID -checkTemplates/clientonly-verification-check-v1-0-0params: 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 withyear,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 monitoringrequireAddressVerification: Electronic address matching & verificationrequireCcjInsolvency: 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 providedclientReference: Your reference IDstate: Current check state (ACTIVE,INACTIVE,CANCELLED, orDELETED)createTime: When the check was created (ISO 8601 timestamp)updateTime: When the check was last updated (null if never updated)template: The check template usedparams: The parameters you provided (echoed back with defaults filled in)relatedSubjects: Subjects created from the check parameters (output only)- Includes a
Subjectresource with the individual's details
- Includes a
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 settingsenabled: Whether ongoing monitoring is activeactiveUntil: 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 summarycreateTime: 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 summaryreportUrl: Download URL for the full PDF reportsummaryReportUrl: Download URL for the summary PDF report
Payload Fields (for Client-Only Verification):
@type: Type identifier for the payloadoverallRecommendation: Overall check recommendationrecommendation:CLEAR,CONSIDER, orFAILdescription: Human-readable explanation
addressVerificationCheckResult: Address verification results (ifrequireAddressVerification: true)screeningCheckResult: AML screening results (always included)ccjInsolvencyCheckResult: CCJ/Insolvency results (ifrequireCcjInsolvency: true)providedSubjectData: The subject data you provided (echoed back)pdfReportUrl: Legacy field (empty string, use top-levelreportUrlinstead)summaryPdfReportUrl: Legacy field (empty string, use top-levelsummaryReportUrlinstead)
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 reportsummaryReportUrl: Download link for summary PDF reportpayload: Check-specific results
Payload Fields:
-
overallRecommendation: Overall check recommendation objectrecommendation:CLEAR,CONSIDER, orFAILdescription: 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
- Only present if
-
ccjInsolvencyCheckResult: CCJ/Insolvency check results- Only present if
requireCcjInsolvency: trueand UK address
- Only present if
Recommendation Values
CLEAR: No concerning issues found - proceed with confidenceCONSIDER: Anomalies detected that may be explainable - review findingsFAIL: 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 objectsnextPageToken: Token for pagination (empty if no more pages)
Finding Fields:
name: Resource name of the findingdisplayName: Human-readable name for the findingdescription: Human-readable description (may be empty)state: Current state of the findingUNREVIEWED- Not yet reviewedDISMISSED- Reviewed and determined not relevantCONFIRMED- Reviewed and confirmed as relevantRETRACTED_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 reportsummaryReportUrl: 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
- API Design Principles - Understand our API patterns (resource names, filtering, etc.)
- Code Generation - Generate client libraries from our OpenAPI spec
- Authentication Guide - Deep dive into OAuth 2.0 implementation
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
- Email: api@thirdfort.com
- Documentation: Browse our full API reference and guides
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
@typefield matches the check template - Ensure date formats use structured objects (year, month, day), not strings
- Verify
displayNameandclientReferenceare 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)
- CreateCheck:
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