Changelog
Python SDK version history. Tracks the `symagedocs` package on PyPI.
This page tracks the Python SDK. Versions correspond to sdk-vX.Y.Z git tags.
v1.0.7 Latest
September 24, 2026
Added
- Dataset card download — The job's dataset card can now be downloaded on its own via
generate.download_readme(job_id, path=".")(served byGET /v1/jobs/{job_id}/dataset/readme); with a directory path it writesREADME_<job_id>.md, job-scoped so it can't overwrite your ownREADME.md.download_dataset()still writes the same content as a plainREADME.mdinside its own, already job-scoped, output directory (STAX-2402). created_viaon the manifest —manifest.jsongains a top-levelcreated_viafield ("api_key"or"web_session") recording how the job was submitted; absent on jobs created before the field existed (STAX-2430).- Generator provenance on every manifest —
manifest.json(top-level, in-archive, and every shard fragment) now carries ageneratorblock —git_shas,render_versions,finalizer_git_sha,scope(always"dataset"), andstamps_seen/stamps_unreadable/guard_keyrecording how strong that evidence is — as advisory evidence of which build produced a dataset. Exposed in the SDK asDatasetManifest.generator/DatasetManifestGenerator(STAX-2514). warningson job creation and pricing estimates —CreateJobResultandPricingEstimatenow carry awarningslist. A fraud preset whose raster scenarios can't be delivered by the job's output formats or degradation profile is still accepted and priced normally, with the dropped scenarios reported here instead of only after the fact inmanifest.fraud.scenarios(STAX-2572).- Failed items are redrawn instead of failing the whole job — An item whose draw hits one of a defined set of per-draw failures is now retried up to three more times on a deterministic sub-seed instead of failing the entire job; an item that still fails after four draws is skipped rather than delivered incomplete. Every job's
manifest.jsonnow always carries anitem_drawsblock (redrawn_items,failed_draws,skipped_items,skipped[], …) — all-zero on the common case, so "nothing was skipped" and "this bundle predates the field" never read the same. A skipped item still counts against the credits charged, so compareitem_draws.skipped_itemsagainst the orderedquantityto see what actually shipped. The job still fails outright if skips, or one failure class, cross a systemic rate (STAX-2554).
Changed
- Shard fragment
schema_versionbumped to1.1.0— Each shard'sshard_manifest.jsongained thegeneratorkey above, so its declaredschema_versionmoves from1.0.0to1.1.0; a consumer pinned to1.0.0should accept1.1.0. The top-levelmanifest.json's ownschema_versionis unchanged — the block is additive there (STAX-2514). - 404 message for a job in another account — A job belonging to a different account now returns
404 code=job_not_foundwith the message"Job not found in this account", the same 404 a nonexistent job id gets, so a 404 never leaks whether the job exists elsewhere (STAX-2430).
Fixed
- Fraud and statement config validated before the credit debit —
generate.create()andpricing.estimate()now check thefraudandstatementconfig blocks up front: an out-of-range value, an unknown preset, a form the block can't apply to, afraudblock combined with a multi-statement packet (statement.sequence_length > 1), and everything the generator itself would otherwise refuse is now rejected at submission with422 code=invalid_fraud_configorcode=invalid_statement_config, instead of being accepted and charged and only failing partway through generation (STAX-2383, STAX-2542). list_jobs(status=...)returns 422 instead of 500 for an unrecognized value — Thestatusfilter onGET /v1/jobsis now a typedLiteralof the eight accepted job statuses; an unrecognized value returns422naming the accepted values instead of a server error (STAX-2413).coherence_mode="shuffled"withquantity <= 1rejected — A single-item job previously acceptedshuffledsilently and produced ordinary coherent output (a one-item shuffle is the identity); the API now rejects the combination with400 code=invalid_coherence_mode(STAX-2239).- Undeliverable fraud scenarios in an explicit list now refused before charge — An explicit fraud
scenarioslist naming a raster recipe that the job's output formats or degradation profile can't deliver was previously accepted and silently dropped the scenario; it's now refused with422 code=undeliverable_fraud_scenarios, naming the affected scenarios, before the credit debit (STAX-2572). - Mixed render-build evidence now fails the job, with a full refund — The stamp listing that builds a dataset's
generatorblock is now taken once, after the archive's downloads, and that same listing feeds every copy of the block for one dataset — the in-zip manifest, the top-level manifest, and every shard fragment. Publishing it is now a claim only one finalizer can hold at a time, so in normal operation the copies agree; a stalled finalizer can still lose that claim to a peer, and an operator restart of an in-flight job can still publish unfenced. If the listing finds genuine evidence of more than one render build (which an earlier, pre-download check can miss), the job now fails with a full refund instead of completing and shipping the inconsistency (STAX-2566). - A retried item's identity could collide with a neighboring item's — An item identity retry could land on the same seed as a later item's first draw, so the two could print the same person. Retries are now seeded independently;
manifest.json'sgeneration_params.identity_seed_versionrecords which scheme a job used ("legacy"marks a job generated before this fix, so it can be told apart from one confirmed collision-free) (STAX-2564). - Private forms are no longer readable or generatable without an entitlement —
forms.get(form_id)andgenerate.create()previously returned or accepted any form by id regardless of visibility, so a private form's schema — and, viagenerate.create(), its filled output — was reachable by any read-scoped key that knew or guessed the id. A private form now requires your account to be linked to it; an id you aren't linked to returns the same 404 /unknown_formas one that doesn't exist (STAX-2213). - Job-launch failures no longer keep the charge — A failure launching a job after the credit debit (for example a webhook subscription-cap rejection, or an internal error before generation starts) now refunds the debit and returns
502instead of silently keeping the credits. A malformedwebhook_urlpassed togenerate.create()is now rejected with400before any debit happens, rather than being debited and refunded through the failure path (STAX-1198).
Documentation
- Corrected the dataset-split allocation, bank-statement row-value, and item-seed derivation/spacing documentation in the API manual and SDK README to match actual generator behavior; no output or SDK-surface changes (STAX-2427, STAX-2437, STAX-2440, STAX-2442).
- Documented that
generate.list_items()andgenerate.download_item()are not subject to the 48-hour download window every other download endpoint has; they follow the underlying files' 7-day storage lifecycle instead (STAX-2588).
v1.0.6
August 6, 2026
Fixed
- Empty
LICENSEin the published wheel — The MIT license file shipped inside everysymagedocswheel fromv1.0.0throughv1.0.5was zero bytes, so the package declaredLicense :: OSI Approved :: MIT Licensewhile distributing no license text at all. The full MIT text is now present (STAX-2286). - Retired form ids in the README and example scripts — The quickstart and the shipped examples still used pre-migration form ids such as
irs_w2_2025andirs_f1040_1988. Those only worked through a server-side alias table and never appeared informs.list(); the documentation now uses the canonical ids (irs_w2_single_page_2025,irs_f1040_classic_1988), and a drift test fails the suite if a retired id comes back (STAX-2286).
v1.0.5
June 15, 2026
Added
- Sharded dataset packaging — Jobs under 2 GiB uncompressed continue to produce a single
dataset.zip; larger jobs now produce apreview.zipplus boundedshards/shard_N.zipfiles, lifting the previous single-archive ceiling (STAX-1730). bundle_layoutonJobSummary— TheGET /api/v1/jobslist endpoint and the SDK'sJobSummarymodel now includebundle_layout, so callers can distinguish single-layout from sharded jobs without a second detail fetch (STAX-1766).- Form
tagsfield — Forms now carry an additivetags: list[str]field for multi-category filtering; the existingcategoryfield is unchanged andtagsdefaults to[category]for all existing forms (STAX-1963).
Changed
- Manifest
annotation_coveragerename — The sharded top-level manifest field previously namedformat_coverageis nowannotation_coverage, more accurately reflecting that the values describe annotation kinds (e.g.funsd,bio,yolo,coco) rather than output file formats (STAX-1733). - Canonical job serialization — The public
/api/v1/jobslist and detail responses are now emitted from a single shared serializer, eliminating field drift between the list and detail surfaces and between the server and SDK models (STAX-1992).
Fixed
- Dataset endpoints returning 404 — The manifest, preview, annotations, and shards endpoints added in STAX-1730 were mounted only on the internal router; they are now correctly delegated through the public
/api/v1surface, sodownload_dataset()and related SDK calls no longer 404 (STAX-1734). - Dataset-level annotations dropped in sharded mode — Sharded jobs were missing donut metadata splits, COCO surface splits, and YOLO
classes.txt/data.yaml/ split lists; the dataset-level annotation post-processing step now runs for all job layouts (STAX-1731, STAX-1732). - Unknown
output_formattokens rejected at submission — Values such as bare"png"(canonical tokens are"png_typed"/"png_handwritten") previously passed validation, persisted on the job row, and produced zero output files; the API now returns a validation error at submission time (STAX-1764). - PNG output without a matching PDF rejected at submission — Submitting a PNG-only
output_formatslist via the API or SDK previously produced a successful-looking job with zero images emitted; the validator now requires a matchingpdf_*token to be present (STAX-1746). - Invalid output-config values rejected at the API boundary — Several job-config fields (including
yolo_mode) previously accepted malformed values, silently coerced them to a default, and emitted mislabeled output; they are now rejected at submission with an explicit error (STAX-1924). - Dataset CSV
item_indexjoin key — Theground_truth/data.csvemitter was omitting a usable join key, making per-row linking to annotation files unreliable;item_indexis now correctly populated (STAX-1913). - COCO/YOLO bounding-box coordinates under geometric degradation — COCO and YOLO bboxes were emitted in pre-augment pixel space and never reprojected through the per-page transform sidecar, causing coordinate drift of roughly 28 px, ~1°, and 2–3% scale under Scanned/Faxed/Phone-Photo degradation modes;
images[].widthandimages[].heightin COCO now reflect actual rendered dimensions (STAX-1882, STAX-1883, STAX-1884). - Stale SDK example scripts — Two of the four shipped example scripts referenced the old
"bundle"download format (renamed to"dataset"in STAX-1730) and used incorrect client symbols; all examples now match thev1.0.5SDK surface (STAX-1994, STAX-1976). - Server-authoritative job cancellation — The cancel API now drains the in-flight SQS message and completes the cancel finalizer — including credit refund — before returning, so the response reflects
status: CANCELEDimmediately rather than leaving the job inCANCELINGindefinitely (STAX-1709).
v1.0.4
May 15, 2026
Added
- Webhook management — The full webhook lifecycle is now SDK-callable: create, list, and delete webhooks via
/api/v1/webhooks; payloads are signed with HMAC for verifiability, and a per-user cap of 20 active webhooks is enforced server-side (STAX-1576). - Locked SDK dependencies —
sdk/python/poetry.lockis now committed, giving installers a fully reproducible dependency closure.
Fixed
- Parallel rendering restored — Multi-PDF-format and non-coherent bulk jobs were silently clamped to 1 worker regardless of available cores since
v1.0.2; the subprocess worker now iteratespdf_formatsand honourscoherence_mode, restoring full parallelism (STAX-1707).
v1.0.3
May 12, 2026
Changed
- Single-sourced
__version__—symagedocs.__version__now reads fromimportlib.metadatainstead of a hard-coded literal, eliminating tag/version drift (STAX-1635, STAX-1563).
v1.0.2
May 8, 2026
Added
- Idempotency + cancel on
client.generate— Generation jobs accept an idempotency key and can be cancelled mid-flight; per-request quantity cap was lifted (STAX-1600). - Typed augmentation kwargs — Augmentation knobs are surfaced as typed SDK keyword arguments, kept in sync with the backend via a drift test (STAX-1524).
- Single-bundle downloads — One bundle per job replaces per-format zips; downloads redirect to presigned S3 URLs (STAX-1414, STAX-1416).
- Always-on per-file JSON/CSV in bundles — Bundles now always include per-file JSON and CSV as foundational ground truth (STAX-1462).
- Donut ML output format — Behind the
ml-output-formats-enabledflag at the API boundary (STAX-1349).
Changed
- SDK parity with public API — Closed gaps so every documented public endpoint has a corresponding SDK method (STAX-1523);
BioTokenaccepts the currenttagpayload (STAX-1528); end-to-end ML training parity for batch flows (STAX-1520, STAX-1521, STAX-1522). - Async bundle build — Bundle assembly moved off the request path to prevent 504s on 1K-item batches (STAX-1541).
- Form catalog rename —
irs_w2_2024renamed toirs_w2_2025to match the 2025 PDF template (STAX-1479). - Validation moved server-side — Statistical validation runs in worker finalize;
/validateis no longer exposed as an OOM vector (STAX-1438).
Removed
- Legacy
/api/v1/batches/*surface — Batch operations consolidated onto/jobs. Useclient.generatewith idempotency keys instead (STAX-1600).
v1.0.1
April 24, 2026
Added
- Multi-form coherent generation — Generate multiple forms for a single coherent identity (e.g. W-2 + 1040 for the same person) via the public
/generateendpoint (STAX-1170). - Initial Batch API + presigned downloads + webhooks — Batch endpoints under user-level
sk_live_*keys with cursor pagination, presigned S3 download URLs, and HMAC-SHA256-signed webhook events (job.completed,job.failed,batch.completed,batch.exhausted). Note: the dedicated batches surface was removed in v1.0.2; useclient.generate.
v1.0.0
Released March 25, 2026
Initial public release of the symagedocs Python SDK.
Added
- Synchronous and async clients —
ClientandAsyncClientwith resource-style namespaces (forms,generate,identities,tabular,account,pricing). - Bearer authentication — User-level API keys with the
sk_live_prefix; created in the web app account portal at/account?tab=api. - Typed exceptions —
AuthenticationError,PermissionDeniedError,NotFoundError,ConflictError,InsufficientCreditsError, etc., one per HTTP status. - Automatic retry — Exponential backoff on
429and5xxresponses. - Convenience helpers —
wait()for job polling,iter_training_examples()for ML consumers,download_urls()for presigned-URL handling. - Optional
[progress]extra — Addstqdmprogress bars for long jobs.