Send an outbound call
Updated
A script talks to a tax office, a bank, or an operator by channel name. The
host owns the wire, the address, and the secret. HttpClient is outside the
script reference set.
Note
Never open a socket from a script. Name the channel. The host resolves URL, credential, signature, and SSRF.
ICredentialResolveris on the deny-list — What a script can do.
How to#
1. A channel — OutboundChannels/<name>.channel.json in your model,
kind OutboundChannel. Path, method, signer, authMode, content type. The
tenant's live address and timeout live on the connection dictionary named in
connectionTable, not in the channel. Secrets never go in the workspace.
2. Pick the door. The choice is not style.
IOutboundGateway |
IOutboundCall |
|
|---|---|---|
| What | a queue (outbox) | a synchronous call |
| When | a document must be sent | an exchange needs its response now |
| Retry | yes | no |
If losing the message means losing the document, enqueue. If the response is
single-use (an OTP swapped for a CSID), IOutboundCall — a queue row would log
the secret and a retry would present a spent OTP.
await ScriptServices.Get<IOutboundGateway>().EnqueueAsync(new OutboundRequest
{
Channel = "fatoora-clearance",
IdempotencyKey = "zatca:" + uuid.ToString("N"),
Payload = body,
SourceTable = "TaxDocument",
SourceRecordId = envelope.MetaId,
});
var result = await ScriptServices.Get<IOutboundCall>().SendAsync(
"fatoora-compliance", payload, idempotencyKey: "zatca-compliance");
Both take a channel name, not a URL.
3. Bump modelVersion. A new channel also needs
POST /api/services/rebuild.
Warning
A successful send is not a receipt. Ask the country contour: is the response the authority's decision, or an operator's "accepted for processing"? Closing the envelope on
Succeededwhen a receipt still has to be fetched registers documents the authority has not seen.
InDoubtmeans the request left and no answer came back. The document may already be registered. Do not retry that status. Query fate; do not submit again.There is no inbound callback. Drain your own outbox for send outcomes; poll the other side with
IOutboundCallwhen you need a receipt.
The longer page is Outbound integrations — signing profiles, four guards against a second submit, and how a country package writes the outcome.
What's not there yet#
The platform does not accept an inbound call from outside. CompletionHandler
is reserved and unread. An integration test cannot cover the exchange itself:
cover everything before the send and everything after the response; say so in
the test header.