Reference
View as MarkdownIntegrations API
12 operations. Every call needs a session cookie or an Authorization: Bearer nct_… token unless marked Public. Conventions, errors and scopes
/cloudflare/ipsCloudflare IP ranges in use
The list the origin lock allows: its source (built-in copy, Cloudflare API or the published text files), size, age and the state of the 3-hourly refresh. stale is set when fetching has failed for more than 24 hours; the last good list stays in use.
Response 200 · OK · application/json
- builtinDatestringrequiredThe day the built-in list was fetched (YYYY-MM-DD)
- changedAtstring (date-time) | nullrequiredThe last time the content changed; null while the built-in list is in use
- failingSincestring (date-time) | nullrequired
- fetchedAtstring (date-time) | nullrequiredThe last successful fetch; null while the built-in list is in use
- hashstringrequired
- lastErrorstringrequiredWhy the last fetch failed; empty after a successful one
- sourceenum: builtin | api | textrequiredWhere the list came from: the copy built into the binary, the Cloudflare API or the published text files
- stalebooleanrequiredFetching has failed for more than 24 hours
- v4Countinteger (int64)required
- v6Countinteger (int64)required
401Unauthorized403Forbidden500Internal Server Error
Errors are RFC 9457 application/problem+json with a stable code field.
/cloudflare/ips/refreshRefresh Cloudflare's IP ranges now (team admin)
Fetches the list like the periodic job does (API first, text files second), validates it and stores it. A changed list is pushed to the servers with locked routes (a route update, no redeploy). 502 ip_refresh_failed when neither source works or the answer fails validation; the stored list stays.
Response 200 · OK · application/json
- builtinDatestringrequiredThe day the built-in list was fetched (YYYY-MM-DD)
- changedAtstring (date-time) | nullrequiredThe last time the content changed; null while the built-in list is in use
- failingSincestring (date-time) | nullrequired
- fetchedAtstring (date-time) | nullrequiredThe last successful fetch; null while the built-in list is in use
- hashstringrequired
- lastErrorstringrequiredWhy the last fetch failed; empty after a successful one
- sourceenum: builtin | api | textrequiredWhere the list came from: the copy built into the binary, the Cloudflare API or the published text files
- stalebooleanrequiredFetching has failed for more than 24 hours
- v4Countinteger (int64)required
- v6Countinteger (int64)required
401Unauthorized403Forbidden500Internal Server Error502Bad Gatewayip_refresh_failed
Errors are RFC 9457 application/problem+json with a stable code field.
/integrations/cloudflareGet the Cloudflare connection
The API token is never returned.
Response 200 · OK · application/json
- accountIdstringrequiredAccount used for Cloudflare Tunnel calls
- accountNamestringrequired
- AccountRef[] | nullrequiredAccounts the token's zones belong to
- autoManagebooleanrequiredNew domains in a connected zone get their DNS records managed automatically
- configuredbooleanrequired
- defaultProxiedbooleanrequiredNew managed records start proxied (orange cloud)
- statusenum: | ok | errorrequirederror after Cloudflare rejected the token; empty when not configured
- statusMessagestringrequired
- tokenExpiresAtstring (date-time) | nullrequired
- verifiedAtstring (date-time) | nullrequired
- warningsstring[] | nullrequired
- zoneCountinteger (int64)required
- zonesSyncedAtstring (date-time) | nullrequired
401Unauthorized403Forbidden500Internal Server Error
Errors are RFC 9457 application/problem+json with a stable code field.
/integrations/cloudflareConnect Cloudflare
Stores a scoped API token (sealed at rest, write-only) after verifying it against Cloudflare and caching its zone list; every domain of the team is matched against the zones. Omit the token to change only the settings. 422 invalid_token when Cloudflare rejects the token.
Request body · application/json · required
- accountIdstringAccount used for Cloudflare Tunnel calls; defaults to the account of the token's zones
- autoManagebooleanNew domains in a connected zone get their DNS records managed automatically (default true)
- defaultProxiedbooleanNew managed records start proxied (orange cloud; default false)
- dns01CredentialIdstringUse the token of an existing Cloudflare DNS-01 credential instead of typing one
- tokenstringWrite-only: a Cloudflare API token with Zone → Zone: Read and Zone → DNS: Edit (add Zone → Zone Settings: Read for SSL-mode warnings and Account → Cloudflare Tunnel: Edit for tunnels). Omit to keep the stored token.
Response 200 · OK · application/json
- accountIdstringrequiredAccount used for Cloudflare Tunnel calls
- accountNamestringrequired
- AccountRef[] | nullrequiredAccounts the token's zones belong to
- autoManagebooleanrequiredNew domains in a connected zone get their DNS records managed automatically
- configuredbooleanrequired
- defaultProxiedbooleanrequiredNew managed records start proxied (orange cloud)
- statusenum: | ok | errorrequirederror after Cloudflare rejected the token; empty when not configured
- statusMessagestringrequired
- tokenExpiresAtstring (date-time) | nullrequired
- verifiedAtstring (date-time) | nullrequired
- warningsstring[] | nullrequired
- zoneCountinteger (int64)required
- zonesSyncedAtstring (date-time) | nullrequired
401Unauthorized403Forbidden422Unprocessable Entityinvalid_token500Internal Server Error502Bad Gateway
Errors are RFC 9457 application/problem+json with a stable code field.
/integrations/cloudflareDisconnect Cloudflare
Forgets the token and the zone list. Records NebulaCtrl created stay in Cloudflare (unmanaged) unless removeRecords=true.
| Parameter | In | Type | Description |
|---|---|---|---|
removeRecords | query | boolean | Delete the DNS records NebulaCtrl created from Cloudflare first (the removal is refused when that fails) |
Response 204 · No Content
No body.
401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity500Internal Server Error502Bad Gateway
Errors are RFC 9457 application/problem+json with a stable code field.
/integrations/cloudflare/testRe-verify the token and refresh the zone list
Verifies the stored token, refreshes the cached zones and re-matches every domain of the team.
Response 200 · OK · application/json
- accountIdstringrequiredAccount used for Cloudflare Tunnel calls
- accountNamestringrequired
- AccountRef[] | nullrequiredAccounts the token's zones belong to
- autoManagebooleanrequiredNew domains in a connected zone get their DNS records managed automatically
- configuredbooleanrequired
- defaultProxiedbooleanrequiredNew managed records start proxied (orange cloud)
- statusenum: | ok | errorrequirederror after Cloudflare rejected the token; empty when not configured
- statusMessagestringrequired
- tokenExpiresAtstring (date-time) | nullrequired
- verifiedAtstring (date-time) | nullrequired
- warningsstring[] | nullrequired
- zoneCountinteger (int64)required
- zonesSyncedAtstring (date-time) | nullrequired
401Unauthorized403Forbidden404Not Found422Unprocessable Entity500Internal Server Error502Bad Gateway
Errors are RFC 9457 application/problem+json with a stable code field.
/integrations/cloudflare/zonesList the connected zones (zone picker)
The cached zone list; empty without a connection.
Response 200 · OK · application/json
- Zone[] | nullrequired
401Unauthorized403Forbidden500Internal Server Error
Errors are RFC 9457 application/problem+json with a stable code field.
/integrations/tailscaleGet the Tailscale integration
The OAuth client secret is never returned (secretSet only).
Response 200 · OK · application/json
- allowedTagsstring[] | nullrequired
- clientIdstringrequired
- configuredbooleanrequired
- defaultTagsstring[] | nullrequired
- headscaleCredentialenum: apikey | preauthrequiredapikey: NebulaCtrl mints single-use pre-auth keys and deletes nodes; preauth: one reusable tagged pre-auth key for every sidecar
- headscaleUserstringrequiredHeadscale user that owns minted pre-auth keys (empty = tags-only keys)
- httpsEnabledboolean | nullrequiredWhether the tailnet has HTTPS certificates enabled (known after a successful test)
- TailscaleLastTestrequired
- loginServerstringrequiredHeadscale control URL (headscale provider)
- providerenum: tailscale_oauth | headscalerequired
- secretSetbooleanrequired
- tailnetstringrequiredTailnet name, or - for the tailnet of the OAuth client
401Unauthorized403Forbidden500Internal Server Error
Errors are RFC 9457 application/problem+json with a stable code field.
/integrations/tailscaleCreate or update the Tailscale integration
Stores an OAuth client (scopes auth_keys and devices:core) or, with provider: headscale, a Headscale server (login URL plus an API key, or a reusable tagged pre-auth key). The secret is sealed at rest; omit clientSecret to keep the stored one. Nothing contacts the control server until the connection test or first use.
Request body · application/json · required
- allowedTagsstring[] | nullTags NebulaCtrl may use; must include every default tag
- clientIdstringOAuth client id (tailscale_oauth only)
- clientSecretstringWrite-only: the OAuth client secret, the Headscale API key or the Headscale pre-auth key. Omit to keep the stored secret.
- defaultTagsstring[] | nullTags minted keys carry (default tag:nebula-svc)
- headscaleCredentialenum: apikey | preauthapikey: NebulaCtrl mints single-use pre-auth keys and deletes nodes; preauth: one reusable tagged pre-auth key (headscale only)
- headscaleUserstringHeadscale user that owns minted pre-auth keys; empty creates tags-only keys (headscale only)
- loginServerstringHeadscale control URL (headscale only)
- providerenum: tailscale_oauth | headscaletailscale_oauth (default) or headscale
- tailnetstringTailnet name; empty or - uses the tailnet of the OAuth client
Response 200 · OK · application/json
- allowedTagsstring[] | nullrequired
- clientIdstringrequired
- configuredbooleanrequired
- defaultTagsstring[] | nullrequired
- headscaleCredentialenum: apikey | preauthrequiredapikey: NebulaCtrl mints single-use pre-auth keys and deletes nodes; preauth: one reusable tagged pre-auth key for every sidecar
- headscaleUserstringrequiredHeadscale user that owns minted pre-auth keys (empty = tags-only keys)
- httpsEnabledboolean | nullrequiredWhether the tailnet has HTTPS certificates enabled (known after a successful test)
- TailscaleLastTestrequired
- loginServerstringrequiredHeadscale control URL (headscale provider)
- providerenum: tailscale_oauth | headscalerequired
- secretSetbooleanrequired
- tailnetstringrequiredTailnet name, or - for the tailnet of the OAuth client
401Unauthorized403Forbidden422Unprocessable Entity500Internal Server Error
Errors are RFC 9457 application/problem+json with a stable code field.
/integrations/tailscaleRemove the Tailscale integration
Refused (409 integration_in_use) while a server uses a managed tailnet.
Response 204 · No Content
No body.
401Unauthorized403Forbidden404Not Found409Conflictintegration_in_use500Internal Server Error
Errors are RFC 9457 application/problem+json with a stable code field.
/integrations/tailscale/devicesList the tailnet's devices (device picker)
Response 200 · OK · application/json
- TailscaleDevice[] | nullrequired
401Unauthorized403Forbidden422Unprocessable Entity500Internal Server Error502Bad Gateway
Errors are RFC 9457 application/problem+json with a stable code field.
/integrations/tailscale/testTest the Tailscale connection
Exchanges a token, lists devices, mints and revokes a 60 second key with the default tags. Leaves no residue.
Response 200 · OK · application/json
- TailscaleCheck[] | nullrequired
- okbooleanrequired
401Unauthorized403Forbidden404Not Found500Internal Server Error
Errors are RFC 9457 application/problem+json with a stable code field.