ZuloOne
English
Sign in
Menu

Add an outbound channel

Updated

Declare where a script may talk, as metadata in your model. The script names the channel. The host owns the URL, the credential, the signer, and SSRF. HttpClient is outside the script reference set.

Note

This page is the channel file. Enqueue versus send, posting, and polling are other doors — Send an outbound call, Enqueue an outbound call when a document posts, Poll a REST API from a job. The longer contract is Outbound integrations.

The JSON below is labelled. Channel wms-ship and dictionary WmsConnection are an example, not a product object. Working country patterns you may copy the shape of: fatoora-clearance (signer: fatoora, connectionTable: TaxAuthorityConnection) and erpn-send (authMode: Login, same connection dictionary). Do not treat a customization pack as the default.

How to#

1. The file — OutboundChannels/<name>.channel.json in your model, kind OutboundChannel. New GUIDs on metaId. modelId is this model's metaId. name is what the script will pass to EnqueueAsync / SendAsync.

{
  "kind": "OutboundChannel",
  "object": {
    "path": "/shipments",
    "method": "POST",
    "signer": "none",
    "authMode": "Header",
    "authHeader": "Authorization",
    "baseUrl": "https://wms.invalid/api",
    "contentType": "application/json",
    "connectionTable": "WmsConnection",
    "devComments": "Example only — not a product channel. Live address comes from the tenant connection.",
    "metaId": "<new guid>",
    "name": "wms-ship",
    "modelId": "<YOUR model guid>"
  }
}

Typical object fields: path, method, signer, authMode, baseUrl, contentType, connectionTable, metaId, name, modelId. Optional: authHeader (Header mode), externalReferenceField (a top-level JSON property of a 2xx body), devComments. GET / HEAD go with no body.

connectionTable names the tenant connection dictionary. The columns the resolver reads are fixed: Code, BaseUrl, CredentialRef, Environment, TimeoutSeconds, MaxRetries, AgentTag. Real dictionaries with that shape: TaxAuthorityConnection (tax), UaBankConnection (bank). Empty connectionTable falls back to TaxAuthorityConnection. That default is for tax channels, not an invitation to put a warehouse token on a tax card.

2. The live address is the connection, not the file. baseUrl in the channel is a default and is often a non-working placeholder (https://wms.invalid/api, https://operator.invalid/erpn). Each tenant's operator has its own host; some sit on the customer's LAN. The script passes ConnectionRef = connection.Code. The resolver substitutes the rest.

Secrets never go in the workspace. CredentialRef is a name. The host reads Integration:Credentials:<name>. Do not put a password, a Bearer token, or a Basic blob in the JSON.

AgentTag lives on the connection, not in .channel.json. A neighbour tenant may use a cloud operator; a loopback from Core is still SSRF. The agent with that tag dials from its own machine.

3. A query that belongs to one document does not fit in path. Put a relative path in header X-ZuloOne-RelativePath. The host strips it, appends it to the connection BaseUrl, and does not put the header on the wire. An absolute URL there is refused: the host still comes only from the connection card.

authMode: Login (M.E.Doc REST): the host posts login (POST /api/System/v2/login with {userLogin, password}) and sets X-API-Key. The script never sees the password. Without a password the login is skipped (stands without a live operator). Do not store a ready Bearer token as the credential — that slot is the password.

4. Bump your modelVersion in the same change (minor: a new channel). The tenant compares MetaPackages.PackageVersion to that number; an equal version skips your model as a whole. Then POST /api/services/rebuild. Probe without an outbox row: Developer → Outbound channels → Test channel, or POST /api/metadata/outbound-channels/{id}/test — Bump the model version.

Warning

Never HttpClient / System.Net.Http from a script. Name the channel. Configuration Integration:Channels:<name> overrides the file on a stand (stub redirect). Do not ship a business channel in appsettings.json.

A named ConnectionRef that is missing from connectionTable is an error, not a quiet fallback to the file's baseUrl. Falling back would send the document to a different host with nothing in the result to say so.

What's not there yet#

The platform does not accept an inbound callback that completes the send. CompletionHandler is reserved and unread. Drain your own outbox for send outcomes; poll the other side when you need a receipt — Poll a REST API from a job. A document you must not lose after posting goes through the outbox, not this file alone — Enqueue an outbound call when a document posts.

Where next#

Was this page helpful?