Docs / Optional Automation

Let your application verify the conversation

Your application already knows which order it received and which invoice it sent. It can now attach those ModernEDI transactions to a scenario run, check the result, and retain the evidence. Operators see that same run in the browser.

One scenario engine, two ways to use it.

Use the browser to author and inspect; use the Integration API when repeatable automation is useful. Mappings remain sufficient to exchange EDI. Neither scenarios, Git, nor a CI pipeline are required to get started.

Choose what the application may do

In the workspace's Integration API keys section, give the key a recognizable label, select its Allowed API access, and choose Create integration API key. Copy the one-time value directly into your server's secret store. Do not paste it into scenario JSON, Git, browser code, or logs.

Read scenario runs — scenario-runs:read
List runs, read current state and operation timelines, and download terminal evidence reports. A reporting application can use this alone.
Operate scenario runs — scenario-runs:write
Start a run, attach or refresh a persisted transaction, advance evaluation, or cancel a run. Add Read scenario runs for polling and reports; neither permission implies the other.
Send messages — messages:write
Also required when an advance actually sends EDI, including a ModernEDI test partner sending into your workspace. An observation-only workflow needs no send permission. The API reuses the same authenticated key; it does not ask for a second key.
Configuration and transaction access remain separate
Use configuration:read to discover configuration and configuration:write to apply changes. Use transactions:read if the application must search transaction history for IDs. None is required merely to operate a known applied binding with known transaction IDs.

Traffic selection is not a permission boundary. These scopes cover both Test and Production in this workspace. Choosing a Test binding does not create a Test-only credential. Both traffic environments share deployed mappings; documents and evidence remain in the binding's selected environment.

For a browser-led workflow, choose your applied binding and parameters in Implementation verification, expand Automate this run, and choose Copy API start request. You do not need to start a browser run first. The request includes the server's definition and binding snapshot hashes, not a credential. Repeat this after applying a new binding revision. For a fully automated apply-to-run workflow, use the selection endpoint below. Configuration export provides portable source files, not a replacement for these frozen runtime selectors.

From configuration apply to a run, without a browser

Prefer the browser? In Change history → Conversations in this change, Review new run checks the same apply-to-run authority and opens the existing start form. It needs no Integration API key and does not start or send anything. Review the exact revision, traffic environment, and parameters, then explicitly start when ready.

Suppose your repository contains a binding whose source metadata.id is order-invoice-test. After your reviewed apply, keep its operationId and wait for that operation to reach SUCCEEDED. Then ask for that binding in that exact applied configuration:

GET /v1/configuration/apply-operations/{operationId}/scenario-run-selections/order-invoice-test

This read requires configuration:read. The binding ID is the one you authored, not its display name or the configuration resource's UUID. The response's selection is a start-request body with the definition, environment, and exact applied binding revision and hash. Add any declared parameters, then persist that final body and a new run Idempotency-Key before calling POST /v1/scenario-runs. Defaults still come from the definition; the endpoint does not invent parameter values.

The apply is still publishing
409 configuration_apply_pending means wait, honor Retry-After, and poll with a bounded deadline. The database change is already committed; do not submit a new apply just to wait for publication.
The workspace changed after that apply
409 configuration_snapshot_changed prevents automation from silently testing a newer configuration. Review the change and choose the intended apply again. This compares the complete configuration, including mapping tests, not only the runtime revision number.
The binding's frozen inputs are stale
409 scenario_binding_not_current asks you to review and refresh the binding. Missing, retired, or reserved browser-managed bindings return no selection. Never calculate a replacement runtime hash from the source file.

A no-op apply can select an unchanged binding; the binding need not have been created by that operation. Discovery does not start a run, send a message, or reserve the workspace. Run admission rechecks the binding and its referenced configuration; an unrelated edit after discovery need not block start. Runtime availability and required parameters are still checked when you start. A selected binding is not a passed scenario, nor proof of the entire configuration bundle.

In TypeScript, call modernEdi.configurationAsCode.getConfigurationScenarioRunSelection({ operationId, bindingId }), then pass the returned selection to modernEdi.scenarioRuns.startScenarioRun. Any server-side HTTP client can use the same workflow.

