Checkio API

Credit Report Integration Guide

Step-by-step guide to generating credit reports, handling authentication challenges, and testing your integration.

Overview

Generating a credit report is a multi-step process. Depending on the credit bureau's risk assessment, the consumer may need to verify their identity before the report data is returned.

  1. Submit a generate request with the consumer's personal details and address.
  2. Check the response status — the report may complete immediately or require an authentication challenge.
  3. If a challenge is required, collect the OTP from the consumer and submit it.
  4. On successful verification, the credit report data is returned.
Request Flow

The flow branches based on the provider's response:

Your AppCheckio APIPOST /credit-reportsResponseCheck status:"complete"Report data returned"blocked"Cannot proceed"auth-required"OTP sent via SMSPOST /otp-challengeResponseCheck status:"complete"Report data returned"retry"Try again (max 3 attempts)"failed"Max attempts exhausted

Statuses

StatusMeaning
completeReport generated successfully. Credit data is included in the response.
authentication-requiredThe provider requires identity verification before releasing data. An OTP has been sent via SMS.
blockedThe provider blocked the request due to risk assessment. The report cannot proceed.
retryOTP code was incorrect. Check attemptsRemaining and prompt the consumer to try again.
failedMaximum OTP attempts exhausted or an unrecoverable error occurred.
Prerequisite: Device Fingerprinting

Before making credit report requests, you must embed our device fingerprinting script on your website. The script collects device and browser data that the credit report provider uses for risk assessment and identity verification.

Why is this required? The OTP authentication challenge relies on device fingerprinting data. Without the script loaded on the consumer's browser, the provider cannot verify the device and the OTP challenge will always fail.

1. Add the script tag

Include the following script on any page where the consumer will submit their details for a credit report. Place it as early as possible (e.g. in <head>) so the SDK has time to collect device data before the form is submitted.

<script src="https://api-next.checkio.co.uk/v1/fingerprints/device"></script>

The script automatically initialises and begins collecting device data. No additional configuration is required.

2. Capture the Session ID

When the script is ready, it calls a callback on window.checkio.deviceFingerprint with the generated Session ID. Register this callback before the script loads:

<script>
  window.checkio = window.checkio || {};
  window.checkio.deviceFingerprint = function (data) {
    // Store the session ID for use in your credit report request
    console.log('Session ID:', data.sessionId);
  };
</script>
<script src="https://api-next.checkio.co.uk/v1/fingerprints/device"></script>

3. Send the Session ID

Pass the Session ID as the sessionId field in your POST /credit-reports request. This links the device fingerprint data to the credit report request at the provider.

Tip: Load the script as early as possible on the page. This gives it time to collect device data before the consumer submits their details.
Step 1: Generate a Credit Report

Submit the consumer's details to begin the credit report process. Replace {tenantId} with your tenant ID.

curl -X POST 'https://api-next.checkio.co.uk/{tenantId}/v1/credit-reports' \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "sessionId": "sdk-generated-session-id",
  "bureaus": ["equifax"],
  "ipAddress": "192.168.1.1",
  "searchType": "pcp",
  "title": "Mr",
  "firstName": "John",
  "lastName": "Doe",
  "dateOfBirth": "1990-05-15",
  "gender": "M",
  "mobileNumber": "+447911123456",
  "email": "john.doe@example.com",
  "externalReference": "your-internal-ref",
  "addresses": [
    {
      "type": "current",
      "ukAddress": {
        "buildingNumber": "42",
        "buildingName": "Rose Court",
        "subBuildingName": "Flat 3",
        "thoroughfare": "High Street",
        "district": "Westminster",
        "townOrCity": "London",
        "county": "Greater London",
        "country": "GB",
        "postcode": "SW1A 1AA"
      }
    }
  ]
}'

Required Fields

