Skip to main content

API

The API the console and the CLI call, the tokens CI deploys with, and what each can reach.

Everything the console does is an HTTP API under /api/vc/v1, and the console and the CLI both call it. How you reach it depends on who is calling:

  • You, at your own machine: vallic login signs the CLI in through your browser, and everything you can do in the console you can do from there.
  • A pipeline: a personal access token, which reaches deploys and what a deploy needs — see What a token can do.

Issuing a token

Your account → Access tokens → Issue a token. It asks three things:

Field Why
What is it for Only you see it. It is how you tell which token to revoke when something is compromised
Team The token reaches this team and nothing else, whatever else you are a member of
Expires 7, 30 or 90 days

The token is shown once. Only a digest of it is kept, so it cannot be shown again or recovered — if you lose it, revoke it and issue another.

There is no token that never expires. A token lives in CI settings, in a colleague's shell history, in a laptop that was sold; 90 days is the most any of them stays good for after it was forgotten. You are emailed from 14 days before one expires, and weekly after that.

Revoke is on the token's row. Revoked and expired tokens stay in the list, so you can see what existed and when it was last used.

What a token can do

A token is for CI. It reaches deploying, redeploying and rolling back, building, following the task and its log, checking a vallic.yaml, and the reads that find a project and environment (/me, /teams, /projects, /environments, releases). Nothing else: variables, domains, backups, environments, keys and tokens need you signed in — the console, or vallic login. A token asked for anything else is refused with a 403, token_not_allowed. A token cannot issue tokens.

Within that, exactly what you can do in that team, and no more. A token is you, narrowed to one team: your role decides what it may touch, every rule that applies to you in the console applies to it, and if your role changes, so does the token. Leaving the team leaves the token with nothing.

There are no scopes. A token cannot be limited to reading, or to one project. If a pipeline should only ever deploy, give it a token belonging to someone whose role is only Developer — a person, or an account made for the purpose.

A token never restores a backup. A pipeline that could replace your live database is a pipeline that could be made to. Restoring over a protected production environment asks for your password again, signed in.

Calling the API

curl https://console.vallic.com/api/vc/v1/environments \
  -H "Authorization: Bearer vcp_…"

JSON in and out. Every token starts vcp_, so one committed by mistake is easy to search for. A request refused for what it sent is a 422 whose error.fields names the reason per field.

Endpoints marked token take a personal access token; the rest need you signed in. Signed in through a browser, a write also carries the session's CSRF token in an X-CSRF-Token header, from /session/token; the CLI's sign-in needs none.

Most changes come in two calls: a GET of what may be asked — the choices, the values as they are now, or blocked with the reason there is nothing to ask — and the POST that makes the change. Where machines are built or given back, a …/preview says first what would happen and what it would cost, and changes nothing. The console's dialogs are these calls, so anything they do can be scripted the same way.

You and your account

Endpoints under /api/vc/v1
You GET /me, GET /teams (token)
Keys and tokens GET, POST on /me/ssh-keys and /me/tokens; DELETE /me/ssh-keys/{id}, /me/tokens/{id}
Other browsers POST /users/{id}/sessions/end-others signs out every browser but this one
Invitations to you POST /invitations/{id}/accept, for the account whose confirmed address it was sent to

Teams

The team GET /teams/new, POST /teams; GET, POST on /teams/{id}/settings; DELETE /teams/{id} once nothing is left in it
People GET /teams/{id}/people; POST /teams/{id}/invitations; POST /invitations/{id}/renew, DELETE /invitations/{id}; PATCH, DELETE on /memberships/{id}
Who it bills as GET, POST on /teams/{id}/billing; POST /billing/address-format with {country} says how that country writes an address
Subscriptions GET, POST on /teams/{id}/subscriptions/{order}/cancel
Integrations GET /teams/{id}/integrations/new; POST /teams/{id}/integrations/fields with {kind} says what a service asks; POST /teams/{id}/integrations; GET, POST, DELETE on /integrations/{id}
GitLab and Gitea GET /teams/{id}/repository-hosts/new, POST /teams/{id}/repository-hosts; DELETE /repository-hosts/{id}
Backup destinations GET /teams/{id}/backup-destinations/new, POST /teams/{id}/backup-destinations; GET, POST on /backup-destinations/{id}
Notifications GET /teams/{id}/notifications — what is waiting and what finished since you last looked, the bell's two counts and their first rows
What you have seen POST /teams/{id}/activity/seen, POST /teams/{id}/next-steps/hide — yours alone

Projects

Listing GET /projects (token)
New GET /projects/new, POST /projects
Settings GET, POST on /projects/{id}/settings, …/registries (DELETE …/registries/{host} forgets one), …/logs, …/notifications and …/backup-window (DELETE goes back to the default)
Edge GET, PATCH on /projects/{id}/edge — blocked addresses and user agents, rate limit, HSTS, compression and the pages the edge serves, in one save; nothing is kept if anything is refused
Commercial terms GET, POST on /projects/{id}/terms
Repository GET, POST on /projects/{id}/repository; POST …/repository/reconnect
Releases GET /projects/{id}/releases (?branch= for one branch) (token)
Variables GET, POST on /projects/{id}/variables; DELETE …/variables/{name}; POST …/variables/import, …/variables/apply
Cancelling, deleting GET, POST on /projects/{id}/cancel; DELETE /projects/{id} once it has no environments

Environments

