Seed format reference

A seed is a JSON file containing a world's starting data and logical time. Reuse a seed to run the same test from the same starting point.

On this page

Create starting data from a template or import in the dashboard, or write a seed file directly. Validate a file before using it:

worlds seed validate my-seed.json

Choose the connector profile

Profile Where records live Task format
Stripe data.customers, products, prices, invoices and subscriptions Version 1 billing tasks
Native Zendesk Top-level zendesk object Version 2 support tasks
Stripe and native Zendesk together Both of the above Version 2 with explicit billing authority
Legacy ticket desk data.tickets, usually beside Stripe records Version 1

Native Zendesk and the legacy desk cannot coexist in one seed. Stripe's implemented subset has real-API verification; native Zendesk has local conformance coverage, with live qualification pending. See connector scope.

Top level

This is a valid empty starting world:

{
  "name": "my-seed",
  "version": 1,
  "epoch": 1767225600,
  "clock_mode": "manual",
  "data": {}
}
Field Required Meaning
name Yes Lowercase letters, digits and hyphens; starts with a letter or digit
version Yes Integer of at least 1; independent of the tasks file's version
epoch Yes Nonnegative Unix seconds; the world's starting logical time
data Yes Stripe and legacy record arrays; omitted arrays default to empty
zendesk No Native Zendesk profile
clock_mode No manual (default) or auto
auto_tick_seconds No Positive integer; defaults to 1

With a manual clock, time moves through worlds clock advance or the admin API. Auto mode also advances by auto_tick_seconds on eligible API requests. Authentication, injected failures and preflight refusals do not tick; see logical clock behavior.

Loading a seed emits no events or webhooks. The world records the parsed seed's canonical-JSON SHA-256 as seed_hash; generated record IDs derive from that hash and world counters. See determinism.

Native Zendesk records

The zendesk object contains version: 1, principal_id and arrays for users, groups, organizations, memberships, tickets, comments and audits. Start from the bundled zendesk-support-v1 example in the dashboard, or an offline import. To inspect the bundled JSON, use GET /admin/seeds/zendesk-support-v1 on your local server; see the Admin API.

Native IDs and references are positive safe integers. The principal must be an active, nonsuspended agent or admin. Directory membership, assignment, comments and audit history are validated together; copying ticket rows alone is not sufficient.

In the beta.4 candidate and current source checkout, native timestamp chronology uses the full accepted ISO instant, including fractional digits beyond milliseconds and equivalent timezone spellings. The frozen published 0.9.0-beta.3 and published beta.1/beta.2 archives predate this validation fix and compare native seed timestamps at millisecond precision. Supplied creation and update times must be at or before the epoch; update must not precede creation. Omitted creation defaults to the epoch and omitted update to creation. A comment and its owning audit must have equal instants. Original timestamp strings survive export and reload.

The native scope documents supported behavior. Source checkouts also include the complete native seed schema for contributors.

Logical closure and follow-up metadata

Optional zendesk.lifecycle.closure enables simulated closure:

Field Accepted value
after_hours Integer from 1 to 672
sweep_phase_seconds Integer from 0 to 3599
author_id Existing native agent or admin

Omitting closure adds no defaults. Tickets may declare solved_at (ISO instant or null) and via_followup_source_id (native ticket ID). Audits may declare via_channel as api or rule.

For closure-enabled solved tickets, created_at <= solved_at <= updated_at <= epoch. Ticket, comment and audit history must not extend beyond the derived closure boundary. Active unsolved tickets require absent or null solved_at; closed tickets may retain the solve episode.

A follow-up source must exist, be closed and be no newer than its child. Equal creation times are valid; self-references and ancestry cycles are rejected.

These fields survive export and reload. Read closure timing and limits before using them to model a workflow.

Stripe records

Stripe seed records use explicit prefixed IDs: cus_, prod_, price_, in_, ch_ and sub_. References must point to records in the same seed.

Amounts are integer cents. Where supported, created_offset is a nonnegative number of seconds before the epoch; a larger value means an older record.

Stripe record fields and examples

data.customers[]

Field Type or default
id Required, unique cus_...
name Required string
email Valid email or null; defaults to null
description, phone String or null; default null
balance Integer cents; default 0
metadata String-valued object; default {}
created_offset Seconds before the epoch; default 0

