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 loginsigns 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}/logfor 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 withnext_before: pass it back asbefore. - Poll with the ETag.
/tasksand/teams/{id}/notificationsanswer with anETag. Send it back asIf-None-Matchand an answer that has not changed is a304with no body. It still counts towards how often you can call it. deployandredeploytake{"skip_steps": true}to put the release live without running the deploy steps fromvallic.yaml. See the first deploy.rollbackdeploys 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": truein the body; resetting a database wants the environment's name asconfirm. Without it you get a 422 onconfirmand nothing happens. - Some changes want a recent sign-in. Restoring over a protected
production environment, among others, answers a 403
reauthentication_requiredwhen 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-keysays what the key opens; the key itself comes only from thePOST, 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
- Teams and people — the roles a token inherits
- Variables — what a pipeline most often sets