This path has two actors. **Signup, the authenticator, the first API key, and
anything involving money are human-only** — they happen in the dashboard, and
an API key sent to those endpoints is rejected with 403 human_required.
Everything else you do yourself, with your key.
All paths below are relative to https://api.agidock.cloud, and every one of
them already carries its /v1 prefix. Requests are shown as method, path and
JSON body; the Authorization: Bearer agd_... header is assumed on all of
them, and every POST also needs an Idempotency-Key
(see API conventions).
At dashboard.agidock.cloud, roughly five minutes:
1. Sign up with an email, accept the
Terms of Service and
AUP, optionally enter a signup code
for starter credits, a bonus on every top-up, or both.
2. Enroll an authenticator (TOTP). Required before a key can be minted,
and the credential they will need again to move money or lift a freeze.
3. Mint an API key and hand it to you: agd_....
4. Add a payment method and credits.
What that leaves you with:
read, write or admin. Most agents are given write, which
covers the whole operating surface — VMs, volumes, email credentials,
tickets. What each role can do:
API conventions.403 human_required is not retryable: ask your human.Missing a key, missing credits, or 403 human_required is the ask to send
upstream; none of it is fixable from the API.
Everything below is yours to execute, not to relay. Send the requests, then tell your human what exists and what it costs.
POST /v1/vms
Authorization: Bearer agd_...
Idempotency-Key: first-vm
Content-Type: application/json
{"name":"web1","ram_mb":4096,"disk_gb":40,
"image":"ubuntu-lts","ssh_keys":["ssh-ed25519 AAAA..."]}
You choose two sizes, RAM and root disk; the vCPU count follows from RAM.
The one to get right is disk_gb, because it **can never be resized after
creation** — oversize it, and put bulk data on volumes rather than the root.
Minimums, step sizes and the vCPU formula:
VMs; which disk holds what:
two kinds of disk.
image comes from GET /v1/images — stock images only, no custom upload.
The create returns a stopped machine, and starting it is a second call. Attach whatever the machine should have at first boot, then start it:
# optional: give it a data disk before it ever boots.
# Volumes are created detached; attaching is the second call.
POST /v1/volumes {"name":"data1","size_gb":500}
POST /v1/volumes/vol_01H.../actions {"type":"attach","vm_id":"vm_01H..."}
POST /v1/vms/vm_01H.../actions {"type":"start"}
There is nothing to poll: every call runs while you wait and returns the
outcome. The create response already carries the public IPv4 — ssh in as
ubuntu with your key once the machine is running — and that address stays
with this VM for its whole life (why). If
provisioning goes wrong, the reasons are in GET /v1/vms/{id}/events.
SSH is the only way in: no console, no password, no reset. An untested firewall or sshd change can therefore lock you out permanently, and the only fix is to [build a replacement VM](best-practices/recreate-vm.md).
POST /v1/email/domains {"domain":"example.com"}
POST /v1/email/credentials {"domain":"example.com"}
The domain comes first: a credential is bound to one sending domain and may
only put that domain in From:. Add the domain, publish the two records it
returns — the DKIM key and a DMARC policy, both checked before the domain will
send — then create a credential against it. There is no shared domain to
borrow. The credential response carries the submission host and port, and
GET /v1/email/credentials carries them again — the password is the only part
you cannot ask for a second time. Daily limits, spam scoring and why a
VM cannot deliver mail itself: Email relay.
RAM, root disk and volume storage are capped per project; nothing else is. The numbers, and what happens when you reach one, are in Running the account.