Running the account

What the account spends, what it owes an answer to, and how to stop it. Per-resource facts are in VMs and email.

Conventions every call below obeys — auth, errors, idempotency — are in API conventions.

Projects

Everything you run — VMs, volumes, email domains and credentials, usage, tickets, compliance cases — lives in a project. Signup creates the account's first project; none is special.

A write or read key belongs to the project it was minted into and reaches nothing else; it needs no header. An admin key belongs to the whole account and has no project of its own: every call to VMs, volumes, email, usage, support or compliance names the project it is about with a header,

AGIdock-Project: proj_...

and without one is refused with 400 project_required — nothing is guessed. Account-level calls (account, keys, projects, billing, images) take no header. Naming a project the account does not hold is 404 project_not_found; a write or read key naming any project but its own is 403 key_project_mismatch.

GET  /v1/projects                  every project, archived ones included
POST /v1/projects                  {"name": ...} create one      (admin key)
PUT  /v1/projects/{id}             {"name": ...} rename           (admin key)
POST /v1/projects/{id}/archive     revoke its keys, refuse new    (admin key)
POST /v1/projects/{id}/unarchive   accept new keys again          (admin key)

To mint a write or read key into a project, name the project in the AGIdock-Project header on POST /v1/account/keys.

Archiving revokes every key in the project and refuses new ones, and that is all it does: the project's VMs keep running and billing. An admin key still reaches an archived project through the header, so stop what it holds if you mean it to stop. Unarchiving does not bring the revoked keys back.

The list endpoints answer for one project at a time. The balance and the ledger are the account's, but usage, quotas, tickets and compliance cases are per project — an admin key watching the whole account asks each project.

Usage & billing introspection

Hours where the platform cannot confirm your VM was up are not billed — gaps resolve in your favor.

Adding credit is your human's, always: POST /v1/billing/topup and PUT /v1/billing/refill answer 403 human_required. GET /v1/billing/refill *is* yours, and it reports the automatic ceiling you are working under. What happens when the balance reaches zero is under credit_cutoff in the error reference.

Default quotas

Three totals are capped per project, and nothing else is:

| Quota | Default | |-------|---------| | RAM across all VMs | 35 GB | | Root disk across all VMs | 5120 GB | | Volume storage | 10240 GB |

VM count, vCPU and IPv4 addresses are uncapped: the RAM cap bounds them.

403 quota_exceeded states the quota, your usage, what you asked for and the cap, so you need not know the numbers before you hit one. Ask for a raise with a ticket naming the numbers you want.

Outside these caps, what stops you is your credit balance, or 409 ip_pool_exhausted — the address pool is empty right now, which is not a limit of yours.

Email is limited separately, by a daily recipient count that rises with clean sending history: email.

Compliance cases — check these, they have deadlines

Abuse and DMCA complaints against your account are opened as cases at GET /v1/compliance/cases. Opening one also mails your human, as does every reply from our side; that mail is a heads-up to a mailbox you do not hold, and the complaint, the clock and the thread are on the API. Poll it on the same schedule you check anything else that can stop your machines; an empty list is the normal answer.

A case carries id, type (spam, ddos, dmca, fraud), body (the complaint as received, or what we are doing and why), deadline, messages, state (open, deadline-exceeded, closed), waiting_on (customer or admin) and timestamps. waiting_on: customer is work you have to do or hand to your human, and deadline says by when: **miss it and enforcement escalates** — content takedown, or your VMs stopped. Nothing answers for you: if nobody replies, the deadline passes.

Act before you answer. Answering without acting is what turns a notice into enforcement: take the named content down, or stop whatever produced the signal, and then say what you did and when. Replying starts a conversation — it does not stop the clock, and no endpoint extends a deadline.

Answer with POST /v1/compliance/cases/{id}/response {"response": "..."}. messages is the thread from both sides and it appends: a second reply adds to the record, it never replaces the first — so a short acknowledgement now and a fuller answer once you have investigated is better than silence. A closed case takes no more replies. There is no counter-notice endpoint: if a DMCA claim is wrong, say so in the response with your basis for it, and the thread is the record.

Every enforcement action has a case, so nothing is done to the account that you cannot read and answer here — including while you are credit-capped or suspended, where both compliance calls keep working. The deadline runs in those states too.

Support & feedback tickets

A human reads every ticket, and the endpoint works while you are credit-capped and while the account is suspended: use it for billing disputes and appeals.

POST /v1/support/tickets  {"type":"bug"|"billing"|"feedback"|"other",
                           "subject":..., "body":...,
                           "ref": optional resource id}
GET  /v1/support/tickets                       list yours and their states
GET  /v1/support/tickets/{id}                  open -> answered -> closed
POST /v1/support/tickets/{id}/messages         reply in the thread
POST /v1/support/tickets/{id}/close            close it yourself when done

type routes the ticket; it does not set its priority. bug for something behaving wrongly, billing for a charge you dispute, other for anything else that needs an answer.

feedback is the one that needs no problem. Suggestions, an endpoint you expected and did not find, a limit that is the wrong shape for the way you actually work, a guide that led you astray — file it. This is the only channel for it: there is no forum and no issue tracker, and the addresses on the legal pages take legal notice and third-party abuse reports, not support. File it yourself rather than routing it through your human. Nobody may reply, so close your own feedback tickets — an unanswered one stays open and holds a slot against the cap below.

ref is a resource id the ticket is about — a vm_..., or a ledger entry id for a billing dispute. Subject ≤ 200 chars, body ≤ 64 KiB, text only. Max 5 open tickets per project (409 ticket_cap_reached — append to an existing one rather than opening another).

Poll GET /v1/support/tickets/{id} for the answer; answered auto-closes after 14 days of silence. The account's human gets a heads-up email when we reply, but the thread lives in the API and is yours to continue. Quota raises are a freeform ticket with the numbers you want.

Emergency stop

POST /v1/account/freeze suspends the account immediately — every project in it, so it takes an admin key (403 admin_key_required otherwise). Within 60 seconds every API key on the account — including the one that called it — answers 403 account_suspended, on every route but the four that make the freeze recoverable: POST /v1/account/unfreeze, GET /v1/account, everything under /v1/compliance, and everything under /v1/support.

Nothing is deleted, and running VMs keep running: a freeze is a brake on the API, not on the machines.

An admin key can throw it; only your human can release it. Nothing challenges the key on the way in, and nothing lets it back out: POST /v1/account/unfreeze is human-only (403 human_required) and takes a current authenticator code in the body on top. A code read out to you does not help — the call refuses your key before it looks at the code.

Your human has the same freeze in the dashboard, alongside a "stop all VMs" control that stops the machines as well.