Create a custom connection
Connections (resources) normally have a dedicated kind with a tailored form — SMTP, PostgreSQL, S3, Telegram bot and so on. The Custom kind is the open-ended complement: a free-form JSON configuration plus an optional secret, for any third-party service SupaCloud has no dedicated kind for — a PayPal API credential, an SSH host, a WooCommerce API, a dashboard login, a Vault AppRole, a Meta Graph token.


How the configuration works
Section titled “How the configuration works”The configuration is an arbitrary JSON object. Every field is stored and passed to workflows and scripts exactly as you enter it, with one exception: the well-known network keys are validated, because they define which hosts the connection may reach (outbound traffic is deny-all otherwise):
| Key | Rule | Effect |
|---|---|---|
base_url / url / endpoint |
must be an http(s) URL |
that URL’s host becomes an allowed outbound authority |
host (+ optional port) |
non-empty string, port 1–65535 | host[:port] becomes an allowed outbound authority |
A configuration without any of these keys is perfectly valid — the connection is then a pure credential carrier with no network access of its own.
The secret is optional and never part of the configuration JSON. It is stored
in the vault and delivered to consuming steps as the secret field — or, as a
JSON object, additionally as individual fields (see the next section).
Multi-field secrets
Section titled “Multi-field secrets”Some services have more than one sensitive value — a PayPal API credential is
a client_id plus a client_secret, a dashboard login is a username plus a
password, a Vault AppRole is a role_id plus a secret_id. Enter these as
a JSON object in the secret field:
{ "client_id": "AXY123…", "client_secret": "EGnH456…" }When the secret parses as a JSON object, its fields reach consuming workflow
steps and scripts as individual fields of the resource bundle — in addition to
the raw string, which always stays available as secret. Imported Windmill
steps that read named fields (say, paypal.client_secret) therefore run
unchanged, while every sensitive value still lives in the vault, never in the
configuration JSON.
Three rules to remember:
- The configuration wins on a name collision. A secret field is only added
when the configuration does not already carry a field of that name — a
secret can never overwrite a configuration value (and never the
secretfield itself). - Anything that is not a JSON object stays a plain secret. A bare token or
password behaves exactly as before: one
secretstring, nothing merged. - Network keys belong in the configuration. A
base_url/url/endpoint/hostinside the secret object grants no outbound access — the egress allowlist derives from the configuration alone.
-
Open the Connections board.
Go to Resources and choose + New resource.
-
Pick the Custom kind.
Select Custom in the kind picker. The configuration opens as a JSON editor seeded with a
base_urlskeleton — keep it for an HTTP service, or delete it and add your own fields. -
Enter the configuration.
For example, a PayPal API credential:
{"base_url": "https://api.paypal.com","client_id": "AXY123…","environment": "live"}Or an SSH host (no URL —
host+portgrant the outbound authority):{ "host": "db-host.example.com", "port": 22, "user": "deploy" } -
Add the secret (optional).
Put the sensitive half — an API client secret, a password, a token — into the secret field. It stays in the vault and reaches workflow steps and scripts as the
secretfield of the resource bundle. Several sensitive values? Enter them as a JSON object — see Multi-field secrets above. -
Test the connection.
Test probes the first URL key (an HTTP
HEAD; auth-required responses still count as reachable) or, without URL keys, TCP-connects tohost:port. A configuration with neither is not probe-able — the test button reports that instead of guessing.