Alighieria Python SDK
Python client for the Alighieria API: upload a manuscript once, then run corrections, translations, dossiers, synopses, indexes, EPUBs, AI detection, plagiarism checks and marketing content on it.
Requires Python 3.10 or later.
pip install alighieria
Quickstart
Create an API key in the dashboard and
export it as ALIGHIERIA_API_KEY. Keys are secret: use the SDK from your
backend, never from a browser or a mobile app.
from alighieria import Alighieria
client = Alighieria() # reads ALIGHIERIA_API_KEY
document = client.documents.upload(
"the_long_winter.docx", title="The Long Winter", author="Ana Pérez"
).wait()
synopsis = client.synopses.create(document.id, word_count=300).wait()
print(synopsis.result().content)
Every workflow has the same three steps: upload a document, launch a job with its id, wait for the job and read or download the result.
Jobs
Uploads and generations run in the background. Launch methods return a Job
right away:
run = client.corrections.create(document.id, correction_types=["editorial", "raccord"])
run.wait() # polls until the run finishes
run.status # "completed", "partial", "error" or "failed"
run.suites # progress per correction family
run.raw["total_cost"] # credits charged
run.download("corrected/") # DOCX, PDF or IDML, in the format of the source
for finding in client.corrections.findings(run.id, family="editorial"):
print(finding.page, finding.original, "->", finding.corrected)
wait() polls every 5 seconds at first and backs off to 30. It raises
JobTimeoutError after an hour by default (timeout=None waits forever; the
job keeps running either way) and JobFailedError if the job ends in error
or failed. A partial job counts as finished.
To come back to a job later, keep its id:
run = client.corrections.retrieve("6650f1c2e4b0a1d2c3f4a5b6")
To wait for several jobs at once:
jobs = [client.synopses.create(doc_id) for doc_id in doc_ids]
client.jobs.wait_all(jobs)
What you can launch
| Resource | Method | Result |
|---|---|---|
client.corrections |
create(doc_id, correction_types=[...]) |
findings, download() |
client.translations |
create(doc_id, language="french") |
result().content, download() for IDML sources |
client.translation_reviews |
create(original_doc_id=..., translation_doc_id=...) |
findings, download(format="docx" | "pdf") |
client.dossiers |
create(doc_id, kind="analysis" | "reading_report") |
result().content |
client.synopses |
create(doc_id, word_count=300) |
result().content |
client.content |
create("thread_x", doc_ids=[...]) |
result().content |
client.indexes |
create(original_doc_id) |
result().content |
client.epubs |
create(doc_id, title=..., author=..., language="es") |
download() |
client.ocr |
create(doc_id) |
download() |
client.ai_detection |
create(doc_id, detection_scope="standard", plagiarism_check=True) |
chunks(), plagiarism_findings(), download(format="docx" | "pdf") |
Lists are plain Python lists: the SDK encodes doc_ids, contributors,
excluded_domains, authors and subjects the way each endpoint expects.
Documents
client.documents.upload("book.pdf", title="Book", author="Author")
client.documents.upload(("guide.docx", data), title="House style", doc_type="guide")
client.documents.upload(file_url="https://example.com/book.epub", title="Book", author="Author")
# Text that is already digital needs no upload and is ready at once.
guide = client.documents.create_markdown(
title="House style", content="# Serial commas\n...", collection="guides"
)
for document in client.documents.iter(search="winter"):
print(document.id, document.title)
Uploads are free except PDFs, which cost 1 credit per 100 pages.
Conversations
conversation = client.conversations.create(document.id)
turn = client.conversations.send(conversation.id, "Where does the brother first appear?")
print(turn.assistant_message, turn.task_cost, turn.sources)
Turns answer synchronously and are charged by the text the assistant reads and writes.
Errors
import alighieria
try:
client.synopses.create(doc_id)
except alighieria.InsufficientCreditsError:
... # 402: top up or wait for the next reload
except alighieria.RateLimitError as error:
... # 429: error.retry_after seconds
except alighieria.APIStatusError as error:
print(error.status_code, error.code, error.message)
| Exception | Status |
|---|---|
BadRequestError |
400 |
AuthenticationError |
401 |
InsufficientCreditsError |
402 |
PermissionDeniedError, NoSubscriptionError, InactiveSubscriptionError |
403 |
NotFoundError |
404 |
ConflictError, TurnInProgressError |
409 |
PayloadTooLargeError |
413 |
RateLimitError |
429 |
InternalServerError |
5xx |
APIConnectionError, APITimeoutError |
no response |
All of them inherit from AlighieriaError.
Retries and credits
The SDK retries a request up to twice, and only when a repeat cannot charge you twice:
- every
429whoseRetry-Afteris at most 60 seconds; - failures to connect;
- timeouts and
5xxon reads, and oncorrections.createanddocuments.create_markdown, which are sent with an idempotency key.
Other launches and conversation turns are never repeated after a timeout or a
5xx: the first attempt may have started. Before launching again, look for the
job with client.jobs.list(source_id=doc_id).
Status polls have their own limit of 60 per minute. Lists and full reads
(result(), findings(), documents.list(), jobs.list()) share 10 per
minute, 30 per hour and 100 per day, so keep them out of tight loops.
client.rate_limit holds the limit headers of the last response.
Async
AsyncAlighieria has the same methods, awaited:
import asyncio
from alighieria import AsyncAlighieria
async def main():
async with AsyncAlighieria() as client:
job = await client.synopses.create(doc_id)
await job.wait()
print((await job.result()).content)
async for document in client.documents.iter():
print(document.title)
asyncio.run(main())
Configuration
client = Alighieria(
api_key="ak_...", # default: ALIGHIERIA_API_KEY
base_url="https://...", # default: ALIGHIERIA_API_URL, then production
timeout=60.0, # per request; conversation turns use 120
max_retries=2,
poll_interval=5.0,
max_poll_interval=30.0,
)
Support
The API reference shows the SDK call for every endpoint. For help, write to info@alighieria.com with the request time and the endpoint, and never include your API key.
Changelog
0.1.2 (2026-10-07)
OutputLanguage accepts basque: translations, dossiers, reports and content
can now be written in Basque.
0.1.1 (2026-10-04)
No code changes. The package page gains the logo, version badges, a support section and this changelog.
0.1.0 (2026-10-04)
First version. Covers every operation of the public API v1:
- Sync (
Alighieria) and async (AsyncAlighieria) clients. - Document uploads from a path, an open file, named bytes or a URL, and markdown documents.
- Corrections, translations, translation reviews, dossiers, synopses, marketing content, indexes, EPUBs, OCR and AI detection with plagiarism screening.
Jobwithwait(),result(),download()anddelete();jobs.wait_all()for several jobs.- Conversations with a processed document.
- Typed errors per status and per account
code. - Automatic retries only where a repeat cannot charge twice.
Metadata
Release files for alighieria 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| alighieria-0.1.2.tar.gz | 30.5 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| alighieria-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 65.7 kB
Release files / alighieria-0.1.2.tar.gz
| Download URL | alighieria-0.1.2.tar.gz |
|---|---|
| Size | 30.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
32d3034d5c2321d97146999a0e33348e7dce055d2ecd50ee35dcdef12ec0e027
|
|
BLAKE2b-256 checksum How to use checksums |
c2aa3ecf2ee3b145c1ff5e1017f0b28ffe6d63caf348ba7a5c20d190957af064
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency logRelease files / alighieria-0.1.2-py3-none-any.whl
| Download URL | alighieria-0.1.2-py3-none-any.whl |
|---|---|
| Size | 35.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3eec7133e6bea90183e674375139128a1cd2bb4c1a648a235efe1249d9d27e7a
|
|
BLAKE2b-256 checksum How to use checksums |
3b2fff8a3dd402f378e409a135ad635c6c43c82c4f76deec513d12b574cfe5d0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency logSecurity for alighieria 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for alighieria-0.1.2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.