Connector scope

Worlds uses the same workflow across connectors: create a world, run an agent, then check which records changed. Each connector has its own supported API and limitations. A catalog listing does not mean an API is implemented.

On this page
Connector Available behavior Verification
Stripe Billing, customers, payments and subscriptions, within the scope below Tested against real Stripe; see the dated fidelity results
Native Zendesk The ticket, directory and workflow subset in the Zendesk API reference Local conformance plus narrow historical source-bound provider observations; broader/current-artifact live qualification remains pending, as recorded in STATUS
Stripe + native Zendesk Combined workflows with explicit ticket-to-billing bindings Inherits each connector's limits; see test files
Legacy ticket desk A simplified inbox used by older billing examples Demo-grade; not a full Zendesk implementation

Start with the dashboard guide to explore a supported world. Check the relevant connector reference before writing tests for a new workflow.

Experimental beta.4 profiles

The public beta.4 release contains the subsets below; STATUS and the publication reconciliation bind registry/artifact evidence and distinguish it from website activation and installed qualification. These profiles are absent from the older beta.3 archive. Local implementation and package inclusion do not establish provider compatibility, complete dashboard authoring, generic task-suite support or a complete provider API. Each profile retains its own remaining qualification obligations.

Profile Included boundary
Agentforce Runtime Bounded sessions, messages, actions and feedback, dedicated principal credentials, local SSE behavior and an intake workflow; an intake guide ships in the runtime
SAP S/4HANA Finite Business Partner/address maintenance and selected queries, sales-order/item reads and conditional reference writes; wider lifecycle remains in the SAP plan
Dynamics 365 Dataverse Implemented Sales/Customer Service records, opportunity/case lifecycle, queues, opportunity assignment and lead discovery; notes and wider actions remain separate in the Dataverse plan
Confluence Permission-aware pages/history, comments/labels and trash lifecycle within the finite contract
Freshservice Native requester, incident and note lifecycles behind configured reserved-authority ingress; deployment settings and the finite contract retain SDK/provider obligations
JSM Seed/state and client foundation; no native JSM endpoints. The native contract is a separate pending delivery

The browser/storefront workflow uses its own commerce profile, worker/MCP execution, state checks and deterministic recovery scenarios. It does not add real payment, fulfillment or arbitrary external-site parity. Customer Desk, Team Inbox and Digital Shop remain guided starter experiences with their own checks and demo-grade boundaries; Digital Shop's unpaid invoice proposals are separate from browser commerce. The release limitations keep these experimental boundaries explicit. Unimplemented catalog entries continue to collect interest. Generic airline, Gmail, Shopify, Google Workspace and Linear runtime work is outside this public artifact; the inventory records the boundary. Generic airline does not claim Delta parity.

Stripe

The sections below describe the Stripe-compatible surface. Unimplemented routes return a connector-shaped error; parameters that would silently change an unsupported financial behavior are refused.

