Skip to main content
An external call is a durable request for an external system to do something: void an invoice, update a customer record, send an email. You submit it from an operation’s preparation, and it is persisted in the same transaction as your local changes, before anything is sent.
bijection/invoices.ts
Here billing is an integration whose setStatus command describes how to send the request and how to tell whether it took effect. billing_invoices is the table that integration keeps in sync.

Submitting an external call

ctx.externalCalls.submit(command, options) takes a command from one of your integrations and these options: It returns the call’s ID, a string you can store and use to follow the call. Submission is part of the transaction:
  • The call is recorded only if the transaction commits. If preparation throws after submitting, the call disappears with the rest of the transaction.
  • The call can only be submitted from a mutation transaction, such as an operation’s prepare. Anywhere else it is refused with MutationRequired.
  • The command’s arguments are fixed when the request is accepted. Later retries send those same arguments; they are never recalculated by newer code.
Submitting records your intent. It does not update the synced table. The table changes only when the external system’s answer confirms the change and the confirmed record is published back.

The lifecycle of an external call

1

Persisted

The call commits with the operation, before any request is sent. From this point the engine owns delivering it, independently of the process that submitted it.
2

Held and sent

When the call’s turn comes, the engine holds it and sends the command’s request. A call can wait here for an earlier call it is ordered after, or for an approval.
3

Outcome recorded

The external system’s response is retained and interpreted under the command’s declared evidence contract. The resulting outcome is recorded in its own commit.
4

Published

Confirmed facts reach the synced table, where your queries see them: from the response itself when it proves the resulting record, otherwise from a later read of the source. Confirmation and publication are recorded separately.
External systems control their own transactions. No local transaction stays open while a request is in flight, and an operation that submits several calls does not make their effects atomic.

Delivery outcomes

Each external call has one of these delivery states, reported by an operation’s status: A call’s status also reports its publication: null, pending, blocked, or published at a revision.

Delivery guarantees

What the engine may do after a lost response depends on the command’s declared delivery contract, which the integration states for each command:
The destination deduplicates requests by the call’s identity for a stated period. Within that period, the engine can send again under the same identity, and the destination treats it as the same request. If the destination states no retention period, the engine never resends under the retained identity.
Neither contract promises that the external effect happens exactly once. The engine records what the destination’s evidence proves, and nothing more.
A successful HTTP status is not always proof. Commands declare which part of a response carries the verdict, and a response that proves only that a request was well formed does not settle the call as delivered.

Unknown outcomes and recovery

A timeout, a crashed worker, or a missing response does not prove that a call failed. The engine records such a call as unknown, and it stays unknown until it is reconciled under the command’s own contract, for example by reading the destination’s records for this call’s identity. When you meet an unknown outcome:
  • Do not submit a replacement. A new request is a new business change and could apply the effect twice. The original call keeps its identity.
  • Recover the same call. A deployment administrator can inspect and recover it from the CLI. Recovery reuses the accepted identity, interprets retained evidence or performs a bounded read, and never sends a new write.
command-status reports the retained outcome, the stopping reason, the attempt and byte budgets, and the evidence still required. See also CLI and console.
Undoing a completed external effect is a new business change. Write a separate operation for it, such as refund for charge. Cancelling a request cannot undo an effect that already happened.

Reading a call’s status in your code

externalCallStatus is in beta.
externalCallStatus(ctx, id) returns the delivery state of a call your component submitted, as one of the states above. It is an ordinary tracked read, so a query that calls it re-runs when the call settles.
bijection/invoices.ts
It answers only for calls submitted by the calling component. Any other ID, or a call another component submitted, is refused with ExternalCallNotFound. Nothing else about the call is disclosed: not its arguments, its attempts, nor the destination’s own words for a refusal.