> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sahlfinancial.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Create a key, read a document, get a verdict. Three steps.

The API reads documents (`extract`) and verifies a profile (`verify`), two of the things Sahl does for lenders and banks. Bank connections and scoring are in the console. This is the real flow in v0.2.0. For a longer example see the [walkthrough](/guides/walkthrough), and to try the calls without code see [Test in the sandbox](/test-in-sandbox).

## Before you start

1. Get the partner API enabled on your workspace. It is switched on per workspace by Sahl, not self-serve: [request sandbox access](https://sahlfinancial.com/contact?type=demo).
2. In the console open **Settings**, then **API Keys**, then **New key**. Tick `kyc:extract` and `kyc:verify`. Copy the secret once. Keep it on your server.

Set it as `SAHL_API_KEY`. All samples use `https://app.sahlfinancial.com/api`, `environment=sandbox` and fake data. Use a fake image of a Moroccan national ID (CIN) of your own.

## 1. Read a document

Send 1 to 5 files (JPEG, PNG, WebP, TIFF or PDF, up to 30 MB each). Add a `reference` (your id for the client) to file the result on a case.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://app.sahlfinancial.com/api/v1/kyc/extract \
    -H "Authorization: Bearer $SAHL_API_KEY" \
    -F "files=@cin-test.jpg" \
    -F "doc_type=national_id" \
    -F "reference=client-0001" \
    -F "environment=sandbox" > extracted.json
  ```

  ```javascript JavaScript theme={null}
  import { readFile } from "node:fs/promises";

  const form = new FormData();
  form.append("files", new Blob([await readFile("cin-test.jpg")], { type: "image/jpeg" }), "cin-test.jpg");
  form.append("doc_type", "national_id");
  form.append("reference", "client-0001");
  form.append("environment", "sandbox");

  const res = await fetch("https://app.sahlfinancial.com/api/v1/kyc/extract", {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.SAHL_API_KEY}` },
    body: form,
  });
  const extracted = await res.json();
  ```

  ```python Python theme={null}
  import os, requests

  with open("cin-test.jpg", "rb") as f:
      res = requests.post(
          "https://app.sahlfinancial.com/api/v1/kyc/extract",
          headers={"Authorization": f"Bearer {os.environ['SAHL_API_KEY']}"},
          files=[("files", ("cin-test.jpg", f, "image/jpeg"))],
          data={"doc_type": "national_id", "reference": "client-0001", "environment": "sandbox"},
      )
  extracted = res.json()
  ```
</CodeGroup>

The answer has `fields`, `documents`, `field_count`, `checks`, `reader_unavailable` and `policy`. With a `reference` it also has `case_id` and `document_ids`. See [Read documents](/guides/ocr-documents).

## 2. Verify the profile

Send the `documents` entries back as they came, with the fields you hold.

<CodeGroup>
  ```bash cURL theme={null}
  jq '{reference: "client-0001", environment: "sandbox", subject: "Test Client", kind: "individual",
       values: {first_name: "Test", last_name: "Client"}, documents: .documents}' extracted.json |
  curl -X POST https://app.sahlfinancial.com/api/v1/kyc/verify \
    -H "Authorization: Bearer $SAHL_API_KEY" \
    -H "Content-Type: application/json" \
    -d @-
  ```

  ```javascript JavaScript theme={null}
  const verdict = await fetch("https://app.sahlfinancial.com/api/v1/kyc/verify", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SAHL_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      reference: "client-0001",
      environment: "sandbox",
      subject: "Test Client",
      kind: "individual",
      values: { first_name: "Test", last_name: "Client" },
      documents: extracted.documents,
    }),
  }).then((r) => r.json());
  console.log(verdict.passed, verdict.flags);
  ```

  ```python Python theme={null}
  verdict = requests.post(
      "https://app.sahlfinancial.com/api/v1/kyc/verify",
      headers={"Authorization": f"Bearer {os.environ['SAHL_API_KEY']}"},
      json={
          "reference": "client-0001",
          "environment": "sandbox",
          "subject": "Test Client",
          "kind": "individual",
          "values": {"first_name": "Test", "last_name": "Client"},
          "documents": extracted["documents"],
      },
  ).json()
  print(verdict["passed"], verdict["flags"])
  ```
</CodeGroup>

## 3. Read the verdict

`passed` is true when no critical check failed. `critical_failures` and `flags` list what needs a person. A file with no photo ID among its documents fails with `required:photo_id`, so send the entries from step 1. `/v1/kyc/assess` takes the same body and adds a risk assessment.

Because of the `reference`, the case, its documents and the verdict are filed on your workspace, where your staff see them under Cases and Documents.

## Next

<CardGroup cols={2}>
  <Card title="Verify a profile" icon="shield-check" href="/guides/verification">Every check, what it returns, how to read passed and flags.</Card>
  <Card title="Errors" icon="triangle-exclamation" href="/errors">Every status and code, with the fix.</Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.