Skip to main content

syntheticcfo - Python client

synthetic cfo generates SAP and Oracle ledgers from accounting rules, with fraud planted, every planted record written down at the moment it is planted, and innocent look-alikes beside nearly every scheme, so fraud detection can be trained and measured without a single real record. Three schemes are closed sets by design, with no look-alike planted: segregation of duties, the ghost vendor and phantom inventory, where the join or the reconciliation that finds them is the real analytic and every match is a genuine exception.

This client generates that data, for SAP ECC, SAP S/4HANA and Oracle Cloud, from a script, a notebook or one command. Every dataset it generates is a four-layer package with its labelled fraud answer key (a blind-track dataset keeps part of the key sealed on the platform for scoring) and a reproducibility certificate that names the engine version and lists the SHA-256 of its files: the same seed and configuration on the same engine version reproduce the package byte for byte, and on another engine version they can build a different dataset. A dataset with purchase to pay, order to cash, payroll, inventory or fixed assets also carries articulated financial statements. No language model ever generates the numbers.

The client has no dependencies beyond the standard library:

pip install syntheticcfo

That installs the client and the syntheticcfo command. If your network blocks the package index, the platform serves the current wheel itself; the exact command is on https://app.syntheticcfo.com/evaluate.

Or, since it is one file, take it directly and drop it anywhere:

curl -O https://app.syntheticcfo.com/sdk/syntheticcfo.py

An account and a key

A free account needs no card: all three platforms and the core four cycles, within the free plan's limits on scale and on datasets a month, which https://app.syntheticcfo.com/evaluate states. Make one at https://app.syntheticcfo.com/?signup=1, then create an API key under Account, API access. The key carries your plan and monthly allowance. It cannot manage your account, read your chats or create more keys.

One command

syntheticcfo generate --key scfo_YOURKEY --platform oracle --industry retail --fraud high --rows 600

It builds the world, waits, and saves the package zip where you stand. python -m syntheticcfo does the same thing everywhere.

Command What it does
syntheticcfo generate builds a world, waits, and saves the package zip
syntheticcfo download JOB_ID waits for a job if it is still building, then saves its package
syntheticcfo reproduce JOB_ID runs a job again with its seed and configuration, then saves the new package
syntheticcfo score JOB_ID FILE grades your detector's flagged record ids (a file, or - for standard input) against the job's answer key
syntheticcfo me shows the account the key belongs to: plan, this month's generations, limits
syntheticcfo jobs lists your recent generations, with the engine each ran on and what Reproduce would do

Every command takes --key (or reads SCFO_API_KEY); generate, download and reproduce also take --lab and --out. generate also takes:

Option What it sets
--platform SAP_ECC (the default), SAP_S4HANA or ORACLE, plain words like oracle work; or a combined environment, SAP_MIGRATION_PAIR or INTERCOMPANY_GROUP, on the Team plan and above
--modules the cycles, any of P2P O2C CE R2R HR MM FA (default: the core four, P2P O2C CE R2R)
--industry TMT (the default), PHARMA, MANUFACTURING, FINANCIAL_SERVICES or RETAIL
--fraud none, low, medium (the default) or high
--rows the scale: base transactions per cycle, the setting the plans call rows (not a count of the rows the tables end up holding), up to your plan's limit (syntheticcfo me shows it). A value outside the platform's range is first brought into it; a value then above your plan's limit is refused with a message naming the limit. Left out, the world takes the standard volume; when your plan allows less, as the free plan does, it is sized at your plan's limit instead and the command prints the platform's note saying so
--jurisdiction a country code such as US, DE, ZA or JP (syntheticcfo generate --help lists them)
--seed any integer; the same seed and configuration on the same engine version rebuild the world byte for byte (on another engine version they can build a different dataset). Left out, a fresh one is drawn and printed at the end
--years 1 for a single year; 2 to 5 for a multi-year arc on the Team plan and above (3 at most on the intercompany group; the migration pair is one year)
--evaluation-mode withholds the ground-truth marker columns and moves the annotations out of the shipped data
--lab also saves the JSON-lines lab export: one file per table, the answer key and the dataset card
--out the folder or file path for the downloads (default: where you stand)

From Python

from syntheticcfo import Client

c = Client(api_key="scfo_...")            # or set the SCFO_API_KEY env var
me = c.me()
print(me["plan"], me["generations"])      # your plan and this month's generations

job = c.generate(
    platform="ORACLE",                    # SAP_ECC | SAP_S4HANA | ORACLE
    industry="RETAIL",                    # TMT PHARMA MANUFACTURING FINANCIAL_SERVICES RETAIL
    fraud="high",                         # none | low | medium | high
    rows=600,                             # the scale, up to your plan's limit: me["caps"]["max_rows"]
    modules=["P2P", "O2C"],               # subset of P2P O2C CE R2R HR MM FA
    jurisdiction="ZA",
    seed=42,
    wait=True,                            # poll until the package is built
)