FieldTypeDescription
sessionIdstringThe Session ID generated by the device fingerprinting SDK on the consumer's browser. This links the device data to the credit report request. See Prerequisite: Device Fingerprinting above.
bureausstring[]Credit bureaus to query: "equifax", "transunion", "experian"
ipAddressstringThe consumer's IP address
searchTypestringSearch type (currently "pcp")
firstNamestringConsumer's first name
lastNamestringConsumer's last name
dateOfBirthstringDate of birth in YYYY-MM-DD format
addressesobject[]At least one address (see Address Fields below)

Optional Fields

FieldDescription
titlee.g. "Mr", "Mrs", "Ms"
middleNameConsumer's middle name
gender"M" or "F"
mobileNumberRequired if OTP challenges are expected
emailConsumer's email address
externalReferenceYour internal reference for correlation

Address Fields

Each entry in the addresses array has a type (e.g. "current") and a ukAddress object with the following fields:

FieldRequiredDescription
subBuildingName*Sub-unit within a building, e.g. "Flat 3", "Unit B"
buildingName*Name of the building, e.g. "Rose Court"
buildingNumber*House or building number, e.g. "42"
thoroughfareNoStreet name, e.g. "High Street"
districtNoDistrict or locality, e.g. "Westminster"
townOrCityYesTown or city name, e.g. "London"
countyNoCounty, e.g. "Greater London"
countryNoCountry code, e.g. "GB"
postcodeYesUK postcode, e.g. "SW1A 1AA"

* At least one of subBuildingName, buildingName, or buildingNumber must be provided to identify the property.

Response: Direct Success
No Challenge

When the provider does not require identity verification, the credit report data is returned immediately.

{
  "meta": {
    "request": { "timeTakenMs": 2845 },
    "wallet": { "balance": 9500, "cost": 500 }
  },
  "data": {
    "status": "complete",
    "challengeType": "none",
    "creditReportId": "019abc12-3456-7890-abcd-ef1234567890",
    "creditReport": {
      "person": {
        "title": "Mr",
        "firstName": "John",
        "lastName": "Doe",
        "dateOfBirth": "1990-05-15"
      },
      "residencies": [
        {
          "addressId": "addr-1",
          "address": {
            "type": "uk",
            "ukAddress": {
              "subBuildingName": "Flat 3",
              "buildingName": "Rose Court",
              "buildingNumber": "42",
              "thoroughfare": "High Street",
              "district": "Westminster",
              "townOrCity": "London",
              "county": "Greater London",
              "country": "GB",
              "postcode": "SW1A 1AA"
            },
            "addressLine1": "Flat 3, Rose Court, 42 High Street",
            "lines": ["Flat 3, Rose Court", "42 High Street", "Westminster", "London", "Greater London", "SW1A 1AA"]
          },
          "yearsAtAddress": 3,
          "monthsAtAddress": 6,
          "isCurrent": true
        }
      ],
      "consumerData": {
        "records": [
          {
            "title": "Mr",
            "firstName": "John",
            "lastName": "Doe",
            "accountNumber": "****1234",
            "accountType": "Credit Card",
            "accountStatus": "Open",
            "companyType": "Bank",
            "companyName": "Example Bank plc",
            "numberOfPayments": 24,
            "repaymentPeriod": 24,
            "payment": { "amount": 50000, "currency": "GBP" },
            "startBalance": { "amount": 500000, "currency": "GBP" },
            "balance": { "amount": 250000, "currency": "GBP" },
            "startDate": "2022-01-15",
            "bureaus": [
              { "id": "equifax", "ref": "EQF-REF-123456" }
            ]
          }
        ]
      },
      "previousSearches": {
        "providers": [
          {
            "companyName": "Example Bank plc",
            "records": [
              { "date": "2024-06-01T14:30:00Z" }
            ]
          }
        ]
      }
    }
  }
}
Money values are in the smallest currency unit. For GBP, amounts are in pence. For example, 50000 means £500.00.
Response: Authentication Required
OTP Challenge

