Genni API
Getting started
The Genni API turns annual reports and financial statements into structured, checked data. Send a PDF (digital or scanned); Genni finds the primary statements, extracts every line, maps it to a standard template, checks it against accounting rules, and gives you the figures with the page each came from.
Everything in the Genni portal is built on this API, so anything you can do there you can automate.
Base URL
https://api.genni.scribblegreen.com/v1Authentication
Every request needs an API key. Create one in the portal under API keys. Keys start with sgk_, belong to your organisation, and are shown once. Send it as a bearer token:
Authorization: Bearer sgk_your_keyKeep keys on your server; never put them in a web page or mobile app. Revoke a key in the portal at any time.
Your first document in three calls
1. Upload a report. Company name and financial year are optional but let Genni compare with last year's report.
curl https://api.genni.scribblegreen.com/v1/documents \
-H "Authorization: Bearer $GENNI_KEY" \
-F file=@annual-report-2024.pdf \
-F company_name="Dangote Cement Plc" \
-F fiscal_year=20242. Wait until its status is completed, or in_review if a check needs a person. It usually takes about a minute. Use a webhook, or poll:
curl https://api.genni.scribblegreen.com/v1/documents/$DOCUMENT_ID -H "Authorization: Bearer $GENNI_KEY"3. Get the figures, or the whole thing as a spreadsheet:
curl "https://api.genni.scribblegreen.com/v1/documents/$DOCUMENT_ID/figures?statement=financial_position" \
-H "Authorization: Bearer $GENNI_KEY"
curl -o report.xlsx "https://api.genni.scribblegreen.com/v1/documents/$DOCUMENT_ID/export?format=xlsx" \
-H "Authorization: Bearer $GENNI_KEY"The same in Python
import time, requests
API = "https://api.genni.scribblegreen.com/v1"
H = {"Authorization": f"Bearer {GENNI_KEY}"}
with open("annual-report-2024.pdf", "rb") as f:
doc = requests.post(f"{API}/documents", headers=H, files={"file": f},
data={"company_name": "Nestle Nigeria Plc", "fiscal_year": 2024}).json()
while (status := requests.get(f"{API}/documents/{doc['id']}", headers=H).json()["status"]) in ("uploaded", "processing"):
time.sleep(10)
figures = requests.get(f"{API}/documents/{doc['id']}/figures", headers=H).json()["items"]And in JavaScript (Node 18+)
const API = "https://api.genni.scribblegreen.com/v1";
const headers = { Authorization: `Bearer ${process.env.GENNI_KEY}` };
const form = new FormData();
form.append("file", new Blob([await fs.promises.readFile("annual-report-2024.pdf")]), "annual-report-2024.pdf");
form.append("company_name", "Zenith Bank Plc");
form.append("fiscal_year", "2024");
const doc = await (await fetch(`${API}/documents`, { method: "POST", headers, body: form })).json();Document statuses
| Status | Meaning |
|---|---|
uploaded | Received and queued. |
processing | Genni is finding and reading the statements. |
completed | Figures extracted and every check passed (or review finished). Ready to use. |
in_review | Figures extracted, but at least one check needs a person. See Checks and review. |
analyzed | No figures could be extracted, for example because no statements were found. |
failed | Processing failed after retries. Try again, or contact us with the request ID. |