package = job.download("out/")            # the four-layer audit package (zip)
lab = job.lab_export("out/")              # JSONL tables + answer_key.jsonl + dataset card
print(job.insights())                     # what was planted, by control

generate also takes volume_tier, company_code (the SAP company code on every document; the intercompany group keeps its subsidiaries' own codes), region, size_band, fiscal_year, years, entropy, fx_share and blind (the blind evaluation track, Team plan and above). What the platform says when it accepts a request, such as the scale it chose when no row count was given, is on job.notes and printed unless quiet=True.

For model evaluation, add evaluation_mode=True: the shipped database and workbooks then withhold the ground-truth marker columns, and the annotation layer moves to 01_Audit_Evidence beside the answer key, so no column names a scheme on its own rows. The answer key itself ships in full. A scheme built on one account (phantom revenue on an invented customer) is still isolated by that account once a detector finds it.

Score a detector

flagged = my_detector(lab)                # your detector's record ids, as the tables spell them
result = job.score(flagged)               # graded against this job's answer key
print(result["precision"], result["recall"], result["f1"], result["grade"])

A flag is a record id as the answer key spells it: a document number, or a composite such as 4500000123/10 for a purchase-order line, which also matches on the purchase order alone and never on the line number alone. On a multi-year arc, FY2024:4500000123 grades a flag inside that year; a bare id counts in every year that labels it. job.score(text=...) takes ids separated by newlines, commas or spaces, or a CSV with a record_id column (a fiscal_year column beside it names the year on an arc), as syntheticcfo score does. A file of that one column works too: the client leaves its header line out of what it sends. The result carries precision, recall, F1, the grade, the counts and recall per scheme. More on reading a score: https://app.syntheticcfo.com/evaluate

Reproduce

print(job.reproduce_note)                 # what Reproduce will do, before you call it
again = job.reproduce(wait=True)          # the same seed and configuration, as a new job

On the engine version the original ran on, Reproduce uses no generation and, for a job that completed, rebuilds the same files. On another engine, or when the platform has no record of the original's engine, the same seed and configuration build a new dataset (its certificate names the engine), which counts as one generation on a metered plan. The platform's note on the new job says which. A job from before the platform stored configurations cannot be reproduced; the platform refuses it and says why.

Notes

  • Plan limits apply exactly as in the app. A request for a module, platform or feature your plan does not include is refused with a 402 naming what is missing. A scale outside the platform's range is first brought into it, without a note; a scale then above your plan's limit is refused with a 402 naming the limit. A request with no row count takes the volume tier's size (the standard tier's unless volume_tier names another); when that size is more than your plan allows, as the standard tier's is on the free plan, it is sized at your plan's limit instead and the platform says so. Once the month's generations are spent, a request that would use one is refused the same way until the allowance resets on the 1st; the generate request that leaves a single generation for the month carries a note saying so.
  • A generation that fails, or that a server restart interrupts, refunds its metered credit automatically. A generation you cancel still counts toward the month on the free plan.
  • The client is MIT licensed (the LICENSE file in the package). Datasets generated on the free plan are for evaluation and non-commercial use and may not be redistributed, resold, or used to train or evaluate a competing product; commercial use needs a paid plan. The free public sample carries its own licence: Free for evaluation and non-commercial research, including publishing results on it with a citation. Not to be redistributed as files, resold, or used to train or evaluate a competing product. Full terms: https://app.syntheticcfo.com/terms

Metadata

Release files for syntheticcfo 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for syntheticcfo 0.2.2
File Size Uploaded Provenance Actions
syntheticcfo-0.2.2.tar.gz 16.4 kB With provenance Details for syntheticcfo-0.2.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for syntheticcfo 0.2.2
File Interpreter ABI Platform Actions
syntheticcfo-0.2.2-py3-none-any.whl Python 3 none any Details for syntheticcfo-0.2.2-py3-none-any.whl

Total release size: 34.2 kB

Release files / syntheticcfo-0.2.2.tar.gz

Download URL syntheticcfo-0.2.2.tar.gz
Size 16.4 kB
Tags Source
SHA-256 checksum
How to use checksums
00a5287d84af60cd913b0d548555e484bcb2e8c72c2106a286fe2769e9c368d8
BLAKE2b-256 checksum
How to use checksums
a04ffafbc3e2c0f3e462031bd716f48db1e517cb87a47e73881e3a90c8b79cfe
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 20, 2026.

Transparency log

Release files / syntheticcfo-0.2.2-py3-none-any.whl

Download URL syntheticcfo-0.2.2-py3-none-any.whl
Size 17.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ef7b71992d0fd25a818d3d8e872d7c41ca4e075febedd9c49578c9da21ddc378
BLAKE2b-256 checksum
How to use checksums
9b65f5b24635a3c68994b1add24c6f04251ceef1b67cd3e4d5fcd293ea3ae4c3
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 20, 2026.

Transparency log

Security for syntheticcfo 0.2.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

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for syntheticcfo-0.2.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 20, 2026.

Transparency log

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

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page