Implemented (/v1/*)

resource operations depth notes
Customers create, retrieve, update, delete, list (email filter) deleted customers stay retrievable as {deleted: true} stubs (HTTP 200, like real Stripe); deletes hide them from lists and block updates; deleting a customer does not cancel its subscriptions (Known gaps)
Customer balance transactions create, retrieve, list single-currency customer credits and debits; applicable credit is consumed when an invoice is finalized
Products create, retrieve, list (active) minimal fields, enough for prices/invoices
Prices create, retrieve, list (product, active) one-time and recurring; recurring backs subscriptions; unit_amount ≥ 0
Invoice items create, retrieve, list (customer, pending) pending items sweep into the next invoice; quantity ≥ 0
Invoices create, retrieve, delete (drafts — the items it swept are stranded, Known gaps), list (customer, status, subscription), lines, finalize, pay, void, mark_uncollectible full draft → open → paid/void/uncollectible lifecycle with status-transition timestamps, deterministic numbers, guards with Stripe error codes
PaymentIntents create (confirm supported), retrieve, list (customer), confirm, cancel test tokens pm_card_visa and pm_card_chargeDeclined; declines record the failed charge + last_payment_error
Charges retrieve, list (customer, payment_intent, invoice) born only from flows (invoice pay, PI confirm, subscription billing); amount_refunded/refunded maintained
Refunds create (charge or payment_intent), retrieve, list (charge) partial refunds accumulate; over-refund rejected with Stripe's message; full re-refund → charge_already_refunded; a seeded amount_refunded lists one refund for that total, its id derived from the seed hash and the charge id
Subscriptions create, retrieve, update (cancellation, single-item price and quantity), cancel (DELETE), list (customer, status, price) creation bills the first period; price/quantity changes support create_prorations or none; clock advance bills each elapsed period
Events retrieve, list (type) every mutation emits the correct evt_; pending_webhooks reflects the delivery queue

Plus, everywhere: Stripe's exact error envelope (type/code/message/param, correct statuses), cursor pagination (limit, starting_after, ending_before, has_more), idempotency keys (replay + idempotency_error; a request rejected by parameter validation reserves no key, an executed outcome — errors and 500s included — is replayed), Bearer/Basic auth with Stripe-shaped 401s, form-encoded bracket syntax bodies (the real SDKs' wire format), and the Stripe-Should-Retry header on injected errors where Stripe sends it (lock_timeout), which is what the official SDKs' retry logic reads. Official stripe-node 16 (the demo agent) and 22 (the cold agent, stock defaults: two retries, an idempotency key on every POST, API version 2026-08-26.dahlia) run against the twin in the test suite; the twin ignores Stripe-Version and answers in its own pinned shapes.

Request representation has Worlds-specific safety limits: bracket paths allow at most 64 segments, nested JSON objects/arrays allow at most 64 levels below the parameter root, and arrays allow at most 1,000 entries (indices 0–999). A request may materialize at most 100,000 entries across object keys and array slots, including sparse holes; parsing and merged JSON are both checked. Invalid percent-encoded UTF-8 and excess structure return connector-shaped validation errors before handler execution or idempotency storage. These guards are not a claim about the real provider's limits. Prototype-named keys remain literal data and cannot change another request's parameters.

Deliberately not implemented

Where one of these is reachable by a parameter on an implemented route, the request is refused with worlds_unsupported_parameter (below, "Refused parameters") — never accepted and silently ignored.

Payment plumbing — PaymentMethods as objects (only the two test tokens), SetupIntents, 3DS/requires_action, captures/holds (capture_method: manual), multi-currency conversion, account balance/payouts/transfers, Connect, disputes.

Billing breadth — coupons/discounts/promotion codes, tax (rates, automatic tax), credit notes, quotes, usage-based/metered billing, tiered prices, trials, custom proration dates, subscription schedules, multi-item subscriptions (one item per subscription), collection_method: send_invoice (auto-charge only), invoice auto_advance timers (finalize/pay are explicit or subscription-driven).

Platform surface — Checkout, Payment Links, Billing Portal, Sources/Tokens (legacy), files, search endpoints (use list filters or the admin state API), expand[] (objects embed what the twin considers primary; expansion params are accepted and ignored).

Field-level omissions on implemented objects (returned as null/absent rather than half-implemented): address/shipping on customers, default_payment_method, application_fee_amount, transfer_data, on_behalf_of, statement_descriptor overrides, receipt_url contents, balance_transaction objects, invoice PDFs/hosted_invoice_url, webhook endpoint objects via /v1/webhook_endpoints (the twin's endpoint is configured via the admin API instead — one per world).

Currency and lifecycle limits

  • livemode is always false. The account's default currency is USD.
  • Each invoice and subscription uses one currency. Creating an invoice with several pending currencies requires an explicit currency; renewals collect only items in the subscription's currency.
  • A customer's balance uses one currency. Credit is applied only to invoices in that currency. The runtime does not model Stripe's separate credit balance for every currency.
  • Requests that would create credit in a conflicting currency are refused. This includes negative invoice items, affected prorations and attempts to pin a balance beside incompatible pending credits.
  • Charges are created through payment and invoice flows; direct POST /v1/charges is not supported.
  • Rate limits occur only when a scenario injects them.
Recovery from an incompatible renewal

Normal API writes reject the currency combinations described above before a renewal can encounter them. If state supplied outside that API still produces an incompatible renewal, the transaction and clock movement roll back.

A twin request returns a logged api_error 500; explicit clock advance returns 409. In automatic clock mode, requests continue to encounter that failure until the world is reset. In manual mode, adding a positive line in the invoice's currency or scheduling the subscription to cancel can allow the next advance.

Refused parameters

The reference below is for checking a specific Stripe request. Expand it when a run reports an unsupported parameter.

Stripe parameter compatibility

Real Stripe accepts every parameter below and changes how money moves; the twin does not model it. Rather than return a normal success for a request whose real outcome would differ — a manual capture that never captures, a coupon that never discounts, a trial that never defers — the twin refuses the request before the handler runs: 400 invalid_request_error with the twin's own code worlds_unsupported_parameter (not a Stripe code, so a test can tell "the twin cannot grade this" from "Stripe rejected this"), the parameter in param, no idempotency result (a corrected retry under the same key runs; a key already holding a stored result keeps replaying it, and a request under that key that carries a refused parameter is refused rather than answered idempotency_error), and a row in the request log whose unsupported column names the parameter — GET /admin/worlds/:id/requests?unmatched=true lists these beside the un-twinned routes, one row per route and parameter. The request has been authenticated and counted by then: it uses one of the key's requests_used and advances the scenario counters it matched, exactly as an injected or unmatched request does; what does not happen is the handler, the auto-clock tick and the idempotency store. The drift battery pins the gap: pi-capture-manual-refused and price-trial-period-days expect real Stripe to accept what the twin refuses.

How to read the table:

  • A listed allowed value passes through. Other values for that parameter are refused.
  • An absent, null or empty value is treated as not supplied. Fields that only affect echoed output may still be accepted and ignored.
  • This is a list of recognized spellings, not a complete Stripe parameter validator. Unknown parameters, case variants and some unsupported parameter shapes are ignored.
  • Some refusals depend on customer state, such as incompatible credit currencies. Those happen during execution. If the request has an idempotency key, the outcome is cached; changing the request while reusing that key returns an idempotency error.
  • Validation refusals before execution do not reserve an idempotency key. Injected scenario errors also occur before idempotency lookup and storage.
route parameter allowed why
POST /v1/payment_intents capture_method automatic, automatic_async a manual capture holds funds without moving them; the twin captures on confirm
POST /v1/payment_intents payment_method_options[card][capture_method] — the card-level capture_method overrides the top-level one: manual holds the funds instead of capturing them
POST /v1/payment_intents application_fee_amount — a Connect fee splits the charge
POST /v1/payment_intents transfer_data — a Connect transfer moves money to another account
POST /v1/payment_intents on_behalf_of — Connect settlement on another account
POST /v1/payment_intents/:id/confirm capture_method automatic, automatic_async a manual capture holds funds without moving them; the twin captures on confirm
POST /v1/payment_intents/:id/confirm payment_method_options[card][capture_method] — the card-level capture_method overrides the top-level one: manual holds the funds instead of capturing them
POST /v1/subscriptions trial_period_days — a trial defers the first charge
POST /v1/subscriptions trial_end — a trial defers the first charge
POST /v1/subscriptions trial_from_plan false takes the trial from the price's recurring[trial_period_days]; a trial defers the first charge
POST /v1/subscriptions coupon — a discount changes every invoice total
POST /v1/subscriptions discounts — a discount changes every invoice total
POST /v1/subscriptions promotion_code — a discount changes every invoice total
POST /v1/subscriptions default_tax_rates — tax changes invoice totals
POST /v1/subscriptions automatic_tax[enabled] false tax changes invoice totals
POST /v1/subscriptions billing_cycle_anchor — moves the first period boundary and prorates the first invoice
POST /v1/subscriptions billing_cycle_anchor_config — moves the first period boundary and prorates the first invoice
POST /v1/subscriptions backdate_start_date — bills past periods at creation
POST /v1/subscriptions collection_method charge_automatically send_invoice leaves the invoice open instead of charging it
POST /v1/subscriptions days_until_due — only meaningful with send_invoice
POST /v1/subscriptions payment_behavior allow_incomplete, error_if_incomplete default_incomplete and pending_if_incomplete leave the invoice unpaid; the twin charges at once
POST /v1/subscriptions cancel_at — the twin models cancel_at_period_end only
POST /v1/subscriptions add_invoice_items — one-time lines change the first invoice total
POST /v1/subscriptions items[0][price_data] — an inline price the twin cannot read; create the price, then pass items[0][price]
POST /v1/subscriptions items[0][tax_rates] — tax changes the line total
POST /v1/subscriptions items[0][discounts] — a discount changes the line total
POST /v1/subscriptions application_fee_percent — a Connect fee splits every invoice's charge
POST /v1/subscriptions transfer_data — a Connect transfer moves every invoice's charge to another account
POST /v1/subscriptions on_behalf_of — Connect settlement on another account
POST /v1/subscriptions billing_thresholds — bills when the amount crosses a threshold, not at the period boundary
POST /v1/subscriptions/:id trial_end — a trial defers the next charge
POST /v1/subscriptions/:id coupon — a discount changes every invoice total
POST /v1/subscriptions/:id discounts — a discount changes every invoice total
POST /v1/subscriptions/:id promotion_code — a discount changes every invoice total
POST /v1/subscriptions/:id default_tax_rates — tax changes invoice totals
POST /v1/subscriptions/:id automatic_tax[enabled] false tax changes invoice totals
POST /v1/subscriptions/:id billing_cycle_anchor unchanged resetting the anchor prorates and moves every renewal
POST /v1/subscriptions/:id proration_date — changes the proration amounts
POST /v1/subscriptions/:id cancel_at — the twin models cancel_at_period_end only
POST /v1/subscriptions/:id pause_collection — pauses charging while the subscription stays active
POST /v1/subscriptions/:id collection_method charge_automatically send_invoice leaves the invoice open instead of charging it
POST /v1/subscriptions/:id days_until_due — only meaningful with send_invoice
POST /v1/subscriptions/:id payment_behavior allow_incomplete, error_if_incomplete default_incomplete and pending_if_incomplete leave the invoice unpaid; the twin charges at once
POST /v1/subscriptions/:id add_invoice_items — one-time lines change the next invoice total
POST /v1/subscriptions/:id items[0][price_data] — an inline price the twin cannot read; create the price, then pass items[0][price]
POST /v1/subscriptions/:id items[0][tax_rates] — tax changes the line total
POST /v1/subscriptions/:id items[0][discounts] — a discount changes the line total
POST /v1/subscriptions/:id items[0][deleted] false deletes the one item — Stripe 400s unless another item replaces it, and the twin models exactly one
POST /v1/subscriptions/:id application_fee_percent — a Connect fee splits every invoice's charge
POST /v1/subscriptions/:id transfer_data — a Connect transfer moves every invoice's charge to another account
POST /v1/subscriptions/:id on_behalf_of — Connect settlement on another account
POST /v1/subscriptions/:id billing_thresholds — bills when the amount crosses a threshold, not at the period boundary
DELETE /v1/subscriptions/:id invoice_now false invoices pending prorations at once
DELETE /v1/subscriptions/:id prorate false credits the unused time on cancel
POST /v1/invoices collection_method charge_automatically send_invoice leaves the invoice open instead of charging it
POST /v1/invoices days_until_due — only meaningful with send_invoice
POST /v1/invoices due_date — only meaningful with send_invoice
POST /v1/invoices auto_advance false Stripe finalizes and collects on its own about an hour later; the twin finalizes and pays only when told to
POST /v1/invoices discounts — a discount changes the invoice total
POST /v1/invoices default_tax_rates — tax changes invoice totals
POST /v1/invoices automatic_tax[enabled] false tax changes invoice totals
POST /v1/invoices pending_invoice_items_behavior include exclude leaves the pending items off the invoice; the twin always sweeps them
POST /v1/invoices subscription — includes only that subscription's pending items; the twin sweeps every pending item of the customer
POST /v1/invoices application_fee_amount — a Connect fee splits the charge
POST /v1/invoices transfer_data — a Connect transfer moves money to another account
POST /v1/invoices on_behalf_of — Connect settlement on another account
POST /v1/invoiceitems price_data — an inline price the twin cannot read; pass amount + currency, or price
POST /v1/invoiceitems unit_amount — the twin reads amount (a total), or price × quantity
POST /v1/invoiceitems unit_amount_decimal — the twin reads amount (a total), or price × quantity
POST /v1/invoiceitems discounts — a discount changes the line total
POST /v1/invoiceitems tax_rates — tax changes the line total
POST /v1/invoiceitems invoice — adds the line to a specific draft invoice; the twin sweeps pending items only
POST /v1/invoices/:id/pay paid_out_of_band false marks the invoice paid with no charge
POST /v1/invoices/:id/pay forgive false writes off the remaining amount
POST /v1/refunds refund_application_fee false a Connect fee refund
POST /v1/refunds reverse_transfer false a Connect transfer reversal
POST /v1/customers coupon — a discount changes every future invoice
POST /v1/customers promotion_code — a discount changes every future invoice
POST /v1/customers cash_balance — a second balance the twin does not model
POST /v1/customers/:id coupon — a discount changes every future invoice
POST /v1/customers/:id promotion_code — a discount changes every future invoice
POST /v1/customers/:id cash_balance — a second balance the twin does not model
POST /v1/prices billing_scheme per_unit tiered pricing changes the amount per quantity
POST /v1/prices tiers — tiered pricing changes the amount per quantity
POST /v1/prices tiers_mode — tiered pricing changes the amount per quantity
POST /v1/prices transform_quantity — changes the billed quantity
POST /v1/prices recurring[usage_type] licensed metered billing bills reported usage, not the quantity
POST /v1/prices recurring[aggregate_usage] — metered billing; a Plans-era parameter Stripe's current API no longer accepts on a price, refused rather than echoed
POST /v1/prices recurring[meter] — metered billing
POST /v1/prices recurring[trial_period_days] — a trial every subscription created with trial_from_plan takes; a trial defers the first charge
POST /v1/prices unit_amount_decimal — the twin reads unit_amount
POST /v1/prices custom_unit_amount — the customer chooses the amount
POST /v1/prices currency_options — multi-currency prices
POST /v1/prices product_data — an inline product the twin cannot create; create the product, then pass product

Known gaps

Behavior on the implemented surface that is known to differ from Stripe and is written down here rather than fixed yet; each row names its follow-up.

gap today Stripe follow-up
DELETE /v1/customers/:id leaves the customer's subscriptions active the stub is deleted: true; the subscriptions keep renewing on every clock advance, billing a deleted customer "Also immediately cancels any active subscriptions on the customer" a drift probe (customer-delete-cancels-subscriptions) and the fix, under C2 (whatever live drift flags)
every recurring price echoes recurring.aggregate_usage: null priceShape in packages/server/src/twin/build.ts still emits the field, though POST /v1/prices refuses the parameter the current API neither accepts nor returns it dropped when the price shape is next re-pinned against the drift battery
deleting a draft invoice strands the items it swept the items keep invoice: <the deleted id> — not pending (?pending=true misses them), on no invoice; the next POST /v1/invoices answers Nothing to invoice unverified: returned to pending, or deleted with the draft a drift probe decides; until then, void instead of delete, or create the items after deleting the draft

The legacy tickets surface (/api/v2/*)

The following describes existing seeds without a top-level zendesk profile. The opt-in native Zendesk profile has a separate resource model and wider supported API; neither profile is generally certified against the real Zendesk API.

Worlds also expose a Zendesk-shaped support-desk surface so composite ticket+billing agent runs can be graded by one diff: GET/POST /api/v2/tickets.json, GET/PUT /api/v2/tickets/{id}.json, GET /api/v2/tickets/{id}/comments.json, with Zendesk's envelopes, ISO timestamps (from the logical clock), status/priority lifecycles (closed tickets are immutable), and Zendesk-shaped errors.

This surface is demo-grade: faithful enough for realistic agent traffic, deterministic like everything else, but — unlike the Stripe surface — not drift-verified against the real Zendesk API, and deliberately simplified (numeric-string ids, comments stored on the ticket, no users/orgs/macros/search, no page-based pagination). Authenticated tool-mediated observations inform selected regressions, but do not establish full raw-API conformance; treat "the twin behaves exactly like Zendesk" as out of scope. See conformance and adversarial checks.

Supported ticket writes validate nested objects and field types before allocation or mutation. Creation honors status, updates can change subject, tags remove exact duplicates and empty entries, and string/null external IDs persist. Omitted comment privacy inherits the preceding comment; a new ticket retains the public default. Seed export/load preserves the opening comment's privacy. Malformed supported inputs and recognized unsupported native mutations fail explicitly, without partial ticket/comment/event changes.

Native users, requester/assignee IDs, groups, organizations, custom fields/statuses, follower/CC relations, uploads/HTML comments, protected concurrency and native idempotency remain outside this subset. They require the native-record and lifecycle milestones in the implementation plan. Priority clearing, provider text/HTML normalization and size limits, full tag normalization, configurable closed-ticket permissions, audits and pagination are also unqualified. A subset error is not a claim that Zendesk itself rejects that operation.