Listing GET /environments, /environments/{id} (token)
New, changed, deleted GET /projects/{id}/environments/choices, POST /projects/{id}/environments; PATCH /environments/{id} (git_ref, auto_deploy), DELETE /environments/{id}
Deploying GET /environments/{id}/deploy and …/source say what may be deployed and from where; POST …/deploy, …/redeploy, …/rollback, …/build (token)
Variables GET, POST on /environments/{id}/variables; GET, DELETE …/variables/{name}; POST …/variables/import, …/variables/apply; POST /variables/parse reads a pasted .env back and saves nothing
Domains GET, POST on /environments/{id}/domains; PATCH, DELETE on /domains/{id}; POST /domains/{id}/verify
CDN and edge GET, PATCH on /environments/{id}/cdn and …/edge (the environment's own: allowed addresses, password, stickiness); POST …/cdn/clear
Maintenance POST /environments/{id}/maintenance with {maintenance, note?}
Logs GET /environments/{id}/logs: where the environment's request and error logs go — the project's destination by kind and name, whether it can send, how many days each machine keeps its own copy. Vallic Cloud does not keep the logs, so there is nothing to tail here
Resources GET /environments/{id}/resources?window= 1h, 24h, 7d, 30d or 90d: CPU, memory and disk, oldest first, averaged into at most 500 points; step says how many seconds each covers. Kept three months
Services GET /environments/{id}/services; GET …/services/choices, POST …/services/preview, POST …/services
Shape and scale GET, POST on /environments/{id}/reshape and …/scale; POST …/reshape/preview; POST …/discard-old-database
Storage GET, POST on /environments/{id}/storage/split, …/storage/allowance and …/storage/{disk}/disk; POST …/storage/{disk}/move, …/storage/discard; GET, POST on /volumes/{id}/grow
Machines for it GET, POST on /environments/{id}/build-machines; POST …/build-machines/options for one provider's sizes
Backups GET, POST on /environments/{id}/backups; POST …/backups/{snapshot}/download, …/restore; DELETE …/backups/{snapshot}; GET, POST on …/sync; POST …/reset-database; GET, POST on …/backup-key
Checking a manifest POST /validate, POST /environments/{id}/validate (token)

Machines, tasks and support

Machines GET /servers; GET, POST on /servers/{id}/resize; POST /servers/{id}/reboot
Following GET /tasks, /tasks/{id}, /tasks/{id}/log (token); POST /tasks/{id}/cancel while nothing has started it
Activity GET /tasks narrows with team, project, environment, kind (deployments, backups, machines, configuration, maintenance) and type, newest first, limit up to 100 and before for the next page; GET /tasks/{id} carries the task's account — what the console's dialog shows — and ?include=log adds the end of a log you may read
Support GET /teams/{id}/tickets/new; POST /teams/{id}/tickets, as multipart/form-data with screenshots as attachments[], or JSON without; POST /tickets/{id}/replies with {body, resolved}

A few things worth knowing before you script against them:

  • Deploys are refused, not queued, while another is running on the same environment — you get a 409. Wait for the task and try again. See Deployments.
  • Deploy, redeploy and rollback return a task. Poll /tasks/{id} to learn how it ended, and read /tasks/{id}/log for what it printed.
  • The activity list is the console's. The console's Activity page, its task dialog and its bell read /tasks, /tasks/{id} and /teams/{id}/notifications — what you script against is what you see there. Page with next_before: pass it back as before.
  • Poll with the ETag. /tasks and /teams/{id}/notifications answer with an ETag. Send it back as If-None-Match and an answer that has not changed is a 304 with no body. It still counts towards how often you can call it.
  • deploy and redeploy take {"skip_steps": true} to put the release live without running the deploy steps from vallic.yaml. See the first deploy.
  • rollback deploys the release that was running before the last successful deployment. It is code only; see going back.
  • A domain past the project's allowance is refused with a 409, domain_allowance_spent. See how many domains.
  • Adding a domain takes the hostname and nothing else. Making a domain canonical and declaring a CDN in front of it are done in the console. See Domains.
  • Verification is throttled to twelve checks an hour per domain; past that you get a 429.
  • What cannot be taken back asks to be confirmed. Cancelling a project or a subscription and copying another environment's data in want "confirm": true in the body; resetting a database wants the environment's name as confirm. Without it you get a 422 on confirm and nothing happens.
  • Some changes want a recent sign-in. Restoring over a protected production environment, among others, answers a 403 reauthentication_required when your sign-in is older than it allows. Sign in again and repeat the request; the console sends you through it and back.
  • Revealing a backup key is its own POST. GET …/backup-key says what the key opens; the key itself comes only from the POST, and every reveal is written in the activity log.

How often you can call it

Two limits, and only one of them is about how busy you are.

Six hundred requests a minute per token. Past that you get a 429 and should wait and repeat the request unchanged. It is a ceiling for a loop that has lost its sleep, not a budget to plan against — a pipeline doing real work will not come near it. The count is per token, not per person or per team, so a runaway script cannot lock your colleagues out, and whoever has to revoke it can still sign in.

If you are polling a task to see how a deploy ended, poll it every few seconds rather than as fast as the loop will go. Nothing goes faster for being asked more often.

Repeatedly presenting a credential that does not work gets your address refused with a 429 for a while, whatever token you try next. A token is a bearer credential — whoever holds the string is you — so guessing has to cost something. Calling an endpoint with no Authorization header at all does not count against this: that is a 401 and nothing more, so a forgotten header cannot lock out an office that shares one address.

Presenting a token that worked clears the count, so an occasional typo in a pipeline costs you nothing once the right one goes through.

Next