{"openapi":"3.1.0","info":{"title":"Carousel API","version":"1.0.0","description":"Carousel onboards any applicant — a tenant, a borrower, a new hire — through one link they complete on their phone: it verifies their identity, pulls their credit, connects their bank for income and cash flow, and checks court and police records. This API lets your own system — a CRM, a leasing or lending tool, an AI agent — send a screening, follow it, and show its report.\n\n## How it works\n1. Your system sends a screening — the checks to run and the applicant’s email — with `POST /api/v1/screenings`.\n2. Carousel emails the applicant their link (`applicantLink`), or hands it to you to deliver (`\"delivery\": \"none\"`).\n3. The applicant completes the checks on Carousel’s own pages — ID and selfie, credit, court, police, bank, a short self-declaration — and pays at checkout when `payer` is `renter`.\n4. Each provider’s result lands in Carousel’s report as it finishes; events (or your webhook) tell you as it happens.\n5. Your team opens the report at `portalUrl`. With a results key, your system can read it from `/results`.\n\n**Carousel never approves or rejects an applicant** — the decision is yours.\n\n## The words\n- **Account and key** — sign up at app.oncarousel.com with Google, then make a key: account menu → **Developers** → **Keys**. A key acts for its account and sees every screening filed there, whoever sent it.\n- **Workspace → building → unit** — where a screening is filed. With none, it goes to **Private** (your account’s screenings with no workspace); then send `\"region\"`.\n- **Region** — `CA` or `US`: the checks, prices, currency and token balance.\n- **Checks and combinations** — a screening runs exactly one combination of checks; `GET /api/v1/checks?region=CA` lists them. Canada has two court systems: Québec’s `court_qc` + `penal_qc`, or the rest of Canada’s `court_roc`. A building in Québec takes Québec’s.\n- **Payer** — `tokens`: you pay from your balance, per check as it completes. `renter`: the applicant pays at checkout, and you pay nothing.\n- **`portalUrl` vs `applicantLink`** — `portalUrl` is for your team (people signed in to Carousel with access to the screening’s account or workspace). `applicantLink` is for the applicant only. Never swap them.\n\n## Money\n12 tokens = $1 (CAD in Canada, USD in the US), with one balance per region. Each check has a token price — `GET /checks` has the live ones — and you’re charged as each check completes. `tokenCost` is the most a screening can cost; a send the balance can’t cover is refused (`402`).\n\n## Test mode\nMake a **test key** (`cp_test_…`: account menu → **Developers** → **Keys** → Test key) and build against it. Same address, same requests, same answers — but a send reaches nobody, costs nothing and never runs a real check. With a live key every send is real, **including from this page’s request console**.\n- **A simulated applicant** completes each test screening: invited, started after 30 seconds, one check every 15 seconds, completed. `POST /screenings/{id}/advance` does the rest at once.\n- **Choose what happens** with the applicant email’s +tag: `tenant+record@example.com` finds a court record, `+stopped` stops the first check, `+expire` never starts (expires after two minutes), `+bounce` bounces the invitation. No tag: everything clear.\n- **Events** go to the test stream: `GET /events` with the test key. **`POST /webhook/test`** sends a signed sample event to your webhook now, with its answer.\n- **Results** are Carousel’s fictional sample applicant, cut to the checks you sent; `portalUrl` opens the sample report.\n- Every answer carries `\"livemode\"`; test data never mixes with real screenings, billing or your team’s lists. Workspaces and buildings are your real ones — a test key can read and add them like a live key.\n\nThe API can’t cancel or remind yet — do both in Carousel, from the application’s row.\n\n## Use it from an AI assistant (MCP)\nClaude, ChatGPT, Cursor or any MCP client can use Carousel through its MCP server at `https://mcp.oncarousel.com`. In claude.ai and ChatGPT, add it as a custom connector and **sign in with Carousel** (OAuth); elsewhere, send a key (`Authorization: Bearer <key>`). Its tools are this API — list what you can send, file and send screenings, follow them, read results with a results key — with the same limits and refusals. In Claude Code: `claude mcp add --transport http carousel https://mcp.oncarousel.com --header \"Authorization: Bearer $CAROUSEL_API_KEY\"`.\n\n## Quickstart\n1. **Create a key.** In Carousel: account menu → **Developers** → **Keys**. It’s shown once — keep it on your server.\n2. **Check it.** `GET /api/v1/me` with `Authorization: Bearer <key>`.\n3. **See what you can send.** `GET /api/v1/checks?region=CA`.\n4. **Send a screening.** `POST /api/v1/screenings` with an `Idempotency-Key` and a body like `{\"checks\": [\"id\", \"credit\", \"court_roc\"], \"applicant\": {\"email\": \"tenant@example.com\"}, \"building\": \"<id>\"}` (or `\"region\": \"CA\"` instead of a building). Show the answer’s `portalUrl` in your CRM.\n5. **Follow it.** `GET /api/v1/events?after=0`, or have every event POSTed to your webhook.\n\n## Authentication\nEvery request carries `Authorization: Bearer cp_live_…`. A key acts for its account: it can send screenings, which spend tokens. Make one per system that uses it, and revoke it in the same place when that system goes away.\n\n## Retrying safely\nA `503 busy` means Carousel is briefly at capacity: wait the seconds in `Retry-After` and send the same request again.\n\nSend `Idempotency-Key` with every `POST /screenings` — any string up to 255 characters, unique per send; keys are per API key. The same key and the byte-identical body again returns the first answer (header `Idempotent-Replayed: true`) and sends nothing; the same key with a different body — even reformatted JSON — is `409 idempotency_conflict`. A refusal about the moment — out of tokens, rate limited, a service didn’t answer — keeps nothing, so the same request can go through later with the same key. Any other refusal is kept for that key: after fixing a 400, 404 or 422, send with a new key.\n\n## Webhooks\nSet one HTTPS address in Carousel (account menu → **Developers** → **Webhook**). Each event is POSTed as JSON with `Carousel-Event`, `Carousel-Delivery` and `Carousel-Signature: t=<unix seconds>,v1=<hex>` — an HMAC-SHA256, keyed with your signing secret, of `t`, a dot and the raw body. Answer any 2xx within 10 seconds; otherwise we retry after at least 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours, then stop — every event stays readable from `GET /api/v1/events`. Delivery is at least once and not in order: dedupe on `Carousel-Delivery`, order by the event’s `seq`. Requests carry `User-Agent: Carousel-Webhooks/1`. **Saving the address again creates a new signing secret**, shown once.\n\n```js\nimport crypto from 'node:crypto';\n\n// rawBody: the request body exactly as received, before any JSON parsing\nfunction isFromCarousel(rawBody, header, secret) {\n  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));\n  const expected = crypto.createHmac('sha256', secret)\n    .update(`${parts.t}.${rawBody}`).digest('hex');\n  return expected.length === parts.v1.length &&\n    crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));\n}\n```\n\n## Errors\nEvery error is `{\"error\": {\"code\", \"message\", \"hint\"}}`. Branch on `code`; `hint` is the next thing to do.\n\n| HTTP | Code | What to do |\n|---|---|---|\n| 400 | `invalid_request` | Fix the field named in the message; GET /api/v1/openapi.json describes every body. |\n| 400 | `invalid_email` | Send the applicant’s email address in applicant.email — phone numbers are not accepted. |\n| 401 | `unauthorized` | Send the header \"Authorization: Bearer <key>\". Keys are made in Carousel (app.oncarousel.com): account menu → Developers → Keys. |\n| 402 | `insufficient_tokens` | Your balance can’t cover this screening’s tokenCost. Top up tokens in Carousel, then retry the same request (the same Idempotency-Key works) — or send with \"payer\": \"renter\" so the applicant pays. |\n| 403 | `results_not_allowed` | This key can’t read applicant results. Create a key with “Read applicant results” ticked: account menu → Developers → Keys. |\n| 404 | `not_found` | Use an id this key’s account owns: GET /api/v1/workspaces, /api/v1/buildings or /api/v1/screenings list them. |\n| 409 | `idempotency_conflict` | This Idempotency-Key was already used with a different body — use a new key for a new send. |\n| 409 | `request_in_progress` | The first request with this Idempotency-Key is still running — retry the same request in a few seconds. |\n| 409 | `region_mismatch` | Send to a workspace or building in the same region, or change \"region\" to match the property. |\n| 422 | `unknown_combination` | Send exactly the checks of one combination, in any order: GET /api/v1/checks?region=CA lists them. |\n| 422 | `court_area_mismatch` | This building is in Québec, which runs Québec’s court checks: send court_qc and penal_qc instead of court_roc. |\n| 422 | `combination_unavailable` | GET /api/v1/checks?region=CA says whether each combination can be sent right now (\"sendable\") for your payer — pick one that can, or retry later. |\n| 422 | `workflow_unavailable` | List this account’s custom workflows with GET /api/v1/checks and use one offered where you are sending. |\n| 400 | `test_mode_only` | This works with a test key only (cp_test_…). Make one in Carousel: account menu → Developers → Keys → Test key. |\n| 503 | `test_mode_not_ready` | Test mode isn’t switched on for Carousel yet — use a live key meanwhile, or try again later. |\n| 409 | `results_changed` | The data changed between pages — start again with after=0. |\n| 413 | `document_too_large` | Download it in ranges: send \"Range: bytes=0-4194303\", then the next 4 MB, until Content-Range shows the whole file (byteSize in the results). |\n| 429 | `rate_limited` | Wait the number of seconds in the Retry-After header, then retry. |\n| 503 | `busy` | Carousel is briefly at capacity. Retry after the seconds in the Retry-After header; with the same Idempotency-Key a send is never made twice. |\n| 502 | `carousel_error` | A screening service behind Carousel didn’t answer. Nothing was sent or charged — retry the same request (with the same Idempotency-Key) in a minute. |\n| 500 | `internal_error` | Retry later; if it keeps happening, contact Carousel support with the time of the request. |\n\n## Limits\n120 requests a minute per key; 30 screenings sent a minute per account (replays and refusals count); 30 results reads a minute per key; 10 live keys per account. Over a limit the answer is `429` with a `Retry-After` header, in seconds.\n\n## Applicant results\n`GET /api/v1/screenings/{id}/results` returns each check’s results and the stored documents — for a key made with **Read applicant results** ticked (account menu → **Developers** → **Keys**); any other key gets `403 results_not_allowed`. Fetch them after `screening.step_completed` or `screening.completed`; bank transactions page through `…/transactions`, and files over 4 MB download in ranges. 30 reads a minute per key; every read is logged. Statuses come from what the provider returned — never an approval or a rejection — and bank account numbers come as their last four digits."},"servers":[{"url":"https://app.oncarousel.com"}],"security":[{"bearer":[]}],"tags":[{"name":"Start here","description":"What Carousel is, how a screening flows, and the way to test a key. New here? Read the introduction above first."},{"name":"Checks","description":"What you can send: every check, every combination of checks a screening can run — with its cost and whether each payer can send it right now — and any custom workflow Carousel set up for you. Send a combination as its `checks`, in any order."},{"name":"Workspaces & buildings","description":"Where a screening is filed. A screening filed under a building shows up there in Carousel, and a building in Québec runs Québec’s court checks. Adding a building is safe to repeat: an address already in the workspace comes back as that building."},{"name":"Screenings","description":"Send a screening and follow it. Every answer carries `portalUrl`, the screening’s page in Carousel — the link to show in your CRM."},{"name":"Results","description":"Each check’s results — identity, credit, court, police, bank, and what the applicant declared — and the stored documents behind them, as Carousel’s report shows them. Only for a key made with **Read applicant results** ticked. Statuses are read from what the provider returned, never from an approval or rejection; bank account numbers come as their last four digits; links to provider files never leave — download the stored copies from `documents`."},{"name":"Events","description":"Everything that happens to your screenings, oldest first. Read them with a cursor, or have each one POSTed to your webhook."}],"paths":{"/api/v1":{"get":{"summary":"About the API","description":"Endpoints, how to authenticate, and links to this document and the guide. No key needed.","security":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["Start here"],"operationId":"getApi"}},"/api/v1/openapi.json":{"get":{"summary":"OpenAPI document","description":"This document, as JSON. No key needed.","security":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["Start here"],"operationId":"getOpenApiDocument"}},"/api/v1/guide.md":{"get":{"summary":"Guide for AI agents","description":"A one-page walkthrough in plain text — the best first read for an agent. No key needed.","security":[],"responses":{"200":{"description":"Markdown","content":{"text/markdown":{"schema":{"type":"string"}}}}},"tags":["Start here"],"operationId":"getGuide"}},"/api/v1/me":{"get":{"summary":"Check your key","description":"The account and the key the request was made with. The quickest test that a key works.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Start here"],"operationId":"getMe"}},"/api/v1/checks":{"get":{"summary":"List checks and combinations","description":"Every check in the region with its token price, and every combination a screening can run.\n\n- **Send a combination** as `\"checks\"` in `POST /screenings` — exactly its checks, in any order. Use one whose `sendable` is true for your payer.\n- **Canada has two court systems.** Québec’s court checks are `court_qc` and `penal_qc`; the rest of Canada’s is `court_roc`. A combination’s `courtArea` says which it runs; a building in Québec takes Québec’s.\n- **Custom workflows** Carousel set up for your account are under `workflows`; send one by its `id` as `\"workflow\"`.","parameters":[{"name":"region","in":"query","required":true,"schema":{"type":"string","enum":["CA","US"]},"description":"CA (Canada) or US."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckList"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Checks"],"operationId":"listChecks"}},"/api/v1/workspaces":{"get":{"summary":"List workspaces","description":"Your workspaces — the top-level groups your buildings sit in.","parameters":[{"name":"region","in":"query","required":false,"schema":{"type":"string","enum":["CA","US"]},"description":"CA (Canada) or US."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Workspace"}}}}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Workspaces & buildings"],"operationId":"listWorkspaces"},"post":{"summary":"Create a workspace","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceCreate"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Workspace"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Workspaces & buildings"],"operationId":"createWorkspace"}},"/api/v1/buildings":{"get":{"summary":"List buildings","description":"A workspace’s buildings, with their units.","parameters":[{"name":"workspace","in":"query","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Building"}}}}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Workspaces & buildings"],"operationId":"listBuildings"},"post":{"summary":"Add a building","description":"An address already in the workspace returns that building (\"created\": false) with any new units added — never a duplicate. A unit written in the address (\"44 King St W #1203\") is moved to the units.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BuildingCreate"}}}},"responses":{"200":{"description":"Already there","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Building"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Building"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Workspaces & buildings"],"operationId":"createBuilding"}},"/api/v1/screenings":{"post":{"summary":"Send a screening","description":"Creates the screening, issues the applicant’s link and, unless `delivery` is `none`, emails it. The answer’s `portalUrl` is the link to show in your CRM.\n\n- **Retries are safe** with `Idempotency-Key`: the same key and body return the first answer (`Idempotent-Replayed: true`) and send nothing.\n- **A refusal about the moment** — `rate_limited`, `insufficient_tokens`, `combination_unavailable`, `workflow_unavailable`, `carousel_error`, `internal_error` — keeps nothing: the same request can go through later with the same key. Any other refusal is replayed.\n- **If the first request died after sending**, the retry answers `200` with the screening.\n- **Unknown fields are refused**, never ignored.\n- **Tokens are charged per completed check**; `tokenCost` is the most it can cost.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Strongly recommended. Makes retries safe."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendRequest"}}}},"responses":{"200":{"description":"A replay: this Idempotency-Key and body already sent this screening (header `Idempotent-Replayed: true`). The screening as GET returns it.","headers":{"Idempotent-Replayed":{"schema":{"type":"string","const":"true"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Screening"}}}},"201":{"description":"Sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScreeningCreated"}}}},"400":{"description":"invalid_request / invalid_email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"insufficient_tokens","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_conflict / request_in_progress / region_mismatch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"unknown_combination / court_area_mismatch / combination_unavailable / workflow_unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited / rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"carousel_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"test_mode_not_ready","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Screenings"],"operationId":"sendScreening"},"get":{"summary":"List screenings","description":"Every screening in your account — sent through the API or from Carousel, by anyone on your team, before or after you had a key — newest first, a page at a time: pass back `cursor` as `after` while `hasMore`. Narrow it with `status`, `workspace`, `building` or `updatedSince`. With `externalId`, every screening sent with that id instead (one page, `{ data }`). Import your history once with this, then follow changes with events or the webhook.","parameters":[{"name":"externalId","in":"query","required":false,"schema":{"type":"string"},"description":"Your own id — returns its screenings, newest first; the other parameters don’t apply."},{"name":"status","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated: invited, in_progress, completed, expired, cancelled."},{"name":"workspace","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Only screenings filed directly in this workspace."},{"name":"building","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"updatedSince","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Only screenings whose status or steps were written after this. Can include some with no visible change — events are the precise way to follow changes."},{"name":"after","in":"query","required":false,"schema":{"type":"string"},"description":"The \"cursor\" of the previous page."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ScreeningListItem"}},"cursor":{"type":["string","null"],"description":"Pass as \"after\" for the next page. Opaque; null on an empty page. Absent with `externalId` (up to 50, one page)."},"hasMore":{"type":"boolean"}}}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Screenings"],"operationId":"listScreenings"}},"/api/v1/screenings/{id}":{"get":{"summary":"Get a screening","description":"Its status, each check’s progress, and its links.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Screening"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Screenings"],"operationId":"getScreening"}},"/api/v1/screenings/{id}/advance":{"post":{"summary":"Advance a test screening","description":"Test keys only: the simulated applicant does everything still to come at once — the screening reaches `completed` (or `expired`, with `+expire`), and its events land in the test stream. Answers the screening as GET then does.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Screening"}}}},"400":{"description":"test_mode_only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"test_mode_not_ready","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Screenings"],"operationId":"advanceTestScreening"}},"/api/v1/screenings/{id}/results":{"get":{"summary":"Get results","description":"Every check’s results, its availability (`present`, `withheld` with a `note` saying why, `not_bought`, `absent`, `error`), the steps with provider-read statuses, and the stored documents. What Carousel has stored — a result lands within minutes of the step. Bank transactions are paged on their own (`…/transactions`). Needs a key with **Read applicant results**; 30 reads a minute per key across results, transactions and documents.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScreeningResults"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"results_not_allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Results"],"operationId":"getScreeningResults"}},"/api/v1/screenings/{id}/documents/{documentId}":{"get":{"summary":"Download a document","description":"One stored document — an ID image, the police report PDF, a court-file copy, an upload, the selfie video — in its own content type. Ids come from `documents` in the results. Files over 4 MB come in ranges: send `Range: bytes=0-4194303`, then the next 4 MB, until `Content-Range` shows the whole file. Needs a key with **Read applicant results**.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"documentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Range","in":"header","required":false,"schema":{"type":"string","examples":["bytes=0-4194303"]},"description":"Required for files over 4 MB; a range longer than 4 MB is answered with its first 4 MB."}],"responses":{"200":{"description":"The whole file, in its own content type (image/jpeg, application/pdf, video/mp4, …)","content":{"*/*":{"schema":{"type":"string","format":"binary"}}}},"206":{"description":"A range of it — see Content-Range","content":{"*/*":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"results_not_allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"document_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"416":{"description":"The range is outside the file"},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Results"],"operationId":"getScreeningDocument"}},"/api/v1/screenings/{id}/transactions":{"get":{"summary":"List bank transactions","description":"The bank check’s transactions, in ledger order, a page at a time — pass back `cursor` as `after` while `hasMore`. Needs a key with **Read applicant results**.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"after","in":"query","required":false,"schema":{"type":"string"},"description":"The \"cursor\" of the previous page; 0 or absent for the start. A cursor from before the bank data changed is 409 results_changed."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":500}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionPage"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"results_not_allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"results_changed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Results"],"operationId":"listScreeningTransactions"}},"/api/v1/events":{"get":{"summary":"List events","description":"Poll with after=<cursor from the last page> (0 to start). Every event the webhook would deliver is here too, kept for good. Filter with types=screening.completed,screening.started.","parameters":[{"name":"after","in":"query","required":false,"schema":{"type":"integer","minimum":0},"description":"The \"cursor\" of the previous page; 0 or absent for the start."},{"name":"types","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated event types."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventPage"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Events"],"operationId":"listEvents"}},"/api/v1/webhook/test":{"post":{"summary":"Send a test webhook","description":"POSTs one signed sample event to your webhook now and answers with what your receiver said — to check the signature, the parsing and a 2xx in time without waiting for a real screening. Any key. The event says `\"livemode\": false` and names no real screening.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"type":{"type":"string","enum":["screening.sent","screening.invitation_delivered","screening.invitation_failed","screening.reminded","screening.started","screening.step_completed","screening.completed","screening.viewed","screening.cancelled","screening.expired","application.stage_changed","application.note_added","application.moved","building.created","unit.created","balance.low","balance.exhausted"],"default":"screening.completed"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["delivered","statusCode","error","url","delivery","event"],"properties":{"delivered":{"type":"boolean","description":"Your receiver answered 2xx within 10 seconds."},"statusCode":{"type":["integer","null"]},"error":{"type":["string","null"]},"url":{"type":"string"},"delivery":{"type":"string","format":"uuid","description":"The Carousel-Delivery header sent."},"event":{"$ref":"#/components/schemas/Event"}}}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Events"],"operationId":"sendTestWebhook"}},"/api/v1/events/types":{"get":{"summary":"List event types","description":"Every event type, with what it means.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"description":{"type":"string"}}}}}}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"internal_error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Events"],"operationId":"listEventTypes"}}},"webhooks":{"event":{"post":{"tags":["Events"],"operationId":"receiveEvent","summary":"An event, POSTed to your webhook","description":"Every event type, with what it means:\n\n- `screening.sent` — A screening was created and its applicant link issued.\n- `screening.invitation_delivered` — The invitation email reached the applicant’s mail provider.\n- `screening.invitation_failed` — The invitation email bounced — hand the applicant the link yourself.\n- `screening.reminded` — A reminder was sent to the applicant.\n- `screening.started` — The applicant opened the application and started.\n- `screening.step_completed` — One check finished (data.check names it).\n- `screening.completed` — Every check is done — the report is ready at data.screening.portalUrl.\n- `screening.viewed` — Someone on your team opened the report in Carousel.\n- `screening.cancelled` — The screening was cancelled; nothing more is charged.\n- `screening.expired` — The applicant never started within 30 days; the invitation expired.\n- `application.stage_changed` — The application moved to another pipeline stage (data.stage).\n- `application.note_added` — A team note was added to the application.\n- `application.moved` — The application was filed under another workspace or building.\n- `building.created` — A building was added.\n- `unit.created` — A unit was added to a building.\n- `balance.low` — The token balance fell below what one standard screening costs (data.region).\n- `balance.exhausted` — The token balance ran out (data.region); token-paid sends are refused until a top-up.\n\nAnswer any 2xx within 10 seconds. Check `Carousel-Signature` before trusting the body. Saving the webhook address again in Carousel creates a NEW signing secret (shown once). Missed deliveries can always be read back from `GET /api/v1/events`.","security":[],"parameters":[{"name":"Carousel-Event","in":"header","required":true,"schema":{"type":"string","enum":["screening.sent","screening.invitation_delivered","screening.invitation_failed","screening.reminded","screening.started","screening.step_completed","screening.completed","screening.viewed","screening.cancelled","screening.expired","application.stage_changed","application.note_added","application.moved","building.created","unit.created","balance.low","balance.exhausted"]},"description":"The event’s type."},{"name":"Carousel-Delivery","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"This delivery’s id — the same on every retry. Dedupe on it."},{"name":"Carousel-Signature","in":"header","required":true,"schema":{"type":"string"},"example":"t=1791060000,v1=5f0c2b7e9a1d…","description":"`t` is the unix time of this attempt; `v1` is the hex HMAC-SHA256 of `t`, a dot and the raw body, keyed with your signing secret. Both are new on every attempt — you may refuse an old `t`."},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"Carousel-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"responses":{"200":{"description":"Received. Any 2xx works."}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"An account API key: cp_live_… — made in Carousel (app.oncarousel.com): account menu → Developers → Keys. There are no test keys."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","hint"],"properties":{"code":{"type":"string","enum":["invalid_request","invalid_email","unauthorized","insufficient_tokens","results_not_allowed","not_found","idempotency_conflict","request_in_progress","region_mismatch","unknown_combination","court_area_mismatch","combination_unavailable","workflow_unavailable","test_mode_only","test_mode_not_ready","results_changed","document_too_large","rate_limited","busy","carousel_error","internal_error"]},"message":{"type":"string"},"hint":{"type":"string"}}}}},"Me":{"type":"object","required":["account","key","livemode"],"examples":[{"account":{"id":"9c1e2d3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f","name":"Plateau Rentals"},"key":{"id":"1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e","name":"CRM"},"livemode":true}],"properties":{"account":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}},"key":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}},"livemode":{"type":"boolean","description":"False for a test key (cp_test_…), or a connection made in Test."}}},"CheckList":{"type":"object","properties":{"region":{"type":"string","enum":["CA","US"]},"currency":{"type":"string","enum":["CAD","USD"]},"checks":{"type":"array","items":{"$ref":"#/components/schemas/Check"}},"combinations":{"type":"array","items":{"$ref":"#/components/schemas/Combination"}},"workflows":{"type":"array","items":{"$ref":"#/components/schemas/CustomWorkflow"}}}},"Check":{"type":"object","examples":[{"id":"court_roc","name":"Court & Eviction Check (Rest of Canada)","provider":"OpenRoom","tokens":72,"courtArea":"ROC"}],"properties":{"id":{"type":"string","description":"What you send in \"checks\"."},"name":{"type":"string"},"provider":{"type":"string","description":"Who runs it."},"tokens":{"type":"integer","description":"Charged when this check completes (payer \"tokens\")."},"courtArea":{"type":["string","null"],"enum":["QC","ROC",null],"description":"Canada: the court system a court check belongs to. Null for every other check."}}},"Combination":{"type":"object","examples":[{"checks":["id","credit","court_roc"],"courtArea":"ROC","tokens":396,"applicantPrice":{"amount":32.99,"currency":"CAD"},"sendable":{"tokens":true,"renter":true}}],"properties":{"checks":{"type":"array","items":{"type":"string"},"description":"Send exactly these as \"checks\", in any order."},"courtArea":{"type":["string","null"],"enum":["QC","ROC",null],"description":"Canada: whose court checks it runs. Null when it has none (and in the US)."},"tokens":{"type":"integer","description":"The most it costs when every check completes (payer \"tokens\")."},"applicantPrice":{"type":"object","properties":{"amount":{"type":"number"},"currency":{"type":"string"}},"description":"What the applicant pays when payer is \"renter\"."},"sendable":{"type":"object","properties":{"tokens":{"type":"boolean"},"renter":{"type":"boolean"}},"description":"Whether each payer can send it right now."}}},"CustomWorkflow":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Send it as \"workflow\"."},"name":{"type":"string"},"payer":{"type":"string","enum":["tokens","renter"],"description":"Fixed by the workflow."},"tokens":{"type":"integer"},"checks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"tokens":{"type":"integer"}}}},"workspaces":{"type":"array","items":{"type":"string"},"description":"Present when it may only be sent into these workspaces."}}},"Workspace":{"type":"object","required":["id","name","region","kind","parent"],"examples":[{"id":"2a7d9c41-0b3e-4f6a-8c5d-1e2f3a4b5c6d","name":"Plateau portfolio","region":"CA","kind":"tenant","parent":null}],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"region":{"type":"string","enum":["CA","US"],"description":"A workspace has one region; its screenings, balance and prices follow it."},"kind":{"type":"string","enum":["tenant","commercial","employment","regular"],"description":"What it screens for. POST creates `tenant`."},"parent":{"type":["string","null"],"description":"The workspace it sits under, if any (read-only here)."}}},"WorkspaceCreate":{"type":"object","required":["name","region"],"additionalProperties":false,"properties":{"name":{"type":"string","maxLength":120},"region":{"type":"string","enum":["CA","US"]}}},"Building":{"type":"object","required":["id","address","workspace","region","province","units"],"examples":[{"id":"4b9f1c2e-8d3a-4f6b-9e21-7c5d0a1b2c3d","address":"3645 Boulevard Gouin Ouest, Montréal, QC H4K 1B3","workspace":"2a7d9c41-0b3e-4f6a-8c5d-1e2f3a4b5c6d","region":"CA","province":"QC","units":[{"id":"7e8f9a0b-1c2d-4e3f-8a4b-5c6d7e8f9a0b","label":"4B"}],"created":true}],"properties":{"id":{"type":"string","format":"uuid"},"address":{"type":"string"},"workspace":{"type":"string","format":"uuid"},"region":{"type":"string","enum":["CA","US"]},"province":{"type":["string","null"],"description":"Read from the address (postal code, or province and city names). A building in Québec runs Québec’s court checks."},"units":{"type":"array","items":{"type":"object","required":["id","label"],"properties":{"id":{"type":"string","format":"uuid"},"label":{"type":"string"}}}},"created":{"type":"boolean","description":"POST only: false when the address was already a building in the workspace."}}},"BuildingCreate":{"type":"object","additionalProperties":false,"required":["workspace","address"],"properties":{"workspace":{"type":"string","format":"uuid"},"address":{"type":"string","maxLength":200,"description":"The street address, e.g. \"3645 Boulevard Gouin Ouest, Montréal, QC H4K 1B3\"."},"units":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":500,"description":"Unit labels, e.g. [\"4B\", \"5A\"]. Omit for a whole-building rental. A unit written in the address (\"44 King St W #1203\") is moved here."},"rent":{"type":["number","null"],"minimum":0,"maximum":1000000,"description":"Monthly rent in the region’s currency (each unit’s, or the building’s when it has none). The report weighs the applicant’s income against it."}}},"SendRequest":{"type":"object","required":["applicant"],"additionalProperties":false,"description":"Send exactly one of `checks` or `workflow`, and at least one of `workspace`, `building` or `region` (`region` alone files it in Private). The applicant is an email address only — their name comes from their ID once they complete it.","examples":[{"checks":["id","credit","court_roc"],"applicant":{"email":"tenant@example.com"},"building":"4b9f1c2e-8d3a-4f6b-9e21-7c5d0a1b2c3d","externalId":"lead-1042"}],"properties":{"checks":{"type":"array","items":{"type":"string","pattern":"^[a-z_]{1,40}$"},"minItems":1,"maxItems":12,"uniqueItems":true,"description":"The checks to run: exactly one combination from GET /api/v1/checks, in any order. A malformed list (empty, over 12, duplicates, an id not in lowercase letters and _) is 400 invalid_request; a list that isn’t a combination is 422 unknown_combination. The check id `id` is identity verification. Send this or \"workflow\".","examples":[["id","credit","court_roc"]]},"workflow":{"type":"string","format":"uuid","description":"A custom workflow id from GET /api/v1/checks (\"workflows\"). Send this or \"checks\"."},"payer":{"type":"string","enum":["tokens","renter"],"description":"`tokens`: you pay from your token balance, per check as it completes. `renter`: the applicant pays the combination’s applicantPrice at checkout, and you are charged no tokens. Omitted: \"tokens\" for checks, the workflow’s own payer for a custom workflow (fixed per workflow)."},"applicant":{"type":"object","required":["email"],"additionalProperties":false,"properties":{"email":{"type":"string","format":"email","maxLength":254,"description":"Where the invitation goes. Phone numbers are refused."}}},"workspace":{"type":"string","format":"uuid","description":"File it in this workspace."},"building":{"type":"string","format":"uuid","description":"File it under this building (its workspace is used)."},"unit":{"type":"string","format":"uuid","description":"A unit of that building."},"region":{"type":"string","enum":["CA","US"],"description":"Required without `workspace` or `building` — it then files the screening in Private (your account’s screenings with no workspace). With one, optional: it must match the property’s region (409 region_mismatch)."},"externalId":{"type":"string","maxLength":200,"description":"Your own id for this send — stored, echoed, searchable, in every event.","examples":["lead-1042"]},"delivery":{"type":"string","enum":["email","none"],"default":"email","description":"email: we email the applicant their link. none: you deliver applicantLink yourself."}}},"ScreeningCreated":{"type":"object","description":"The 201 answer to POST /screenings.","required":["id","status","externalId","applicantLink","portalUrl","delivery","tokenCost","region","workspace","building","unit","createdAt","livemode"],"examples":[{"id":"6f0c2d1e-5b7a-4c8e-9f10-2a3b4c5d6e7f","status":"invited","externalId":"lead-1042","applicantLink":"https://apply.oncarousel.com/start-application?…","portalUrl":"https://app.oncarousel.com/report/6f0c2d1e-5b7a-4c8e-9f10-2a3b4c5d6e7f","delivery":"sent","tokenCost":336,"region":"CA","workspace":"2a7d9c41-0b3e-4f6a-8c5d-1e2f3a4b5c6d","building":"4b9f1c2e-8d3a-4f6b-9e21-7c5d0a1b2c3d","unit":null,"createdAt":"2026-10-04T15:02:11.000Z"}],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","const":"invited"},"externalId":{"type":["string","null"]},"applicantLink":{"type":"string","description":"For the applicant only. Never give it to your team."},"portalUrl":{"type":"string","description":"For your team: the screening’s page in Carousel. Opens for people signed in to Carousel who belong to this account or to the screening’s workspace. Never send it to the applicant."},"delivery":{"type":"string","enum":["sent","failed","none"],"description":"`sent`: our mail service accepted the invitation. `failed`: refused right away — hand the applicant `applicantLink` yourself. `none`: you asked for no email, or it wasn’t sent at that moment. A bounce later arrives as `screening.invitation_failed`."},"tokenCost":{"type":"integer","description":"The most it can cost you in tokens, when every check completes. 0 when the applicant pays."},"region":{"type":"string","enum":["CA","US"]},"workspace":{"type":["string","null"],"format":"uuid","description":"Where it is filed — the building’s workspace when you sent a building. Null: Private."},"building":{"type":["string","null"],"format":"uuid"},"unit":{"type":["string","null"],"format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"livemode":{"type":"boolean","description":"False for a test key’s screening (test mode): nothing real happened."}}},"Screening":{"type":"object","description":"GET /screenings/{id}, and the answer to a replayed send (200).","required":["id","status","externalId","applicantEmail","checks","workflow","payer","tokenCost","portalUrl","applicantLink","createdAt","invitedAt","startedAt","completedAt","steps","livemode"],"examples":[{"id":"6f0c2d1e-5b7a-4c8e-9f10-2a3b4c5d6e7f","status":"in_progress","externalId":"lead-1042","applicantEmail":"tenant@example.com","checks":["id","credit","court_roc"],"workflow":null,"payer":"tokens","tokenCost":336,"portalUrl":"https://app.oncarousel.com/report/6f0c2d1e-5b7a-4c8e-9f10-2a3b4c5d6e7f","applicantLink":"https://apply.oncarousel.com/start-application?…","createdAt":"2026-10-04T15:02:11.000Z","invitedAt":"2026-10-04T15:02:12.000Z","startedAt":"2026-10-04T16:40:03.000Z","completedAt":null,"steps":[{"check":"id","name":"Identity verification","status":"done","completedAt":"2026-10-04T16:46:51.000Z"},{"check":"credit","name":"Credit check","status":"in_progress","completedAt":null},{"check":"court_roc","name":"Court & Eviction Check (Rest of Canada)","status":"waiting","completedAt":null}]}],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["invited","in_progress","completed","expired","cancelled"],"description":"`invited`: sent, not started. `in_progress`: the applicant started. `completed`: every check is done — the report is at portalUrl. `expired`: nobody started it within 30 days of the invitation (only unstarted screenings expire). `cancelled`: cancelled in Carousel; nothing more is charged."},"externalId":{"type":["string","null"]},"applicantEmail":{"type":["string","null"]},"checks":{"type":"array","items":{"type":"string"},"description":"The check ids it runs."},"workflow":{"type":["string","null"],"format":"uuid","description":"The custom workflow it was sent with, if any."},"payer":{"type":"string","enum":["tokens","renter"]},"tokenCost":{"type":"integer","description":"The most it can cost you in tokens; 0 when the applicant pays."},"portalUrl":{"type":"string"},"applicantLink":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"invitedAt":{"type":["string","null"],"format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"livemode":{"type":"boolean","description":"False for a test key’s screening."},"steps":{"type":"array","items":{"type":"object","required":["check","name","status","completedAt"],"properties":{"check":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["waiting","in_progress","done","stopped"],"description":"`stopped`: didn’t run to a normal finish (an applicant error, a time-out, or the provider stopped it) — not charged as completed. GET …/results says what the provider returned."},"completedAt":{"type":["string","null"]}}}}}},"ScreeningListItem":{"description":"A screening in GET /screenings: the GET shape, plus where it is filed and when it last changed.","allOf":[{"$ref":"#/components/schemas/Screening"},{"type":"object","required":["workspace","building","unit","updatedAt"],"properties":{"workspace":{"type":["string","null"],"format":"uuid","description":"Null: Private."},"building":{"type":["string","null"],"format":"uuid"},"unit":{"type":["string","null"],"format":"uuid"},"updatedAt":{"type":"string","format":"date-time"}}}]},"Event":{"type":"object","examples":[{"id":"0d6e4f2a-1b3c-4d5e-8f90-a1b2c3d4e5f6","seq":1042,"type":"screening.completed","createdAt":"2026-10-03T18:42:10.512Z","data":{"screening":{"id":"6f0c2d1e-5b7a-4c8e-9f10-2a3b4c5d6e7f","externalId":"lead-1042","portalUrl":"https://app.oncarousel.com/report/6f0c2d1e-5b7a-4c8e-9f10-2a3b4c5d6e7f"}}}],"properties":{"id":{"type":"string","format":"uuid"},"seq":{"type":"integer","description":"Increasing (shared numbering, so expect gaps); the events cursor. Order by it — createdAt can go backwards."},"type":{"type":"string","enum":["screening.sent","screening.invitation_delivered","screening.invitation_failed","screening.reminded","screening.started","screening.step_completed","screening.completed","screening.viewed","screening.cancelled","screening.expired","application.stage_changed","application.note_added","application.moved","building.created","unit.created","balance.low","balance.exhausted"]},"createdAt":{"type":"string","format":"date-time"},"livemode":{"type":"boolean","description":"False for test mode’s events (a test key’s stream, POST /webhook/test)."},"data":{"type":"object","description":"Ids, your externalId and the screening’s page link — never applicant data. Screening events: `data.screening` = { id, externalId, portalUrl }. Application events list the application’s screenings."}}},"ApiStatus":{"type":"object","description":"Where a step or provider is, read from what the provider returned — never an approval or rejection.","properties":{"state":{"type":"string","enum":["clear","incomplete","processing","retry_asked","applicant_error","timed_out","cancelled","not_started","unknown"]},"label":{"type":"string","examples":["Clear"]}}},"CheckResult":{"type":"object","properties":{"availability":{"type":"string","enum":["present","withheld","not_bought","absent","error"]},"note":{"type":["string","null"],"description":"Why it is withheld, absent or in error."},"fetchedAt":{"type":["string","null"],"format":"date-time"},"result":{"type":["object","null"],"description":"The check’s results when `availability` is `present`."}}},"ScreeningResults":{"type":"object","description":"Which check id lands where: `identity` ← id; `credit` ← credit (`alternativeCredit`: extra bureau data from the same pull); `court` ← court_roc, court_qc, penal_qc (US: records); `police` ← criminal (US: records); `bank` ← bank; `selfDeclaration` and `questionnaire`: what the applicant declared and answered. The example is Carousel’s fictional sample applicant.","required":["screening","updatedAt","steps","checks","documents"],"examples":[{"screening":{"id":"a1000000-0000-4000-8000-000000000001","status":"completed","externalId":"lead-1042","portalUrl":"https://app.oncarousel.com/report/a1000000-0000-4000-8000-000000000001"},"updatedAt":"2026-09-12T14:25:00.000Z","steps":[{"key":"kyc","name":"Identity verification","status":{"state":"clear","label":"Verified"},"kind":"verified","startedAt":"2026-09-09T14:04:11.000Z","completedAt":"2026-09-09T14:05:28.000Z"},{"key":"connectBankAccount","name":"Financial verification","status":{"state":"clear","label":"Connected"},"kind":"verified","startedAt":"2026-09-09T14:06:11.000Z","completedAt":"2026-09-09T14:12:28.000Z"},{"key":"creditCheck","name":"Credit check","status":{"state":"clear","label":"Report received"},"kind":"verified","startedAt":"2026-09-09T14:08:11.000Z","completedAt":"2026-09-09T14:09:28.000Z"},{"key":"legalCheck","name":"Court & eviction checks","status":{"state":"clear","label":"Clear"},"kind":"verified","startedAt":"2026-09-09T14:12:11.000Z","completedAt":"2026-09-09T14:13:28.000Z"},{"key":"legalCheck:penal","name":"Penal search","status":{"state":"clear","label":"Clear"},"kind":"verified","startedAt":"2026-09-09T14:12:11.000Z","completedAt":"2026-09-09T14:13:28.000Z"},{"key":"selfDeclaration","name":"Self-declaration","status":{"state":"clear","label":"Stated"},"kind":"self","startedAt":"2026-09-09T14:16:11.000Z","completedAt":"2026-09-09T14:17:28.000Z"}],"checks":{"identity":{"availability":"present","note":null,"fetchedAt":"2026-09-12T14:20:00.000Z","result":{"provider":null,"verified":true,"document":{"type":"DRIVER_LICENSE","number":"B1234-567890-12","country":"CA","province":"QC","issuedOn":"2022-04-22","expiresOn":"2030-04-22"},"person":{"fullName":"NORA J BELLIVEAU","firstName":null,"lastName":null,"dateOfBirth":"1990-04-22","gender":"Female"},"address":{"onDocument":"1450 RUE EXEMPLE APT 4B, MONTREAL QC H3K0A1","lines":[],"city":null,"postcode":null,"selfDeclared":null},"documents":["sample-id-front","sample-id-back","sample-id-face"]}},"credit":{"availability":"present","note":null,"fetchedAt":"2026-09-12T14:25:00.000Z","result":{"provider":null,"found":null,"frozen":null,"messages":[],"scores":[{"product":"CreditVision Risk Score","score":742,"factors":["Balance on revolving account","Presence of inquiry","Presence of recently opened account","Balance on open mortgage account"]}],"trades":[{"creditor":"DESJARDINS HYPOTHEQUE","accountType":"mortgage","ownership":"Joint","opened":"2021-06-01T00:00:00.000Z","reported":null,"lastActivity":"2026-08-12T00:00:00.000Z","balance":444137,"highCredit":520000,"creditLimit":null,"pastDue":0,"payment":null,"frequency":null,"history":["paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid"],"late30":null,"late60":null,"late90":null,"status":null},{"creditor":"BANQUE NATIONALE","accountType":"installment","ownership":"Individual Account","opened":"2023-03-15T00:00:00.000Z","reported":null,"lastActivity":"2026-08-20T00:00:00.000Z","balance":19680,"highCredit":32000,"creditLimit":null,"pastDue":0,"payment":null,"frequency":null,"history":["paid","paid","paid","paid","paid","paid","paid","paid","paid","late30","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid"],"late30":null,"late60":null,"late90":null,"status":null},{"creditor":"CIBC CARTES DE CREDIT","accountType":"revolving","ownership":"Individual Account","opened":"2016-09-02T00:00:00.000Z","reported":null,"lastActivity":"2026-08-25T00:00:00.000Z","balance":2140,"highCredit":9200,"creditLimit":9200,"pastDue":0,"payment":null,"frequency":null,"history":["paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid"],"late30":null,"late60":null,"late90":null,"status":null},{"creditor":"SERVICES DE CARTES DESJARDINS","accountType":"revolving","ownership":"Individual Account","opened":"2019-05-03T00:00:00.000Z","reported":null,"lastActivity":"2026-08-19T00:00:00.000Z","balance":5075,"highCredit":7500,"creditLimit":7500,"pastDue":0,"payment":null,"frequency":null,"history":["paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid"],"late30":null,"late60":null,"late90":null,"status":null},{"creditor":"CANADIAN TIRE BANK","accountType":"revolving","ownership":"Individual Account","opened":"2014-02-11T00:00:00.000Z","reported":null,"lastActivity":"2026-07-30T00:00:00.000Z","balance":0,"highCredit":1500,"creditLimit":1500,"pastDue":0,"payment":null,"frequency":null,"history":["paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid"],"late30":null,"late60":null,"late90":null,"status":null},{"creditor":"ROGERS COMMUNICATIONS","accountType":"open","ownership":"Individual Account","opened":"2020-08-01T00:00:00.000Z","reported":null,"lastActivity":"2026-08-05T00:00:00.000Z","balance":96,"highCredit":310,"creditLimit":null,"pastDue":0,"payment":null,"frequency":null,"history":["paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid"],"late30":null,"late60":null,"late90":null,"status":null},{"creditor":"TD AUTO FINANCE","accountType":"installment","ownership":"Individual Account","opened":"2022-10-20T00:00:00.000Z","reported":null,"lastActivity":"2026-08-15T00:00:00.000Z","balance":11980,"highCredit":28900,"creditLimit":null,"pastDue":0,"payment":null,"frequency":null,"history":["paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","paid","late30","late30","paid","paid","paid","paid","paid","paid","paid","paid"],"late30":null,"late60":null,"late90":null,"status":null}],"enquiries":[{"name":null,"date":"2026-09-09T00:00:00.000Z","type":null},{"name":null,"date":"2026-03-02T00:00:00.000Z","type":null},{"name":null,"date":"2025-11-18T00:00:00.000Z","type":null}],"collections":[],"bankruptcies":[],"employments":[],"addresses":[{"address":"1450 RUE EXEMPLE, Apt 4B, MONTREAL, QC, H3K0A1","current":null,"dateReported":"2025-11-03T00:00:00.000Z"},{"address":"88 AV MODELE, LAVAL, QC, H7N0A2","current":null,"dateReported":"2019-06-18T00:00:00.000Z"}],"identity":{"names":["NORA J BELLIVEAU","NORA BELLIVEAU-ROY"],"dateOfBirth":"1990-04-22","phoneNumbers":["5145550148"]}}},"court":{"availability":"present","note":null,"fetchedAt":"2026-09-12T14:20:00.000Z","result":{"summary":"clear","penalSummary":"clear","providers":[{"provider":"Openroom","status":{"state":"clear","label":"Clear"},"match":null,"message":null,"error":null,"items":[]},{"provider":"Soquij","status":{"state":"clear","label":"Clear"},"match":null,"message":null,"error":null,"items":[]}],"documents":[]}},"police":{"availability":"not_bought","note":null,"fetchedAt":null,"result":null},"bank":{"availability":"present","note":null,"fetchedAt":"2026-09-12T14:25:00.000Z","result":{"connections":[{"title":null,"provider":"Flinks","status":{"state":"clear","label":"Clear"}}],"accounts":[{"id":"12d8b48e-0cb4-56c2-8dc7-896e4e45067d","title":"Chequing","institution":"Desjardins","accountNumberLast4":"4567","category":"Operations","type":"Chequing","currency":"CAD","balanceAvailable":72960,"balanceCurrent":72960,"balanceLimit":1000,"overdraftLimit":1000,"holder":{"fullName":"NORA BELLIVEAU","email":"nora.example@example.com","phone":"+1 514-555-0148","address":{"address":"1450 RUE EXEMPLE APT 4B","city":"MONTREAL","province":"QC","postalCode":"H3K 0A1","country":"CA"}}},{"id":"3802eaa9-6aae-51ae-965b-b88b71a6902f","title":"Epargne a interet eleve","institution":"Desjardins","accountNumberLast4":"4321","category":"Savings","type":"Savings","currency":"CAD","balanceAvailable":18240.55,"balanceCurrent":18240.55,"balanceLimit":null,"overdraftLimit":null,"holder":{"fullName":"NORA BELLIVEAU","email":"nora.example@example.com","phone":"+1 514-555-0148","address":{"address":"1450 RUE EXEMPLE APT 4B","city":"MONTREAL","province":"QC","postalCode":"H3K 0A1","country":"CA"}}}],"transactionCount":111,"transactionsUrl":"https://app.oncarousel.com/api/v1/screenings/a1000000-0000-4000-8000-000000000001/transactions","transactionsTruncated":false}},"alternativeCredit":{"availability":"absent","note":"Nothing came back for this check.","fetchedAt":null,"result":null},"selfDeclaration":{"availability":"present","note":null,"fetchedAt":"2026-09-12T14:20:00.000Z","result":{"income":{"monthlyIncome":{"amount":7290,"currency":"CAD"},"employmentStatus":"EmployedFullTime","employment":{"kind":"employed","position":"Account executive","companyName":"Lightspeed Commerce","employer":{"fullName":"Lightspeed Commerce","phoneNumber":"+15145550188","email":null},"startDate":"2021-03-15"}},"documents":[],"living":{"status":"Owning","detail":null,"address":"1450 RUE EXEMPLE APT 4B, MONTREAL QC H3K0A1","rent":{"amount":0,"currency":"CAD"},"moveInDate":"2021-06-01","landlord":{"fullName":null,"phoneNumber":null,"email":null}},"residences":[{"status":"Owning","detail":null,"address":"1450 RUE EXEMPLE APT 4B, MONTREAL QC H3K0A1","moveInDate":"2021-06-01","moveOutDate":null,"rent":null,"mortgagePayment":null,"landlord":{"fullName":null,"phoneNumber":null,"email":null}},{"status":"Renting","detail":null,"address":"88 AV MODELE, LAVAL QC H7N0A2","moveInDate":"2019-06-18","moveOutDate":"2021-05-31","rent":{"amount":1290,"currency":"CAD"},"mortgagePayment":null,"landlord":{"fullName":null,"phoneNumber":null,"email":null}}],"occupants":{"count":2,"others":[]},"lifestyle":{"smokeOrVape":"no","ownPets":"no","criminalBackground":"no"},"pets":null,"legalStatus":{"status":"CANADIAN_CITIZEN","documents":[],"requiredDocument":null}}},"questionnaire":{"availability":"absent","note":"Nothing came back for this check.","fetchedAt":null,"result":null}},"documents":[{"id":"sample-id-front","kind":"id_front","contentType":"image/jpeg","byteSize":373539,"fetchedAt":"2026-09-12T14:20:00.000Z","downloadUrl":"https://app.oncarousel.com/api/v1/screenings/a1000000-0000-4000-8000-000000000001/documents/sample-id-front"},{"id":"sample-id-back","kind":"id_back","contentType":"image/jpeg","byteSize":373567,"fetchedAt":"2026-09-12T14:20:00.000Z","downloadUrl":"https://app.oncarousel.com/api/v1/screenings/a1000000-0000-4000-8000-000000000001/documents/sample-id-back"},{"id":"sample-id-face","kind":"id_face","contentType":"image/jpeg","byteSize":450995,"fetchedAt":"2026-09-12T14:20:00.000Z","downloadUrl":"https://app.oncarousel.com/api/v1/screenings/a1000000-0000-4000-8000-000000000001/documents/sample-id-face"}]}],"properties":{"screening":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"externalId":{"type":["string","null"]},"portalUrl":{"type":"string"}}},"updatedAt":{"type":["string","null"],"format":"date-time"},"steps":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"},"status":{"$ref":"#/components/schemas/ApiStatus"},"kind":{"type":"string","enum":["verified","self"]},"startedAt":{"type":["string","null"]},"completedAt":{"type":["string","null"]}}}},"checks":{"type":"object","description":"One entry per check. `identity`: document, person, address and its image ids. `credit`: scores, trades with payment history, enquiries, collections, bankruptcies, employments, addresses. `court`: a `summary` for the Court & Eviction searches and a `penalSummary` when the Penal Search was bought (`clear`, `possible_matches`, `not_clear_yet` — as the report says them), and each provider’s status and items, each tagged with its `search` (`eviction`, `court`, `penal`, `decisions`, `other`). `police`: the `result` (`negative`, `confirmation`, `incomplete`), convictions declared, address history — or only `hidden: true` and where it is, when it timed out, was cancelled or hit an applicant error. `bank`: connections, accounts (account numbers as the last four digits), `transactionCount` and `transactionsUrl`. `alternativeCredit`, `selfDeclaration` and `questionnaire`: what was returned or declared.","required":["identity","credit","court","police","bank","alternativeCredit","selfDeclaration","questionnaire"],"properties":{"identity":{"type":"object","required":["availability","note","fetchedAt","result"],"properties":{"availability":{"type":"string","enum":["present","withheld","not_bought","absent","error"],"description":"`withheld`: the screening was cancelled or expired before this check finished (not shown, not charged). `absent`: bought, nothing back yet. `error`: couldn’t be read."},"note":{"type":["string","null"],"description":"One sentence when withheld, absent or in error — or on a present check when a part of it failed."},"fetchedAt":{"type":["string","null"],"format":"date-time"},"result":{"anyOf":[{"type":"object","properties":{"provider":{},"verified":{"type":["boolean","null"]},"document":{"type":"object","properties":{"type":{"type":["string","null"]},"number":{"type":["string","null"]},"country":{"type":["string","null"]},"province":{"type":["string","null"]},"issuedOn":{"type":["string","null"]},"expiresOn":{"type":["string","null"]}}},"person":{"type":"object","properties":{"fullName":{"type":["string","null"]},"firstName":{},"lastName":{},"dateOfBirth":{"type":["string","null"]},"gender":{"type":["string","null"]}}},"address":{"type":"object","properties":{"onDocument":{"type":["string","null"]},"lines":{"type":"array","items":{}},"city":{},"postcode":{},"selfDeclared":{}}},"documents":{"type":"array","items":{"type":["string","null"]}}}},{"type":"null"}],"description":"Set when `availability` is `present`."}}},"credit":{"type":"object","required":["availability","note","fetchedAt","result"],"properties":{"availability":{"type":"string","enum":["present","withheld","not_bought","absent","error"],"description":"`withheld`: the screening was cancelled or expired before this check finished (not shown, not charged). `absent`: bought, nothing back yet. `error`: couldn’t be read."},"note":{"type":["string","null"],"description":"One sentence when withheld, absent or in error — or on a present check when a part of it failed."},"fetchedAt":{"type":["string","null"],"format":"date-time"},"result":{"anyOf":[{"type":"object","properties":{"provider":{},"found":{},"frozen":{},"messages":{"type":"array","items":{}},"scores":{"type":"array","items":{"type":"object","properties":{"product":{"type":["string","null"]},"score":{"type":["integer","null"]},"factors":{"type":"array","items":{"type":["string","null"]}}}}},"trades":{"type":"array","items":{"type":"object","properties":{"creditor":{"type":["string","null"]},"accountType":{"type":["string","null"]},"ownership":{"type":["string","null"]},"opened":{"type":["string","null"]},"lastActivity":{"type":["string","null"]},"balance":{"type":["integer","null"]},"highCredit":{"type":["integer","null"]},"pastDue":{"type":["integer","null"]},"history":{"type":"array","items":{"type":["string","null"]}},"creditLimit":{},"reported":{},"payment":{},"frequency":{},"late30":{},"late60":{},"late90":{},"status":{}}}},"enquiries":{"type":"array","items":{"type":"object","properties":{"date":{"type":["string","null"]},"name":{},"type":{}}}},"collections":{"type":"array","items":{}},"bankruptcies":{"type":"array","items":{}},"employments":{"type":"array","items":{}},"addresses":{"type":"array","items":{"type":"object","properties":{"address":{"type":["string","null"]},"dateReported":{"type":["string","null"]},"current":{}}}},"identity":{"type":"object","properties":{"names":{"type":"array","items":{"type":["string","null"]}},"dateOfBirth":{"type":["string","null"]},"phoneNumbers":{"type":"array","items":{"type":["string","null"]}}}}}},{"type":"null"}],"description":"Set when `availability` is `present`."}}},"court":{"type":"object","required":["availability","note","fetchedAt","result"],"properties":{"availability":{"type":"string","enum":["present","withheld","not_bought","absent","error"],"description":"`withheld`: the screening was cancelled or expired before this check finished (not shown, not charged). `absent`: bought, nothing back yet. `error`: couldn’t be read."},"note":{"type":["string","null"],"description":"One sentence when withheld, absent or in error — or on a present check when a part of it failed."},"fetchedAt":{"type":["string","null"],"format":"date-time"},"result":{"anyOf":[{"type":"object","properties":{"summary":{"type":["string","null"]},"penalSummary":{"type":["string","null"]},"providers":{"type":"array","items":{"type":"object","properties":{"provider":{"type":["string","null"]},"status":{"type":"object","properties":{"state":{"type":["string","null"]},"label":{"type":["string","null"]}}},"items":{"type":"array","items":{}},"match":{},"message":{},"error":{}}}},"documents":{"type":"array","items":{}}}},{"type":"null"}],"description":"Set when `availability` is `present`."}}},"police":{"type":"object","required":["availability","note","fetchedAt","result"],"properties":{"availability":{"type":"string","enum":["present","withheld","not_bought","absent","error"],"description":"`withheld`: the screening was cancelled or expired before this check finished (not shown, not charged). `absent`: bought, nothing back yet. `error`: couldn’t be read."},"note":{"type":["string","null"],"description":"One sentence when withheld, absent or in error — or on a present check when a part of it failed."},"fetchedAt":{"type":["string","null"],"format":"date-time"},"result":{"anyOf":[{"type":"object","description":"With `hidden: true` (timed out, cancelled, applicant error) only `lifecycle`, `submittedAt` and `completedAt` come back.","properties":{"hidden":{"type":"boolean"},"result":{"type":["string","null"],"enum":["negative","confirmation","incomplete",null],"description":"`negative`: no record found. `confirmation`: something to confirm in person. `incomplete`: not finished."},"lifecycle":{"type":"string","enum":["running","completed","failed"]},"service":{"type":["string","null"]},"policeService":{"type":["string","null"]},"submittedAt":{"type":["string","null"]},"completedAt":{"type":["string","null"]},"error":{"type":["string","null"]},"searchedAs":{"type":["object","null"],"description":"Who was searched: name, date of birth, phone, addresses as submitted."},"verification":{"type":["object","null"],"properties":{"documentType":{"type":["string","null"]},"documentNumber":{"type":["string","null"]},"issuingCountry":{"type":["string","null"]},"expiryDate":{"type":["string","null"]}}},"addressHistory":{"type":"array","items":{"type":"object"}},"convictions":{"type":"array","items":{"type":"object","properties":{"offenseType":{"type":["string","null"]},"offenseCode":{"type":["string","null"]},"courtLocation":{"type":["string","null"]},"dateOfSentence":{"type":["string","null"]}}},"description":"What the applicant declared."},"documents":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Ids in `documents` (the police certificate)."}}},{"type":"null"}],"description":"Set when `availability` is `present`."}}},"bank":{"type":"object","required":["availability","note","fetchedAt","result"],"properties":{"availability":{"type":"string","enum":["present","withheld","not_bought","absent","error"],"description":"`withheld`: the screening was cancelled or expired before this check finished (not shown, not charged). `absent`: bought, nothing back yet. `error`: couldn’t be read."},"note":{"type":["string","null"],"description":"One sentence when withheld, absent or in error — or on a present check when a part of it failed."},"fetchedAt":{"type":["string","null"],"format":"date-time"},"result":{"anyOf":[{"type":"object","properties":{"connections":{"type":"array","items":{"type":"object","properties":{"provider":{"type":["string","null"]},"status":{"type":"object","properties":{"state":{"type":["string","null"]},"label":{"type":["string","null"]}}},"title":{}}}},"accounts":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"title":{"type":["string","null"]},"institution":{"type":["string","null"]},"accountNumberLast4":{"type":["string","null"]},"category":{"type":["string","null"]},"type":{"type":["string","null"]},"currency":{"type":["string","null"]},"balanceAvailable":{"type":["integer","null"]},"balanceCurrent":{"type":["integer","null"]},"balanceLimit":{"type":["integer","null"]},"overdraftLimit":{"type":["integer","null"]},"holder":{"type":"object","properties":{"fullName":{"type":["string","null"]},"email":{"type":["string","null"]},"phone":{"type":["string","null"]},"address":{"type":"object","properties":{"address":{"type":["string","null"]},"city":{"type":["string","null"]},"province":{"type":["string","null"]},"postalCode":{"type":["string","null"]},"country":{"type":["string","null"]}}}}}}}},"transactionCount":{"type":["integer","null"]},"transactionsUrl":{"type":["string","null"]},"transactionsTruncated":{"type":["boolean","null"]}}},{"type":"null"}],"description":"Set when `availability` is `present`."}}},"alternativeCredit":{"type":"object","required":["availability","note","fetchedAt","result"],"properties":{"availability":{"type":"string","enum":["present","withheld","not_bought","absent","error"],"description":"`withheld`: the screening was cancelled or expired before this check finished (not shown, not charged). `absent`: bought, nothing back yet. `error`: couldn’t be read."},"note":{"type":["string","null"],"description":"One sentence when withheld, absent or in error — or on a present check when a part of it failed."},"fetchedAt":{"type":["string","null"],"format":"date-time"},"result":{"anyOf":[{"type":"object","properties":{"provider":{"type":["string","null"]},"hasExistingLoans":{"type":["boolean","null"]},"createdAt":{"type":["string","null"]},"documents":{"type":"array","items":{"type":"string","format":"uuid"}}}},{"type":"null"}],"description":"Set when `availability` is `present`."}}},"selfDeclaration":{"type":"object","required":["availability","note","fetchedAt","result"],"properties":{"availability":{"type":"string","enum":["present","withheld","not_bought","absent","error"],"description":"`withheld`: the screening was cancelled or expired before this check finished (not shown, not charged). `absent`: bought, nothing back yet. `error`: couldn’t be read."},"note":{"type":["string","null"],"description":"One sentence when withheld, absent or in error — or on a present check when a part of it failed."},"fetchedAt":{"type":["string","null"],"format":"date-time"},"result":{"anyOf":[{"type":"object","properties":{"income":{"type":"object","properties":{"monthlyIncome":{"type":"object","properties":{"amount":{"type":["integer","null"]},"currency":{"type":["string","null"]}}},"employmentStatus":{"type":["string","null"]},"employment":{"type":"object","properties":{"kind":{"type":["string","null"]},"position":{"type":["string","null"]},"companyName":{"type":["string","null"]},"employer":{"type":"object","properties":{"fullName":{"type":["string","null"]},"phoneNumber":{"type":["string","null"]},"email":{}}},"startDate":{"type":["string","null"]}}}}},"documents":{"type":"array","items":{}},"living":{"type":"object","properties":{"status":{"type":["string","null"]},"detail":{},"address":{"type":["string","null"]},"rent":{"type":"object","properties":{"amount":{"type":["integer","null"]},"currency":{"type":["string","null"]}}},"moveInDate":{"type":["string","null"]},"landlord":{"type":"object","properties":{"fullName":{},"phoneNumber":{},"email":{}}}}},"residences":{"type":"array","items":{"type":"object","properties":{"status":{"type":["string","null"]},"address":{"type":["string","null"]},"moveInDate":{"type":["string","null"]},"landlord":{"type":"object","properties":{"fullName":{},"phoneNumber":{},"email":{}}},"moveOutDate":{},"rent":{},"detail":{},"mortgagePayment":{}}}},"occupants":{"type":"object","properties":{"count":{"type":["integer","null"]},"others":{"type":"array","items":{}}}},"lifestyle":{"type":"object","properties":{"smokeOrVape":{"type":["string","null"]},"ownPets":{"type":["string","null"]},"criminalBackground":{"type":["string","null"]}}},"pets":{},"legalStatus":{"type":"object","properties":{"status":{"type":["string","null"]},"documents":{"type":"array","items":{}},"requiredDocument":{}}}}},{"type":"null"}],"description":"Set when `availability` is `present`."}}},"questionnaire":{"type":"object","required":["availability","note","fetchedAt","result"],"properties":{"availability":{"type":"string","enum":["present","withheld","not_bought","absent","error"],"description":"`withheld`: the screening was cancelled or expired before this check finished (not shown, not charged). `absent`: bought, nothing back yet. `error`: couldn’t be read."},"note":{"type":["string","null"],"description":"One sentence when withheld, absent or in error — or on a present check when a part of it failed."},"fetchedAt":{"type":["string","null"],"format":"date-time"},"result":{"anyOf":[{"type":"object","properties":{"answers":{"type":"array","items":{"type":"object","properties":{"question":{"type":"string"},"description":{"type":["string","null"]},"answer":{}}}}}},{"type":"null"}],"description":"Set when `availability` is `present`."}}}}},"documents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["id_front","id_back","id_face","background_pdf","questionnaire_upload","legal_item","self_declaration_doc","bureau_report"]},"contentType":{"type":"string"},"byteSize":{"type":"integer"},"fetchedAt":{"type":"string","format":"date-time"},"downloadUrl":{"type":"string","description":"GET it with your key."}}}}}},"TransactionPage":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":["string","null"]},"accountId":{"type":["string","null"]},"date":{"type":["string","null"]},"description":{"type":["string","null"]},"amount":{"type":["number","null"]},"type":{"type":["string","null"],"enum":["debit","credit",null]},"balance":{"type":["number","null"]},"category":{"type":["string","null"]},"subCategory":{"type":["string","null"]}}}},"cursor":{"type":"string","description":"Pass as \"after\" next time. Tied to the bank data it came from.","examples":["500.1791060000000"]},"hasMore":{"type":"boolean"},"total":{"type":"integer"},"truncated":{"type":"boolean","description":"An account had more transactions than Carousel’s fetch keeps."}}},"EventPage":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"cursor":{"type":"integer","description":"Pass as \"after\" next time."},"hasMore":{"type":"boolean"}}}}}}