When the provider requires identity verification, an OTP code is sent via SMS to the mobile number provided. The response includes a challengeId that you'll need for the next step.

{
  "meta": {
    "request": { "timeTakenMs": 1234 },
    "wallet": { "balance": 9500, "cost": 500 }
  },
  "data": {
    "status": "authentication-required",
    "challengeType": "otp",
    "creditReportId": "019abc12-3456-7890-abcd-ef1234567890",
    "challenge": {
      "challengeId": "019def34-5678-9012-cdef-ab3456789012"
    }
  }
}

Important: Save both the creditReportId and challengeId from this response. You will need both to submit the OTP. The challenge expires after 5 minutes.

SMS billing: Each SMS sent (initial OTP and any resends) is billed separately as an SMS line item. SMS charges are captured immediately upon successful delivery, regardless of whether the credit report completes.

Response: Blocked
Cannot Proceed

The provider may block a request based on risk assessment. This is a terminal state and the report cannot proceed.

{
  "meta": {
    "request": { "timeTakenMs": 890 },
    "wallet": { "balance": 10000, "cost": 0 }
  },
  "data": {
    "status": "blocked",
    "creditReportId": "019abc12-3456-7890-abcd-ef1234567890"
  }
}
Step 2: Submit the OTP Code

Once the consumer receives the SMS and provides the OTP code, submit it using the creditReportId and challengeId from the previous response.

curl -X POST 'https://api-next.checkio.co.uk/{tenantId}/v1/credit-reports/{creditReportId}/otp-challenge' \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "challengeId": "019def34-5678-9012-cdef-ab3456789012",
  "code": "123456"
}'

Success Response

On successful verification, the credit report data is returned:

{
  "meta": {
    "request": { "timeTakenMs": 3567 },
    "wallet": { "balance": 9500, "cost": 0 }
  },
  "data": {
    "status": "complete",
    "creditReportId": "019abc12-3456-7890-abcd-ef1234567890",
    "creditReport": {
      "person": { ... },
      "residencies": [ ... ],
      "consumerData": { "records": [ ... ] },
      "previousSearches": { "providers": [ ... ] }
    }
  }
}

Retry Response (Invalid Code)

If the code is incorrect, you can retry. The consumer has a maximum of 3 attempts:

{
  "meta": {
    "request": { "timeTakenMs": 234 },
    "wallet": { "balance": 9500, "cost": 0 }
  },
  "data": {
    "status": "retry",
    "errorMessage": "Invalid OTP code",
    "creditReportId": "019abc12-3456-7890-abcd-ef1234567890",
    "attemptsRemaining": 2
  }
}

Failed Response (Max Attempts)

After 3 failed attempts, the challenge is permanently failed:

{
  "meta": {
    "request": { "timeTakenMs": 145 },
    "wallet": { "balance": 10000, "cost": 0 }
  },
  "data": {
    "status": "failed",
    "errorMessage": "Maximum OTP attempts exhausted",
    "creditReportId": "019abc12-3456-7890-abcd-ef1234567890"
  }
}
Resending the OTP SMS

If the consumer did not receive the SMS, you can request a resend. The OTP can be sent a maximum of 3 times per challenge (1 initial + 2 resends). Each resend resets the 5-minute expiry timer.

curl -X POST 'https://api-next.checkio.co.uk/{tenantId}/v1/credit-reports/{creditReportId}/resend-sms' \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "challengeId": "019def34-5678-9012-cdef-ab3456789012"
}'

Response

{
  "meta": {
    "request": { "timeTakenMs": 1200 }
  },
  "data": {
    "remainingSmsCount": 1,
    "smsSentCount": 2
  }
}
Billing: Each SMS sent (including the initial OTP and any resends) is billed separately from the credit report itself. SMS costs are charged immediately upon successful delivery. Check your tenant pricing configuration for the per-SMS rate.
Test Mode