data.products[] and data.prices[]

Record Required fields Optional fields
Product id (prod_...), name description, active (default true), metadata
Price id (price_...), product, unit_amount currency (default usd), nickname, recurring, active, metadata

The price's product must exist. unit_amount is nonnegative. recurring defaults to null for a one-time price; subscriptions require a recurring price:

"recurring": { "interval": "month", "interval_count": 1 }

Intervals are day, week, month or year. interval_count is a positive integer, defaulting to 1.

data.invoices[]

{
  "id": "in_example",
  "customer": "cus_example",
  "status": "paid",
  "currency": "usd",
  "lines": [
    { "description": "Monthly plan", "amount": 4000, "quantity": 1 }
  ],
  "charges": [
    { "id": "ch_example", "amount": 4000 }
  ]
}
Field Rule
customer Required reference to an existing customer
status draft, open, paid, void or uncollectible
lines At least one; amount is the line total, not the unit price
lines[].quantity Positive integer; defaults to 1
lines[].price Optional reference to a price
charges Allowed only on paid invoices; defaults to empty
charges[].amount Positive cents; defaults to the invoice total
charges[].amount_refunded Prior refunded cents, from 0 up to the charge amount
currency, metadata, created_offset Defaults: usd, {}, 0

Non-draft invoices receive a deterministic invoice number and matching status-transition timestamps.

Multiple charges on one invoice can represent a duplicate charge. Prior refunds are represented by amount_refunded; individual historical refund objects are not seeded. A fully refunded charge rejects another refund.

data.subscriptions[]

{
  "id": "sub_example",
  "customer": "cus_example",
  "price": "price_monthly",
  "quantity": 1,
  "current_period_start": 1766361600,
  "current_period_end": 1769040000,
  "cancel_at_period_end": false
}

The customer and recurring price must exist. Seeded subscriptions are active; quantity defaults to 1, cancel_at_period_end to false, created_offset to 0 and metadata to {}.

Period timestamps are absolute Unix seconds. By default, the period starts at the created time and ends one price interval later.

Advancing the clock across a period boundary renews and bills the subscription, or applies its scheduled cancellation. Set a period near the seed epoch to test this without a large clock advance.

Legacy ticket records

data.tickets[] serves the demo-grade, Zendesk-shaped desk. It is separate from native Zendesk. IDs are assigned in file order as "1", "2" and so on.

Legacy ticket fields
Field Type or default
subject, body Required nonempty strings
requester Required {name, email}; nonempty name and valid email
status new, open, pending, hold, solved or closed; default open
priority low, normal, high or urgent; default normal
tags String array; default []
external_id Optional string or null
first_comment_public Optional boolean; defaults in behavior to true
created_offset Nonnegative seconds before the epoch; default 0

Billing references in ticket text are not foreign keys. Version 1 tasks compile into this profile, with one ticket per task and an answer key kept separately.

Referential integrity

Validation rejects unknown fields, duplicate IDs, missing references and inconsistent history. Errors name the JSON path to fix.

For Stripe, it also rejects charges on unpaid invoices, over-refunded charges, subscriptions on one-time prices and inverted periods. For native Zendesk, it checks directory relationships, principal authority, comment/audit links and lifecycle metadata.

Imported native IDs set allocator floors so runtime-created records cannot reuse them. Native wire IDs are numeric; admin state keys remain strings.

Import a Stripe account

Provide a restricted read-only key through STRIPE_API_KEY, then run:

worlds seed import --from-stripe --name my-account --manifest worlds/my-account.manifest.json

The importer reads supported account records and writes a validated seed. By default it samples up to 100 objects per resource and writes seeds/my-account.json, or the directory set by WORLDS_SEEDS_DIR.

Treatment Data
Preserved Amounts, currencies, invoice states, charge refund totals, subscription timing, product and price IDs
Replaced Customer names and emails; product names, price nicknames and invoice-line descriptions
Remapped Customer, invoice, charge and subscription IDs
Dropped Customer descriptions and phones; metadata by default

This is pseudonymization, not anonymity. Amounts and timing can still identify an account. Product and price IDs remain verbatim, including merchant-chosen text. Review the manifest before sharing an imported seed.

