Quick start

Get started in 3 steps

Upload a document, poll by jobId, consume structured results.

Last updated: April 2026

This flow works for invoice, grn, bank_statement, aadhar_card, and pan_card document types.
1

Authenticate

Add your API key to the Authorization header on every request. Get your key from the dashboard.

HTTP
Authorization: Bearer <YOUR_API_KEY>
2

Upload a document

TypeScript
const BASE_URL = "https://api.number7ai.com/api/v1";

const form = new FormData();
form.append("file", file);               // File object
form.append("fileName", file.name);
form.append("fileType", file.type);      // e.g. "application/pdf"

const res = await fetch(
  `${BASE_URL}/upload?document.type=invoice&document.version=v1`,
  {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.N7_API_KEY}` },
    body: form,
  }
);

const { data } = await res.json();
const jobId = data.jobId;               // Save this
Python
import requests

BASE_URL = "https://api.number7ai.com/api/v1"

with open("invoice.pdf", "rb") as f:
    res = requests.post(
        f"{BASE_URL}/upload?document.type=invoice&document.version=v1",
        headers={"Authorization": f"Bearer {API_KEY}"},
        files={"file": ("invoice.pdf", f, "application/pdf")},
        data={"fileName": "invoice.pdf", "fileType": "application/pdf"},
    )

job_id = res.json()["data"]["jobId"]
cURL
curl -X POST \
  "https://api.number7ai.com/api/v1/upload?document.type=invoice&document.version=v1" \
  -H "Authorization: Bearer $API_KEY" \
  -F "file=@invoice.pdf" \
  -F "fileName=invoice.pdf" \
  -F "fileType=application/pdf"
3

Poll for results

TypeScript
async function pollResult(jobId: string) {
  for (let i = 0; i < 6; i++) {               // up to ~2 minutes
    await new Promise((r) => setTimeout(r, 20_000));

    const res = await fetch(`${BASE_URL}/results/${jobId}`, {
      headers: { Authorization: `Bearer ${process.env.N7_API_KEY}` },
    });
    const body = await res.json();

    if (body.data?.fileStatus === "done")   return body.data;
    if (body.data?.fileStatus === "failed") throw new Error("Processing failed");
  }
  throw new Error("Timed out waiting for result");
}
Status lifecycle: uploading → processing → scanning → ai_processing → done | failed