GenniDocs

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/v1

Authentication

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:

http
Authorization: Bearer sgk_your_key

Keep 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.

bash
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=2024

2. 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:

bash
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:

bash
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

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+)

javascript
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

StatusMeaning
uploadedReceived and queued.
processingGenni is finding and reading the statements.
completedFigures extracted and every check passed (or review finished). Ready to use.
in_reviewFigures extracted, but at least one check needs a person. See Checks and review.
analyzedNo figures could be extracted, for example because no statements were found.
failedProcessing failed after retries. Try again, or contact us with the request ID.

Next: Uploading documents →