Use test mode during development to simulate the full flow without hitting real credit bureaus or charging credits. Set test: true in the request body and use challengeOptions to control the behaviour.

Test with OTP Challenge

Simulates the OTP flow. No real SMS is sent and no SMS credits are charged. Use code 123456 to verify. You can also test the resend SMS endpoint — it simulates the resend (including the max 3 sends limit) without sending a real SMS.

{
  "sessionId": "test-session-1",
  "bureaus": ["equifax"],
  "ipAddress": "127.0.0.1",
  "searchType": "pcp",
  "firstName": "Test",
  "lastName": "User",
  "dateOfBirth": "1990-01-01",
  "mobileNumber": "+447000000000",
  "addresses": [
    {
      "type": "current",
      "ukAddress": {
        "buildingNumber": "1",
        "thoroughfare": "Test Street",
        "townOrCity": "London",
        "postcode": "SW1A 1AA"
      }
    }
  ],
  "test": true,
  "challengeOptions": {
    "status": "challenge"
  }
}

Challenge Options

statusBehaviour
"challenge"Returns authentication-required. Submit OTP code 123456 to complete.
"allow"Completes immediately with synthetic report data. No challenge step required.
"block"Returns blocked status. Simulates a provider risk rejection.
Test mode requests do not deduct credits from your wallet. This includes both the credit report cost and any SMS delivery costs.
Test Email Scenarios
Test Mode

In test mode, the email field controls which synthetic data scenario is returned. Use a specific email prefix (the part before @) to select a scenario. Matching is case-insensitive and the domain part is ignored.

Email prefixScenarioRecords returned
test001No records found0 consumer records, 0 previous searches
test002Single PCP record1 active hire-purchase record
test003Multiple mixed records3 records: 1 PCP (hire-purchase), 1 credit card, 1 mortgage
test004All settled/closed2 settled accounts (PCP + credit card) with zero balance
anything elseDefault4 records: 2 PCP, 1 credit card, 1 mortgage

Example: Empty Report

Use test001@example.com to simulate a consumer with no credit history on file:

{
  "sessionId": "test-session-1",
  "bureaus": ["equifax"],
  "ipAddress": "127.0.0.1",
  "searchType": "pcp",
  "firstName": "Test",
  "lastName": "User",
  "dateOfBirth": "1990-01-01",
  "email": "test001@example.com",
  "addresses": [
    {
      "type": "current",
      "ukAddress": {
        "buildingNumber": "1",
        "thoroughfare": "Test Street",
        "townOrCity": "London",
        "postcode": "SW1A 1AA"
      }
    }
  ],
  "test": true,
  "challengeOptions": {
    "status": "allow"
  }
}
Tip: Combine email scenarios with challengeOptions to test different data sets through both the direct and OTP challenge flows.
Error Responses

The following errors may occur during the credit report flow. All errors follow the standard error envelope format.

HTTPCodeWhen
400validation-errorMissing or invalid fields in the request body
402insufficient-fundsWallet balance is too low for this operation
404credit-report-not-foundThe credit report ID does not exist
404challenge-not-foundThe challenge ID does not exist or does not belong to this report
410challenge-expiredThe OTP challenge has exceeded the 5-minute window
429rate-limitedToo many requests

Example Error Response

{
  "code": "insufficient-funds",
  "message": "Your wallet balance is insufficient for this operation"
}
Integration Tips
  • Always provide a mobile number if using bureaus that may require OTP verification. Without it, the challenge cannot be delivered.
  • Handle all three initial statuses (complete, authentication-required, blocked) in your integration logic.
  • Use externalReference to correlate credit reports with records in your own system.
  • Monitor meta.wallet.balance in responses to track your credit usage and avoid 402 errors.
  • Implement timeout handling for OTP challenges. After 5 minutes the challenge expires and a new generate request is needed.
  • Test all paths using test mode before going live. Use challengeOptions.status to exercise each branch.