Tenant screening API

The Great Renter API documentation

Everything you need to order tenant screening checks from your own software: authentication, the six order endpoints, the applicant object, order statuses and results, identity verification reviews, webhooks, errors and rate limits. Written from the public OpenAPI schema, with working examples in curl, Node and Python.

Base URL
https://api.thegreatrenter.com/api/v1
Auth
X-Api-Key header
Format
JSON over HTTPS
Spec
OpenAPI 3.0.3
On this page

Start here

Quickstart

Three requests take you from a new key to a finished credit report. Set your key as an environment variable first so it never ends up in your code: export TGR_API_KEY=sk_live_.... For each new order, generate a unique retry key too: export TGR_IDEMPOTENCY_KEY=....

1. See what you can order

GET /products/ lists every product your company can order, with the price that applies to you. Each product value is also the path you order it from.

curl https://api.thegreatrenter.com/api/v1/products/ \
  -H "X-Api-Key: $TGR_API_KEY"
Response · 200
{
  "data": [
    {
      "product": "identity_verification",
      "name": "Identity Verification (OneID)",
      "kind": "check",
      "price": "<your price>",
      "currency": "CAD"
    }
  ]
}

2. Order a check

Send the applicant to the product's endpoint. This example orders an Equifax credit report. The response comes back straight away with a reference; the report itself follows when the bureau responds.

curl -X POST https://api.thegreatrenter.com/api/v1/credit_check/ \
  -H "X-Api-Key: $TGR_API_KEY" \
  -H "Idempotency-Key: $TGR_IDEMPOTENCY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane.doe@example.com",
    "first_name": "Jane",
    "middle_name": "Q",
    "last_name": "Doe",
    "date_of_birth": "1990-05-01",
    "sex": "F",
    "birth_place": { "country": "CA", "city": "Toronto", "province": "ON" },
    "residences": [
      {
        "street_address": "1 King St W",
        "unit": "1200",
        "city": "Toronto",
        "province": "ON",
        "country": "CA",
        "postal_code": "M5H1A1",
        "start_date": "2022-06-01"
      }
    ]
  }'
Response · 201 (or 200 when replayed)
{
  "reference": "TGR_CA_1A2B3C4D5",
  "product": "credit_check",
  "status": "in_progress",
  "message": null,
  "payment_status": "paid",
  "amount": "<your price>",
  "currency": "CAD",
  "applicant": { "name": "Jane Q Doe", "email": "jane.doe@example.com" },
  "report": null,
  "created_at": "2026-07-03T12:00:00Z",
  "completed_at": null
}

3. Fetch the result

Poll the order by its reference until status is completed, or skip polling entirely and subscribe a webhook. For a credit report, the normalized result is in credit.

curl https://api.thegreatrenter.com/api/v1/credit_check/TGR_CA_1A2B3C4D5/ \
  -H "X-Api-Key: $TGR_API_KEY"

Authentication

Every product endpoint takes an API key in the X-Api-Key header. Keys belong to your company and look like sk_live_xxxx or sk_test_xxxx. API keys and webhook endpoints are managed from your company dashboard on app.thegreatrenter.com; if you don't have an account yet, start here.

  • Scopes. Placing an order needs a key with WRITE or READ_WRITE scope. Read endpoints accept a key of any scope, so give reporting jobs a read-only key.
  • IP allowlist. If your company has an allowlist configured, requests from any other address are refused.
  • Failures. A missing, invalid, or inactive key returns 401. The wrong scope or an IP that is not allowlisted returns 403.

Keep keys on the server

A key can spend money. Never ship one in a browser or mobile app; call the API from your backend and pass results to the client.

Endpoints

All paths are relative to https://api.thegreatrenter.com/api/v1. Each product has the same three routes: order, list, and get one. Order bodies can be sent as JSON, form data, or URL-encoded. Every order route also accepts an optional Idempotency-Key header for safe retries.