An order-to-invoice workflow

  1. Author and apply once.Use the browser scenario workflow to bind the order and invoice steps to your partners, maps, and fact expressions. Configuration as Code can perform the same reviewed apply. Give your application the exact definition identity/hash and applied binding ID, revision, and snapshot hash. An authored file's hash is not a substitute for the applied binding snapshot.
  2. Start a run for one conversation.Call POST /v1/scenario-runs with those exact selectors, the matching test or production environment, and any declared parameters. Include a unique Idempotency-Key. Keep the returned run ID, ETag, and request ID. Starting does not send EDI; adapter preparation may check or prepare its managed runtime dependencies. The reserved browser-managed binding is not a public selector: apply your own binding, optionally using a managed example.
  3. Attach documents the system actually processed.Call POST /v1/scenario-runs/{runId}/observations with stepId, occurrence, messageId, and transactionKey. Supply the current If-Match ETag and a new Idempotency-Key. Send IDs, not raw X12 or claimed facts. ModernEDI loads authoritative transactions and checks traffic environment, partner, map, timing, and frozen configuration. An old transaction from before the binding was applied may be ineligible.
  4. Follow the run's guidance.Attach or refresh eligible occurrences; use POST /v1/scenario-runs/{runId}/advance with an empty object to evaluate pending evidence/deadlines or advance the next adapter-controlled step. Only actual dispatch needs Send messages. The response's retry.requiresApiKey describes a browser supplemental credential, not an exemption from API send permission. Adapter-controlled occurrences cannot be replaced by client attachments.
  5. Inspect and keep the result.Use GET /v1/scenario-runs/{runId} for current state and its ETag. A waiting run is not a pass. Inspect checks and the paginated /timeline; after completion or cancellation, download /evidence-report. The report identifies the frozen configuration and the member or API key that performed each recorded operation, without exposing the credential.

Run history is bounded by the platform's documented operation, idle-expiry, and retention limits. Poll with a bounded deadline and backoff, honor Retry-After, and paginate using the opaque nextCursor unchanged. Cancel abandoned work with POST /v1/scenario-runs/{runId}/cancel, an empty object, current ETag, and a new idempotency key. Cancellation preserves gathered evidence and produces an inconclusive result.

A retry is not always another attempt

You lost the response
Repeat the exact body, original If-Match, and original Idempotency-Key with the same API key identity. ModernEDI returns that caller's original result instead of duplicating a send. Rotating to a different key creates a different idempotency namespace; first inspect the known run and timeline.
The server recorded a failed attempt
Reusing its idempotency key replays the failure. If the failure is retryable, honor its delay, reload the run, and use its current ETag and a fresh idempotency key to attempt the action again. Do not blindly retry every conflict.
Someone else changed the run
A 412 etag_mismatch or in-progress conflict asks you to reload and reassess. Another browser user or API caller can operate the same workspace run. Never fabricate or weaken the ETag.
The key lacks permission
A 403 insufficient_scope is not a transient outage. Grant only the necessary permission, or use an observation-only workflow. Revoked or invalid credentials return 401.

Errors use the standard Integration API envelope: error.code, error.message, error.retryable, error.requestId, and error.details. Conflict details may include currentEtag and the current run. Log the safe request ID for support, not credentials or document bodies.

Preserve the report, not a reserialized approximation

The terminal evidence endpoint returns the same persisted JSON bytes on subsequent downloads. Its X-Content-Sha256 header hashes those exact bytes; its ETag is that hash in quotes, not a run-revision ETag. Save the original response body and hash together. Parsing and reserializing JSON can change the bytes even when the data looks identical. A report proves the recorded conversation against that binding; it does not certify all future traffic or your wider implementation.

How this fits with reviewed configuration

Saved mapping tests and /v1/configuration/verification-runs test proposed configuration before apply without sending EDI. Scenario runs test real persisted traffic against an already applied configuration. Use both when useful: review and test a map change, apply it, then run a conversation against the new binding revision. A pass for an older revision does not carry forward. Git stores configuration, not run evidence or API secrets.

The official SDKs expose these operations through scenarioRuns in TypeScript, scenario_runs in Python, and ScenarioRuns in .NET. TypeScript's *Raw() methods and the Python/.NET response wrappers retain headers and exact report bytes. Any server-side HTTP client can use the same routes; no separate scenario CLI or repository provider is required.

Integration API operations and typed request schemas · Scenario authoring reference · Optional Git workflow