# Hubvix API guide Hubvix provides an API for customer-authorized CI systems and AI agents to deploy and manage hosting projects owned by the account that issued the key. ## Service - Base URL: `https://api.hubvix.ru` - OpenAPI: `https://api.hubvix.ru/api/v1/openapi.json` - Human documentation: `https://hubvix.ru/developers` - Authentication: `Authorization: Bearer hvx_…` - Check account and balance: `GET /api/v1/me` -> `{ "id": 123, "balance_kopeks": 42000 }`. Send the key only as an HTTP header. Never place it in a URL, source file, browser storage, or logs. The full key is displayed once when a person creates it at `https://hubvix.ru/dashboard/profile/api`. `GET`, `POST`, and `DELETE /agent-keys` management actions require the human dashboard session; mutation requests require `X-HUBVIX-CSRF-Token`. Agent Bearer keys cannot mint or revoke keys. Create accepts `name` (1–100 characters), `scopes` (unique values from `read`, `deploy`, `manage`), and required `expires_in_seconds` (60–31,536,000 or `null`). The response includes metadata and one-time `key`; list and revoke return metadata only. Up to 100 active keys are allowed per account. Key creation requires a verified email, completed registration, and accepted user agreement. Changing the account password invalidates existing keys. Key scopes are independent: `read`, `deploy`, and `manage`. Read includes project code, logs, and runtime metadata, so treat even read-only keys as sensitive. `deploy` covers project and service deploy/start/stop/restart operations. `manage` covers configuration, hosting resources, tariff changes, and available deletion operations. A key with only `manage` does not automatically gain `read` or `deploy`. The dashboard's Deploy profile grants `read` + `deploy`; Full Access grants all three. The filtered OpenAPI specification is authoritative and tags every operation with `x-required-scope`. The API follows the account's ordinary ownership, agreement, tariff, balance, region, and resource checks. The owner must accept the current user agreement in the dashboard. An expired or revoked key cannot authorize a new request; a request already authenticated before revocation may finish. An already accepted job may finish after expiration; running applications continue under normal account billing. No automatic deletion occurs when a key expires. Account password confirmation is not delegated to an agent. ## Recommended deployment sequence Read `GET /api/v1/billing/balance` and `GET /api/v1/projects/tariffs`. Choose `region_group=ru` or `eu`, then query `GET /api/v1/projects/create-check?tariff_id={id}®ion_group={group}`. Proceed only when `can_create`, `can_allocate`, and `enough_balance` are all true. This check does not reserve capacity or funds; project creation checks again. A person must have accepted the current hosting/user agreement, and the account needs enough balance for the current admission rules. Create the workspace first without a draft: ```http POST /api/v1/projects/ Authorization: Bearer hvx_… Content-Type: application/json X-HUBVIX-Idempotency-Key: workspace-create-unique-001 {"name":"my-website","tariff_id":1,"region_group":"ru","services":[{"name":"web","language":"html","service_type":"web"}]} ``` Poll GET /api/v1/projects/{id} with pauses until creating becomes stopped and source_pending is true. This means allocated workspace ready, not a running application; reserved resources are billed. Upload multipart files (field files) using POST /api/v1/projects/{id}/files/upload. Read runtime, configure dependencies and launch commands as needed (manage scope), then POST /api/v1/projects/{id}/deploy with {}. Poll deployments until running and check the public URL. source_pending clears after successful first deploy. Upload does not automatically start the application. ## Optional legacy source-first workflow Existing integrations may still create a source draft before creating a project. This is optional; supplying draft_id retains the original create-and-deploy behavior. Create a source draft: ```http POST /api/v1/projects/drafts Authorization: Bearer hvx_… Content-Type: application/json {"source_type":"zip"} ``` Upload the archive as raw ZIP bytes, not as a multipart form: ```http PUT /api/v1/projects/drafts/{draft_id}/archive Authorization: Bearer hvx_… Content-Type: application/zip ``` Draft responses include `id`, `status`, detected `candidates`, and `expires_at`. Drafts expire after 24 hours. Use the returned `draft_id` to create the project: ```http POST /api/v1/projects/ Authorization: Bearer hvx_… Content-Type: application/json X-HUBVIX-Idempotency-Key: deploy-bot-20261019-0001 {"name":"my-service","tariff_id":12,"region_group":"ru","draft_id":""} ``` Keep the same idempotency key and exact body after an uncertain timeout. A completed matching request can replay its response for 24 hours; reusing a key with different content returns `409`. Use a new key for a different logical operation. Idempotency is supported only on selected endpoints; consult OpenAPI and the guide. Poll `GET /api/v1/projects/{id}` until `status` leaves `creating`; `GET /api/v1/projects/{id}/connection-status` checks host/runtime connectivity. Then inspect `GET /api/v1/projects/{id}/runtime`. Launch all active services with `POST /api/v1/projects/{id}/deploy` and `{}` or select services with `{"service_ids":[101,102]}`. The endpoint returns `202 Accepted` and deployment records. Poll `GET /api/v1/projects/{id}/deployments?limit=50`; intermediate statuses include `queued`, `building`, `prepared`, `switching`, and `pending_ingress`, with terminal `running` or `failed`. For the whole project use `POST /api/v1/projects/{project_ref}/restart`. For one non-cron service use `POST /api/v1/projects/{project_id}/services/{service_id}/action` with `{"action":"restart"}`. Cron runs are scheduled; inspect them through `GET /api/v1/projects/{project_id}/services/{service_id}/cron-runs`. Project stop uses `POST /api/v1/projects/{project_ref}/stop`. Reserved resources may remain billable; if the response requires confirmation, the account owner must decide whether to accept continued charges. Project deletion uses `DELETE /api/v1/projects/{project_ref}` with `{"project_name":""}` and deletes project data. Save any required source and data before using it. ## Runtime and resources - `GET /api/v1/projects/runtime-catalog`: supported runtime catalogue and add-on minimums. - `GET /api/v1/projects/{project_id}/runtime`: services, add-ons, routes, and resource totals. - `POST /api/v1/projects/{project_id}/services`: add a web, worker, or cron service. - `PUT /api/v1/projects/{project_id}/services/{service_id}`: update service configuration; required `name` and `language` make this a full configuration update, not a partial patch. - `POST /api/v1/projects/{project_id}/addons` with kind `postgres`, `mysql`, or `redis`: create a storage add-on. - `DELETE /api/v1/projects/{project_id}/addons/{addon_id}` without `confirmation`: detach while preserving data; restore with `POST /api/v1/projects/{project_id}/addons/{addon_id}/restore`. `confirmation=DELETE {kind}` physically deletes add-on data. - `POST /api/v1/projects/{project_id}/routes`: route a path to an active web service. The API creates the platform hostname. - `PUT /api/v1/projects/{project_id}/env-files?path={path}` with env file text as the raw UTF-8 body: store encrypted environment settings; the response contains metadata, not the value. - `GET /api/v1/projects/{project_id}/env-files`: list env file metadata. - `GET /api/v1/projects/{project_ref}/logs?kind=app&tail=100`: read app logs. Logs are redacted where possible. Detaching a service or add-on without `confirmation` preserves its persistent data. Physical data deletion requires exact confirmation query values, such as `confirmation=DELETE%20worker` or `confirmation=DELETE%20postgres`. Treat these operations as destructive and inspect current state before retrying. Password-confirmed operations, including revealing env contents and changing a custom domain, remain human dashboard actions. A human must accept the current user agreement before project creation. ## Errors and retries Most errors are JSON with `detail`. `401` means the key is invalid, expired, or revoked. `403` indicates missing scope, agreement, or a human confirmation requirement. `404` can mean the resource is absent or belongs to another account. On `409`, read the current operation state before trying again. For `429`, reduce request frequency, honor `Retry-After` if supplied, and apply exponential backoff. For a `5xx` on a mutation, check project/deployment state before retrying; reuse the same idempotency key and body only when the endpoint supports it. Never create another project or deployment just because a client timed out. ## Python account check ```python import os import requests api = "https://api.hubvix.ru" client = requests.Session() client.headers["Authorization"] = f"Bearer {os.environ['HUBVIX_AGENT_KEY']}" response = client.get(f"{api}/api/v1/me", timeout=20) response.raise_for_status() print(response.json()) ``` A key covers every hosting project owned by the account, including already-owned preview deployments. Project-specific restriction is not available. Internal Studio order-linked creation, contracts, payments, team and chat workflows are human-only, even when the key owner is a staff member.