API endpoints
MethodPathWhat it does
GET/products/Products you can order, with your price and currency.
POST/credit_check/Order Credit Report.
GET/credit_check/List your Credit Report orders, newest first.
GET/credit_check/{reference}/One Credit Report order and its result.
POST/identity_verification/Order Identity Verification.
GET/identity_verification/List your Identity Verification orders, newest first.
GET/identity_verification/{reference}/One Identity Verification order and its result.
POST/global_watchlist/Order Global Watchlist.
GET/global_watchlist/List your Global Watchlist orders, newest first.
GET/global_watchlist/{reference}/One Global Watchlist order and its result.
POST/adverse_media/Order Adverse Media.
GET/adverse_media/List your Adverse Media orders, newest first.
GET/adverse_media/{reference}/One Adverse Media order and its result.
POST/basic_screening/Order Basic Screening.
GET/basic_screening/List your Basic Screening orders, newest first.
GET/basic_screening/{reference}/One Basic Screening order and its result.
POST/enhanced_screening/Order Enhanced Screening.
GET/enhanced_screening/List your Enhanced Screening orders, newest first.
GET/enhanced_screening/{reference}/One Enhanced Screening order and its result.
POST/identity_verification/{reference}/review/Approve, decline, or ask for a resubmission on a verification in review.

Packages. basic_screening runs the Standard bundle and enhanced_screening the Complete bundle in a single order. Their identity step uses a document check on ID images you supply, not the hosted selfie flow of the standalone identity verification.

The applicant

Order endpoints share the applicant fields below. Dates are YYYY-MM-DD. Five fields are always required: email, first_name, middle_name, last_name, and date_of_birth. Send an empty string for middle_name when the applicant has none; the applicant must be 18 to 120 years old. Residences are also required except for standalone identity verification using oneId_1. The example in the quickstart shows a complete body.

Applicant fields
FieldTypeDescription
first_namerequiredstringLegal first name.
middle_namerequiredstringMiddle name or initial; send an empty string when there is none.
last_namerequiredstringLegal last name.
emailrequiredstringThe applicant's email address.
date_of_birthrequireddateThe applicant's date of birth; they must be 18 to 120 years old.
residencesarrayRequired for every product except standalone identity verification on oneId_1. See the residence fields below.
phone_numberstringThe applicant's phone number.
sexstringFor example F.
birth_placeobjectcountry, province and city.
identificationobjectPackages only. ID image URLs to verify at order time; see below.

Residences

Residence fields
FieldTypeDescription
street_addressrequiredstringStreet number and name.
unitstringUnit or apartment number.
cityrequiredstringCity.
provincerequiredstringFor example ON.
countryrequiredstringFor example CA.
postal_coderequiredstringFor example M5H1A1.
start_daterequireddateWhen the applicant moved in.

Residence rules

A start_date can never be in the future and no two residences may have the same start date. Where residences are required, the history as a whole must cover at least six months: the oldest start_date must be more than six months ago, but the current residence may be recent. The latest start date identifies the current address; each earlier residence ends when the next one starts. A body that breaks these rules returns 400. The one exception is identity verification on oneId_1, which can omit residences.

Identification (packages)

Add an identification object to a basic_screening or enhanced_screening order to include a document check: a front_url (required), an optional back_url, and an optional document_type. The images are verified when you order, and an IDENTITY_VERIFICATION check is added to the report. If the images can't be read, the order stops at action_required with a message saying what to fix; order again with a clearer image.

Orders and results

Creating and fetching return an order object; list endpoints wrap those objects in a paginated response. Standalone identity verification adds one_id_url, link_expires_at, and identity_verification. Save the reference: it's how you fetch the result and how webhooks identify the order.

Order fields
FieldTypeDescription
referencestringThe order's ID, for example TGR_CA_1A2B3C4D5.
productstringWhich product was ordered, for example credit_check.
statusstringWhere the order is; see the statuses below.
messagestring | nullA plain-language explanation when the order needs attention or could not be completed.
payment_statusstringpending, invoiced, paid, or failed.
amount, currencystringWhat the order cost, and in which currency.
applicantobjectThe applicant's name and email.
reportarray | nullCheck-level results, one entry per case: id, created, overall_status, overall_score, and a checks array of type, status, score, sub_score and output_claims.
creditobject | nullCredit orders and packages: the normalized credit result, described below. Null until the bureau returns the report.
created_at, completed_atdate-timeWhen the order was placed and when it finished.

