Skip to content

Connect a cloud account

Connects your organization's own account at a cloud provider, or replaces the stored one, so Forge can run servers there. Send the offering's connect form from List compute offerings as fields. The details are checked with one read at the provider before anything is stored, then kept encrypted and never returned — not by this endpoint, not by any other, not even masked. The response is the stored account plus foreign_servers, the number of servers in that account Forge did not create, so a client can recommend a dedicated project. Servers created in this account are billed to your organization by the provider, never by Aitronos.

It acts for a person: it requires a bearer token whose user holds the manage_forge capability in the acting organization, and Forge cloud compute switched on for the organization.

PUThttps://api.aitronos.com/v1/forge/compute/credentials/{offering_id}

Path Parameters

offering_id string required

The bring-your-own offering to connect: hetzner, digitalocean, vultr, scaleway, exoscale, linode or upcloud. aitronos has no account to connect and is refused with FORGE_COMPUTE_OFFERING_BLOCKED.

Query Parameters

organization_id string optional

The organization to act in. Defaults to your current organization. You must be an active member of it, or the request is refused with 403 ORGANIZATION_ACCESS_DENIED.

Headers

X-Organization-Id string optional

The same as organization_id, as a header. When both are sent, the query parameter wins.

Body Parameters

fields object required

The offering's connect form: one entry per field id listed in the catalog's credential.fields, e.g. {"api_token": "..."} for Hetzner, or {"secret_key": "...", "project_id": "..."} for Scaleway. Every field is required. Values are trimmed and at most 4,096 printable characters, and a field id the offering does not use is refused rather than ignored. A missing or malformed fields is treated as an empty form. Refusals name the fields, never the values.


Returns

The stored account, as in List connected cloud accounts, plus:

foreign_servers integer or null — how many servers already in this account were not created by Forge. Anything above 0 means the account is shared with other workloads; a dedicated project is recommended. null when the provider did not answer the count (the account was still connected).

{
  "offering_id": "hetzner",
  "set": true,
  "account_label": null,
  "verified_at": "2026-09-28T08:12:40Z",
  "status": "connected",
  "inactive_reason": null,
  "expires_at": null,
  "foreign_servers": 0
}

Errors

StatusCodeWhen
401AUTHENTICATION_REQUIREDNo credential, or a credential with no user (an organization API key).
403ORGANIZATION_ACCESS_DENIEDorganization_id or X-Organization-Id names an organization you are not an active member of.
403INSUFFICIENT_PERMISSIONSThe user does not hold manage_forge in the acting organization.
403FORGE_COMPUTE_DISABLEDForge cloud compute is not switched on for the organization.
403FORGE_COMPUTE_OFFERING_BLOCKEDThe offering has no account to connect here (aitronos, or a provider this environment cannot serve). message is the reason.
403FORGE_COMPUTE_OFFERING_NOT_OFFEREDThe offering is not offered to you right now: switched off, switched off for your organization, or offered to Aitronos staff only. message names the offering (for example "DigitalOcean is not offered right now.") and details.offering_id is its id. Nothing was stored.
404FORGE_COMPUTE_OFFERING_NOT_FOUNDNo offering has this id.
409FORGE_COMPUTE_HOSTS_EXISTServers still run on the stored account and the new details cannot be shown to open that same account. details.live_hosts is the count.
422FORGE_COMPUTE_CREDENTIAL_FIELDS_INVALIDA field is missing, unknown or malformed. details.missing and details.unknown (and, for malformed values, details.invalid) name the fields.
422FORGE_COMPUTE_CREDENTIAL_REJECTEDThe provider refused the details. Nothing was stored. When the key itself may be fine but the call came from an address missing from the key's access list, details.reason is ip_not_allowed, details.address is the address the provider saw (when it named one), and message says which address to add.
502FORGE_COMPUTE_PROVIDER_UNREACHABLEThe provider did not answer. Nothing was stored; try again in a moment.
cURL
curl -X PUT "https://api.aitronos.com/v1/forge/compute/credentials/hetzner" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"fields\": {\"api_token\": \"$HETZNER_API_TOKEN\"}}"

Response:

{
  "offering_id": "hetzner",
  "set": true,
  "account_label": null,
  "verified_at": "2026-09-28T08:12:40Z",
  "status": "connected",
  "inactive_reason": null,
  "expires_at": null,
  "foreign_servers": 0
}