The same source state and options produce identical files. The default epoch comes from the newest source creation timestamp, rounded up to UTC midnight.

Stripe import options
Option Purpose
--key <key> Alternative to STRIPE_API_KEY
--out <file> Choose the seed destination
--manifest <file> Record fields preserved, replaced or dropped and import losses
--identity-map <file> Write a private original-to-pseudonym map; keep it local
--limit <n> Maximum objects per resource; default 100
--tickets <export> Also fetch customers named by the export and their billing records
--base-url <url> Stripe-compatible origin; defaults to https://api.stripe.com
--epoch <unix> Override the starting time
--keep-names Preserve product names and price nicknames
--keep-descriptions Preserve invoice-line descriptions
--keep-metadata Preserve customer metadata, for test-mode accounts only

Customer identities are always replaced. Customers sharing an email retain that relationship through a shared pseudonym. By default, invoice-line descriptions use the price's placeholder nickname, or a numbered line label when no price exists.

Metadata on products, prices, invoices and subscriptions is not copied. The manifest lists preserved custom product/price IDs and samples of free text retained through --keep-* options.

Unsupported records, such as non-active subscriptions or invoices whose customer was not imported, are skipped and reported. Refund objects become charge-level amount_refunded totals. Disputed charges import as ordinary charges and are listed in the manifest because disputes are outside the twin's scope.

Offline native Zendesk import

worlds seed import --from-zendesk --input support-export.json --name my-support

This CLI accepts a complete native seed or the explicit worlds-zendesk-native-export format below. It does not fetch a live Zendesk account or accept arbitrary vendor exports. The dashboard offers guided data preparation, including supported offline Zendesk Full JSON conversion.

The import remaps identities, replaces supported identifying text and preserves valid relationships, privacy, timestamps and audit history. Attachments and unsupported fields are omitted and counted. Review the generated manifest.

Defaults are seeds/my-support.json and worlds/my-support.manifest.json. An optional --identity-map is private. See native import workflows for destination rules and composition with Stripe.

Accepted native input contracts

An ordinary native seed must have a top-level zendesk profile and empty Stripe/legacy data collections. Alternatively, the wrapper has:

  • format: "worlds-zendesk-native-export"
  • version: 1
  • epoch
  • zendesk containing the full native profile

Both forms require the principal, directory and membership records, tickets, comments and audits needed to satisfy all references. Optional lifecycle metadata must be coherent.

A populated composite seed is not an input to this importer. Import each source separately, then compose sanitized seeds with matching epochs. A native seed's clock configuration is preserved; the wrapper uses seed defaults.

Save a world's current state as a seed

In the dashboard, choose Save as starting setup from an eligible world. From the CLI:

worlds world export w_abc123def456 --name my-fork

The admin equivalent is GET /admin/worlds/:id/export-seed?name=my-fork. Use the result to start another test from the state your agent produced.

The export uses the world's current logical clock as its epoch and validates as a seed. Its lossy report lists state the seed format cannot retain:

Not retained What survives
Stripe refund objects Each charge's refunded total
PaymentIntents and charges without an invoice No seed representation
Pending invoice items Items already swept into invoice lines
Deleted customers and canceled subscriptions No seed representation
Event log Current supported records

Native Zendesk export keeps supported directory records, tickets, comments, full audit history and lifecycle metadata. Stripe and legacy record offsets remain relative to the new epoch.

Exporting and reloading represents settled state, not a replay of the run. Re-exporting that loaded world preserves the same data block.

Library seeds

Seed Use
zendesk-support-v1 Explore native directory, ticket, comment and audit records
zendesk-outcomes-support-v1 Native support tasks; used by init --connector zendesk
zendesk-outcomes-billing-v1 Combined support and Stripe billing tasks; used by init --connector composite
saas-billing-small Stripe examples, including a duplicate charge
saas-billing-smoke Minimal Stripe fixture for fast tests
acme-prod Scripted support-and-billing demonstration
acme-prod-shift Shared-world workday with follow-ups and a shift budget
acme-prod-library Billing starter cases and the source of version 1 packs

Bundled seeds are synthetic fixtures. See the generated seed catalog for their builders and starter packs for ready-made tasks.