Statuses

Product orders use pending while payment is being taken, action_required while being submitted or waiting for corrected input, and in_progress while the provider is working. They finish as completed or failed. Only completed carries a final result; read message whenever attention is required. The invited, opened, started, and payment_required values belong to the dashboard flow and are not used for product orders. Treat an unrecognised future value as still processing.

The credit object

The bureau is picked from the applicant's most recent address, and credit has the same shape wherever they live. Scales differ by region, so read score_range instead of assuming 300 to 900. When the bureau returns an itemised file, credit.detail holds it in sections; each section lists its own columns, so read those rather than hard-coding field names, and treat an empty rows array as nothing reported.

credit (example)
"credit": {
  "bureau": "equifax_us",
  "country": "US",
  "status": "COMPLETE",
  "score": 710,
  "score_range": { "min": 300, "max": 850 },
  "band": "GOOD",
  "date_created": "2026-07-03T12:19:00Z",
  "claims": { "credit_score": 710, "has_bankruptcies": false }
}

Safe retries

Give every new order a unique Idempotency-Key of at most 255 characters, such as a UUID. Retrying the same body with the same key creates no duplicate and returns the original order with 200 and Idempotent-Replayed: true. Reusing the key with a different body returns 409. Keys are scoped to your company and do not expire, so use a new value for each intended order. Without this header, every retry places a new order.

Billing

Every order is priced for your company. On PAY_PER_CHECK billing the card is charged when you order and refunded automatically if the provider rejects the order, so you only pay for orders that succeed; a declined card returns 402. On INVOICE_MONTHLY the order is added to your monthly invoice.

Identity verification

A standalone identity verification works differently from the other checks, because the applicant has to take part: they upload a government ID and complete a selfie and liveness check on a page the provider hosts.

  1. POST /identity_verification/ returns a one_id_url, valid for 14 days (link_expires_at).
  2. You send that link to the applicant. The Great Renter does not email them, and the order stays in_progress until they finish.
  3. When they do, identity_verification on the order holds the outcome in the same shape for every provider: status (verified, in_review, failed or pending), result, is_identity_verified, the extracted name, date of birth and document details, and any warnings.

To pick the provider for one order, send the optional X-IDV-Provider header as oneId_1 or oneId_2. Without it, your company's configured provider is used. oneId_2 matches against address history, so it needs residences; oneId_1 does not.

Status-only identity results

Companies can ask support to enable status-only results. In that mode, identity_verification returns only the provider, status, result, verification flag, warnings, review or failure reason, and resubmission_options. Applicant names, dates of birth, document details, and images are omitted from API responses and webhooks.

Reviewing a result

When a verification comes back in_review, record a decision with POST /identity_verification/{reference}/review/. Every request needs a decision and an actor, your identifier for the person deciding, such as their email.

Review decisions
FieldTypeDescription
approvedecisionCloses the order as completed; the status becomes verified.
declinedecisionCloses the order as completed; the status becomes failed.
resubmitdecisionReopens the order as in_progress with status pending. Send the applicant the returned one_id_url.
correctionsobjectOptional on any decision, to fix a misread document field: given_name, family_name, date_of_birth, document_type (P, ID, DL, RP or SSC) and document_number. The applicant record itself is never changed.
resubmit_nodesarrayOptional only with resubmit. Pass retry targets from the result's resubmission_options, or omit it to retry all eligible steps automatically.
POST /api/v1/identity_verification/TGR_CA_1A2B3C4D5/review/
X-Api-Key: <your write-capable API key>
Content-Type: application/json

{
  "decision": "approve",
  "actor": "admin@example.com",
  "comment": "Identity confirmed."
}

A decision can only be made once. 200 returns the updated order; store it. 409 means the order is no longer in review, so fetch it again. Every successful decision is logged with the actor, the API key, the time, and the result before and after.

Webhooks

Register an endpoint URL, subscribe it to events, and The Great Renter POSTs a signed payload to it when a matching order finishes. Endpoints are managed from your company dashboard by the account owner or an admin; the signing secret is shown once, when the endpoint is created, so store it straight away.

