Skip to main content
Docs

Search guides and API endpoints, for example “Idempotency-Key” or “submit job”.

    Tools · Cheminformatics & Structure

    Reaction Atom Mapper

    Atom-map reaction SMILES, check element, mass, and charge balance, report stereocenter changes, and extract reaction templates.

    Updated October 1, 2026

    On this page

    Prices, workflows, and method papersOpen in the app

    The Reaction Atom Mapper checks reactions before you rely on them. It works out which reactant atom becomes which product atom (atom mapping), confirms the reaction is balanced, reports what happens to stereocenters, and can extract reusable reaction templates. Use it to clean a reaction dataset, or to check reactions from Reaction Enumeration or Retrosynthesis. It validates reactions only: it doesn't predict products or plan routes. It runs on CPU.

    How it works

    • Mapping with RXNMapper, a transformer model that maps atoms without hand-written rules, with a confidence score per reaction. Set min_confidence to flag low-confidence mappings.
    • Roles: molecules are sorted into reactants, reagents, and products.
    • Balance: element, mass, and formal-charge differences between products and reactants (hydrogens included only with balance_hydrogens), and product atoms that map to nothing.
    • Stereochemistry: each tetrahedral center is created, destroyed, inverted, retained, or undetermined; double bonds that gain or lose E/Z are reported.
    • Templates (extract_templates): retro and forward templates extracted with RDChiral, up to max_templates.

    Inputs

    1 to 10,000 reactions, as a reaction_smiles list (reactants>reagents>products) with optional reaction_ids, or as a table. Tables can hold reaction SMILES in a column, or separate reactant, reagent, and product columns, so the provenance table from Reaction Enumeration and the routes table from Retrosynthesis work without changes.

    Outputs

    FileContents
    mapped.csvOne row per reaction: status (mapped, low_confidence, or rejected), the mapped SMILES, confidence, the balance differences, and stereo changes
    diagnostics.csvEvery problem found, as error, warning, or info, with a code such as parse_error, unbalanced_elements, or stereo_change
    templates.csvExtracted templates (when you asked for them)
    reaction_map_audit.jsonModel and software versions

    Reactions that can't be parsed are listed as rejected; the job carries on.

    Run it from the API

    Submit with Submit a job and the job_type below. Price it first with Estimate job reservation cost: submitting reserves that amount from your wallet, and the charge settles at the actual runtime.

    Reaction Atom Mapper & Balance Validator reaction-map

    Job type
    reaction-map
    Hardware
    cpu (default)
    Typical runtime
    5 min on CPU

    Payload

    Provide exactly one of: reaction_smiles, reaction_table.

    Payload fields
    FieldTypeDescription
    reaction_smiles[]string[]

    Limits: min items 1, max items 10000

    reaction_ids[]string[]

    Limits: min items 1, max items 10000

    reaction_tablestring | object[] | artifactRef
    reaction_columnstring

    Limits: min length 1

    id_columnstring

    Limits: min length 1

    min_confidencenumber

    Default: 0Limits: ≥ 0, ≤ 1

    balance_hydrogensboolean

    Default: false

    extract_templatesboolean

    Default: false

    max_templatesinteger

    Default: 1000Limits: ≥ 1, ≤ 10000

    Example

    from cognichem_client import CogniChem
    
    client = CogniChem.from_env()  # reads COGNICHEM_API_KEY
    payload = {
        "reaction_smiles": ["CC(=O)O.OCC>>CC(=O)OCC.O", "CC(=O)Cl.NCC>ClCCl>CC(=O)NCC"],
        "reaction_ids": ["esterification", "amide_coupling"],
        "extract_templates": True,
        "max_templates": 10,
    }
    
    estimate = client.jobs.estimate(job_type="reaction-map", payload=payload, resource="cpu")
    print(f"Reserves ${estimate.cost:.2f}")
    
    job = client.jobs.submit(
        job_name="my-reaction-map-run",
        job_type="reaction-map",
        payload=payload,
        resource="cpu",
    )
    status = client.jobs.wait(job.process_id)
    if status.status == "completed":
        client.jobs.result(job.process_id, save_path=".")

    Sample data from the job catalog; long values are shortened here. Each job_name must be unique among your jobs.

    Workflow inputs

    • Table (list)CSV, JSON

    Workflow outputs

    • ArchiveZIP
    • TableCSV
    • TableCSV
    • TableCSV