Webhook events
EventFires when
credit_check.completedA Credit Report order finishes.
identity_verification.completedA Identity Verification order finishes.
global_watchlist.completedA Global Watchlist order finishes.
adverse_media.completedA Adverse Media order finishes.
basic_screening.completedA Basic Screening package finishes.
enhanced_screening.completedA Enhanced Screening package finishes.

Delivery

  • An HTTP POST with Content-Type: application/json and an X-Signature header, to every active endpoint subscribed to the event.
  • Respond with any 2xx within 10 seconds. Acknowledge first and do the heavy work asynchronously.
  • A non-2xx, a timeout, or a connection error marks the attempt failed.
  • The endpoint URL must be publicly reachable; private, loopback and internal addresses are rejected.

Each event is delivered once

There is no automatic retry. Make your handler idempotent (the same reference can safely be processed twice) and, if your receiver was down, reconcile by fetching the order from the API.

Verifying the signature

X-Signature is a hex-encoded HMAC-SHA256 of the raw request body, keyed by your endpoint secret. Recompute it over the exact bytes you received, before any JSON parsing, and compare in constant time.

import crypto from "node:crypto";
import express from "express";

const app = express();

// Keep the raw bytes: the signature is computed over the body exactly as sent.
app.post("/webhooks/tgr", express.raw({ type: "application/json" }), (req, res) => {
  const expected = crypto
    .createHmac("sha256", process.env.TGR_WEBHOOK_SECRET)
    .update(req.body)
    .digest("hex");
  const received = req.get("X-Signature") ?? "";

  const valid =
    received.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received));
  if (!valid) return res.sendStatus(401);

  const event = JSON.parse(req.body.toString("utf8"));
  queue.add(event); // process later; answer within 10 seconds
  res.sendStatus(200);
});

Payload

A <product>.completed event carries the order's reference, status, completed_at and report, plus credit for credit results. For identity_verification.completed, an identity_verification object takes the place of credit.

credit_check.completed
{
  "event": "credit_check.completed",
  "reference": "TGR_CA_1A2B3C4D5",
  "status": "completed",
  "completed_at": "2026-07-03T12:20:00Z",
  "report": [
    { "id": "case-abc", "overall_status": "COMPLETE", "checks": ["..."] }
  ],
  "credit": {
    "bureau": "equifax_us",
    "country": "US",
    "status": "COMPLETE",
    "score": 710,
    "score_range": { "min": 300, "max": 850 },
    "band": "GOOD",
    "date_created": "2026-07-03T12:19:00Z",
    "claims": { "credit_score": 710, "has_bankruptcies": false }
  }
}

Errors, limits and pagination

HTTP status codes
StatusMeaning
400Validation error: missing or invalid applicant data, residence history, review data, or idempotency key.
401API key is missing, invalid, or inactive.
402Payment failed, for example a declined card or no payment method on file.
403API key lacks the required scope, or the request IP is not allowlisted.
404No such order for your company, or a requested list page is past the final page.
409An idempotency key was reused with a different body, or a verification is no longer available for review.
429Rate limit exceeded. For API-key limits, wait the number of seconds in Retry-After; review-provider throttling may require fetching the order before retrying.
502Identity review only: the verification service could not confirm the decision. Fetch the order before retrying.

Rate limits

Limits apply per API key and are counted across every product endpoint: 2,000 reads an hour and 120 orders an hour. Exceeding either returns 429 with a Retry-After header giving the seconds to wait before retrying.

Pagination

List endpoints return orders newest first, a page at a time, as count, totalPages, currentPage, and data. Pass page and limit to page through; the default limit is 10 and the maximum is 100. A page past the end returns 404. Use search for a partial, case-insensitive match on reference, applicant name, or email; reference and email for exact case-insensitive matches; and status for one or more comma-separated statuses. Filters combine with AND. ordering selects the result order.

Ready to build?

Keys are issued to company accounts. Email us with what you're building, read how pricing and access work, or try requests in the interactive Swagger reference.