API reference
Every v1 endpoint: parameters, request and response examples, errors and the scopes they need. The same schema as /api/v1/openapi.json.
Authentication and keys
Send the key on every private request in the header: Authorization: Bearer gpz_… A key is 44 characters: the gpz_ prefix and 40 letters and digits.
A key gives access to your account only. Browser sessions do not work with the API, on purpose.
Scopes: user:read and user:write cover the profile, SSH keys and API keys; instances:read and instances:write cover servers and your own templates; billing:read covers the balance and transactions. Top-ups and charges are not possible through the API: payments happen only in the console.
The secret is shown once, when the key is created. Keep it in an environment variable or a secret manager, not in code.
Revoke a key in the console or with DELETE /api-keys/{id}. A key cannot grant scopes that your own key does not have.
Authorization: Bearer gpz_…Environment variable: GPUNZ_API_KEY
Errors
Every error has an HTTP status and the same body: {"error": {"code": "…", "message": "…", "details": {…}}}. The code is stable, so branch on it. The message follows Accept-Language (Russian by default).
{
"error": {
"code": "insufficient_funds",
"message": "Insufficient funds: 120 RUB short. Top up your balance.",
"details": { "short_kop": 12000 }
}
}| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 404 | not_found | Not found, or it belongs to someone else |
| 422 | validation_error | Invalid input. details.issues lists the fields |
| 402 | insufficient_funds | Not enough money for 2 hours of runtime. details.short_kop is how much |
| 409 | conflict | The state does not allow it: price changed, already destroying, limit reached |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 503 | provider_unavailable | Temporary service unavailability. Retry later |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 400 | authorization_pending | Device flow: waiting for approval in the browser |
| 400 | slow_down | Device flow: polling too often |
| 400 | access_denied | Device flow: denied in the browser |
| 400 | expired_token | Device flow: the code expired or was already used |
Retry 5xx and 429 responses with exponential backoff. POST /instances is safe to retry because of the Idempotency-Key.
Limits
120 requests per minute per key, and 60 per minute per address without a key. The X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers show the budget. On 429, wait for Retry-After.
Lists take ?limit= (default 50, maximum 200). Get the next page with next_cursor. There are no offsets: the cursor stays stable while prices change.
Money is whole kopecks (fields *_kop); hourly prices are kopecks per hour (*_kop_h); currency RUB. Times are UTC in RFC 3339.
Public GETs (/gpus, /offers, /templates) send CORS headers and are cached for 60 seconds; everything else is Cache-Control: no-store.
Cursors are opaque: do not parse them or build them yourself.
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 117
X-RateLimit-Reset: 2
{ "data": [...], "next_cursor": "eyJ…" }Interruptible instances
An interruptible server costs less, but it can be stopped when the market price rises above your bid. The outbid status means it was interrupted.
GET /offers with type=interruptible lists such offers, and GET /gpus returns from_interruptible_kop_h. price.interruptible_kop_h is the price of the whole server in kopecks per hour.
An interruptible server is created with the same POST /instances and type: interruptible. When the market price rises above your bid, the server becomes outbid: the GPU is not billed while the disk is. Starting it places a new bid.
Account
Profile, balance and transactions
/api/v1/meCurrent user
Profile of the key owner.
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
Request
curl -X GET 'https://gpu.nz/api/v1/me' \
-H "Authorization: Bearer $GPUNZ_API_KEY"Response
{
"id": "u_01J9Z3K2Q7",
"email": "you@example.com",
"name": "Egor",
"created_at": "2026-09-01T10:00:00.000Z",
"two_factor": false,
"email_verified": true,
"telegram_linked": false
}/api/v1/balanceBalance and burn rate
Balance, available amount, burn rate per hour, and how many hours the money lasts at the current burn.
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
Request
curl -X GET 'https://gpu.nz/api/v1/balance' \
-H "Authorization: Bearer $GPUNZ_API_KEY"Response
{
"balance_kop": 250000,
"available_kop": 241250,
"credit_limit_kop": 0,
"burn_kop_h": 4120,
"runway_hours": 58.5,
"currency": "RUB"
}/api/v1/transactionsAccount transactions
Top-ups, rental and traffic charges, bonuses. Newest first.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| limitquery | integer | no | How many rows to return (1–200, default 50) |
| cursorquery | string | no | Cursor from the previous page's next_cursor |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 422 | validation_error | Invalid input. details.issues lists the fields |
Request
curl -X GET 'https://gpu.nz/api/v1/transactions' \
-H "Authorization: Bearer $GPUNZ_API_KEY"Response
{
"data": [
{
"id": "t_01J9Z4",
"at": "2026-10-10T11:00:00.000Z",
"type": "usage",
"amount_kop": -1850,
"description": "Instance rental",
"instance_id": "i_8f2KQ1xZ"
}
],
"next_cursor": null
}Catalog
GPUs, offers and templates
/api/v1/gpusGPU models
All GPU models with free GPU count and the cheapest price per card. Public, CORS enabled.
Request
curl -X GET 'https://gpu.nz/api/v1/gpus'Response
{
"data": [
{
"slug": "rtx-4090-24gb",
"name": "RTX 4090",
"vram_gb": 24,
"tier": "consumer",
"available_gpus": 42,
"from_kop_h": 2650,
"from_interruptible_kop_h": 1190
}
],
"next_cursor": null
}/api/v1/offersSearch offers
Servers available to rent, with filters and sorting. Prices are for the whole server, kopecks per hour. Public.
- Only offers available right now are listed. Page with next_cursor, not offsets.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| gpuquery | string | no | Comma-separated model slugs |
| num_gpusquery | string | no | GPUs per server: 1,2,4,8 (comma-separated) |
| min_gpusquery | integer | no | Minimum GPUs per server |
| typequery | "on_demand" | "interruptible" | no | on_demand (default) or interruptible |
| countryquery | string | no | ISO-2 country codes, comma-separated |
| min_reliabilityquery | number | no | Reliability from 0 to 1 |
| min_vram_gbquery | number | no | Minimum VRAM per GPU, GB |
| max_price_kop_hquery | integer | no | At most this many kopecks per hour (whole server, for the chosen type) |
| verifiedquery | boolean | no | Verified datacenters only |
| min_cudaquery | number | no | Minimum CUDA version, e.g. 12.4 |
| min_disk_gbquery | number | no | Minimum disk, GB |
| min_inet_down_mbpsquery | number | no | Minimum download, Mbit/s |
| orderquery | "price" | "-price" | "dlperf" | "dlperf_per_price" | "reliability" | "vram" | "inet_down" | no | price (default), -price, dlperf, dlperf_per_price, reliability, vram, inet_down |
| limitquery | integer | no | How many rows to return (1–200, default 50) |
| cursorquery | string | no | Cursor from the previous page's next_cursor |
Errors
| Status | Code | Meaning |
|---|---|---|
| 422 | validation_error | Invalid input. details.issues lists the fields |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
Request
curl -X GET \
'https://gpu.nz/api/v1/offers?gpu=rtx-4090-24gb%2Crtx-3090-24gb&country=DE%2CNL&limit=5'Response
{
"data": [
{
"id": "o_4Jx9Q2",
"available": true,
"verified": true,
"country": "DE",
"region": "Hesse",
"gpu": {
"slug": "rtx-4090-24gb",
"name": "RTX 4090",
"count": 2,
"vram_gb": 24,
"total_tflops": 165.2,
"mem_bw_gbs": 1008
},
"cpu": {
"name": "AMD EPYC 7543",
"cores": 16
},
"ram_gb": 128,
"disk": {
"max_gb": 1500,
"bw_mbps": 2400,
"name": null
},
"network": {
"up_mbps": 900,
"down_mbps": 950,
"ports": 4
},
"pcie": {
"gen": 4,
"bw_gbs": 31.5
},
"cuda_max": 12.8,
"driver": "550.120",
"reliability": 0.9987,
"max_duration_days": 120,
"dlperf": 88.4,
"price": {
"on_demand_kop_h": 5280,
"interruptible_kop_h": 2380,
"storage_kop_gb_month": 900,
"traffic_kop_gb": 0
}
}
],
"next_cursor": null
}/api/v1/offers/{id}One offer
Full specification and prices. Public.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| idpath | string | yes | offer id |
Errors
| Status | Code | Meaning |
|---|---|---|
| 404 | not_found | Not found, or it belongs to someone else |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
Request
curl -X GET 'https://gpu.nz/api/v1o_4Jx9Q2'Response
{
"id": "o_4Jx9Q2",
"available": true,
"verified": true,
"country": "DE",
"region": "Hesse",
"gpu": {
"slug": "rtx-4090-24gb",
"name": "RTX 4090",
"count": 2,
"vram_gb": 24,
"total_tflops": 165.2,
"mem_bw_gbs": 1008
},
"cpu": {
"name": "AMD EPYC 7543",
"cores": 16
},
"ram_gb": 128,
"disk": {
"max_gb": 1500,
"bw_mbps": 2400,
"name": null
},
"network": {
"up_mbps": 900,
"down_mbps": 950,
"ports": 4
},
"pcie": {
"gen": 4,
"bw_gbs": 31.5
},
"cuda_max": 12.8,
"driver": "550.120",
"reliability": 0.9987,
"max_duration_days": 120,
"dlperf": 88.4,
"price": {
"on_demand_kop_h": 5280,
"interruptible_kop_h": 2380,
"storage_kop_gb_month": 900,
"traffic_kop_gb": 0
}
}/api/v1/templatesTemplates
The template catalogue. With a key, your own templates are included (owner = me).
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
Request
curl -X GET 'https://gpu.nz/api/v1/templates' \
-H "Authorization: Bearer $GPUNZ_API_KEY"Response
{
"data": [
{
"slug": "pytorch-cuda12",
"name": "PyTorch + CUDA 12",
"description": "PyTorch 2.5 with CUDA 12.4 and Jupyter",
"image": "pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime",
"launch_mode": "ssh",
"ports": [
8888
],
"env": {},
"onstart": null,
"min_disk_gb": 20,
"recommended_disk_gb": 40,
"public": true,
"owner": "gpunz"
}
],
"next_cursor": null
}/api/v1/templatesCreate an own template
Your own Docker image with ports and variables. Visible only to you. Limit: 20 templates.
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Name |
| description | string | no | Description |
| image | string | yes | Docker image with a tag |
| launch_mode | "ssh" | "jupyter" | "entrypoint" | no | Launch mode (default ssh) |
| ports | array<integer> | no | Ports to publish |
| env | object | no | Environment variables (up to 30) |
| onstart | string | no | Command run at start |
| min_disk_gb | integer | no | Minimum disk |
| recommended_disk_gb | integer | no | Recommended disk |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 422 | validation_error | Invalid input. details.issues lists the fields |
| 409 | conflict | The state does not allow it: price changed, already destroying, limit reached |
Request
curl -X POST 'https://gpu.nz/api/v1/templates' \
-H "Authorization: Bearer $GPUNZ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "My trainer",
"image": "ghcr.io/me/trainer:1.2",
"ports": [
7860
],
"min_disk_gb": 40
}'Response
{
"slug": "pytorch-cuda12",
"name": "PyTorch + CUDA 12",
"description": "PyTorch 2.5 with CUDA 12.4 and Jupyter",
"image": "pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime",
"launch_mode": "ssh",
"ports": [
8888
],
"env": {},
"onstart": null,
"min_disk_gb": 20,
"recommended_disk_gb": 40,
"public": true,
"owner": "gpunz"
}/api/v1/templates/{slug}Delete an own template
Hides the template. Instances already created from it keep running.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| slugpath | string | yes | Template slug |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 404 | not_found | Not found, or it belongs to someone else |
Request
curl -X DELETE 'https://gpu.nz/api/v1pytorch-cuda12' \
-H "Authorization: Bearer $GPUNZ_API_KEY"SSH keys
Keys for server access
/api/v1/ssh-keysSSH keys
Keys attached to new instances.
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
Request
curl -X GET 'https://gpu.nz/api/v1/ssh-keys' \
-H "Authorization: Bearer $GPUNZ_API_KEY"Response
{
"data": [
{
"id": "k_9Qw1Zm",
"name": "laptop",
"type": "ssh-ed25519",
"fingerprint": "SHA256:5mkcWNm+GX3XK8EbRD+A6ieMSHyFHC0ysCe5CgbJRLM",
"created_at": "2026-09-01T10:00:00.000Z"
}
],
"next_cursor": null
}/api/v1/ssh-keysAdd an SSH key
A public key from the .pub file. Never send a private key.
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | no | Name (optional) |
| public_key | string | yes | Line from the .pub file |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 422 | validation_error | Invalid input. details.issues lists the fields |
Request
curl -X POST 'https://gpu.nz/api/v1/ssh-keys' \
-H "Authorization: Bearer $GPUNZ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "laptop",
"public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAc6078X+m8JF6aSSsBQjeBTnWzC726H37M3DAbeLVMg you@laptop"
}'Response
{
"id": "k_9Qw1Zm",
"name": "laptop",
"type": "ssh-ed25519",
"fingerprint": "SHA256:5mkcWNm+GX3XK8EbRD+A6ieMSHyFHC0ysCe5CgbJRLM",
"created_at": "2026-09-01T10:00:00.000Z"
}/api/v1/ssh-keys/{id}Delete an SSH key
New instances will not get the key. Running ones are not changed.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| idpath | string | yes | SSH key id |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 404 | not_found | Not found, or it belongs to someone else |
Request
curl -X DELETE 'https://gpu.nz/api/v1k_9Qw1Zm' \
-H "Authorization: Bearer $GPUNZ_API_KEY"Instances
Rental, control and logs
/api/v1/instancesInstances
Your instances. By default only live ones (not destroyed).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| statusquery | "active" | "all" | no | active (default) or all |
| limitquery | integer | no | How many rows to return (1–200, default 50) |
| cursorquery | string | no | Cursor from the previous page's next_cursor |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 422 | validation_error | Invalid input. details.issues lists the fields |
Request
curl -X GET 'https://gpu.nz/api/v1/instances' \
-H "Authorization: Bearer $GPUNZ_API_KEY"Response
{
"data": [
{
"id": "i_8f2KQ1xZ",
"name": "trainer",
"status": "running",
"desired_state": "running",
"type": "on_demand",
"gpu": {
"slug": "rtx-4090-24gb",
"name": "RTX 4090",
"count": 1,
"vram_gb": 24
},
"template": {
"slug": "pytorch-cuda12",
"name": "PyTorch + CUDA 12"
},
"image": "pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime",
"disk_gb": 40,
"country": "DE",
"price": {
"running_kop_h": 2640,
"stopped_kop_h": 24,
"traffic_kop_gb": 0
},
"cost_so_far_kop": 1850,
"ssh": {
"host": "203.0.113.10",
"port": 40122,
"user": "root",
"command": "ssh -p 40122 root@203.0.113.10"
},
"urls": [
{
"label": "8888",
"url": "http://203.0.113.10:41001/"
}
],
"created_at": "2026-10-10T11:00:00.000Z",
"started_at": "2026-10-10T11:02:00.000Z",
"stop_reason": null
}
],
"next_cursor": null
}/api/v1/instancesCreate an instance
Quotes the offer, locks the price and creates the instance. Send an Idempotency-Key header: a repeat with the same key does not create a second instance and returns the existing one (200).
Idempotent: a repeat with the same Idempotency-Key returns the same object
- 402 insufficient_funds: details.short_kop is how many kopecks are missing for the 2-hour runway.
- 403 forbidden with details.reason = email_not_verified: confirm your e-mail in the account.
- Interruptible instance: type: interruptible. When the price rises it becomes outbid (GPU not billed); start places a new bid.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| Idempotency-Keyheader | string | yes | Unique request key, up to 64 characters |
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| offer_id | string | yes | Offer id from GET /offers |
| template | string | yes | Template slug |
| disk_gb | integer | yes | Disk, GB |
| name | string | no | Name |
| ssh_key_ids | array<string> | no | Keys (default: all of yours) |
| type | "on_demand" | "interruptible" | no | Type (default on_demand) |
| image | string | no | Docker image, only for the custom template |
| env | object | no | Not supported yet: send an empty object or omit it |
| onstart | string | no | Not supported yet: send null or omit it |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 404 | not_found | Not found, or it belongs to someone else |
| 422 | validation_error | Invalid input. details.issues lists the fields |
| 402 | insufficient_funds | Not enough money for 2 hours of runtime. details.short_kop is how much |
| 409 | conflict | The state does not allow it: price changed, already destroying, limit reached |
| 503 | provider_unavailable | Temporary service unavailability. Retry later |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
Request
curl -X POST 'https://gpu.nz/api/v1/instances' \
-H "Authorization: Bearer $GPUNZ_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"offer_id": "o_4Jx9Q2",
"template": "pytorch-cuda12",
"disk_gb": 40,
"name": "trainer"
}'Response
{
"id": "i_8f2KQ1xZ",
"name": "trainer",
"status": "running",
"desired_state": "running",
"type": "on_demand",
"gpu": {
"slug": "rtx-4090-24gb",
"name": "RTX 4090",
"count": 1,
"vram_gb": 24
},
"template": {
"slug": "pytorch-cuda12",
"name": "PyTorch + CUDA 12"
},
"image": "pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime",
"disk_gb": 40,
"country": "DE",
"price": {
"running_kop_h": 2640,
"stopped_kop_h": 24,
"traffic_kop_gb": 0
},
"cost_so_far_kop": 1850,
"ssh": {
"host": "203.0.113.10",
"port": 40122,
"user": "root",
"command": "ssh -p 40122 root@203.0.113.10"
},
"urls": [
{
"label": "8888",
"url": "http://203.0.113.10:41001/"
}
],
"created_at": "2026-10-10T11:00:00.000Z",
"started_at": "2026-10-10T11:02:00.000Z",
"stop_reason": null
}/api/v1/instances/{id}Instance
State, access and cost of an instance.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| idpath | string | yes | instance id |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 404 | not_found | Not found, or it belongs to someone else |
Request
curl -X GET 'https://gpu.nz/api/v1i_8f2KQ1xZ' \
-H "Authorization: Bearer $GPUNZ_API_KEY"Response
{
"id": "i_8f2KQ1xZ",
"name": "trainer",
"status": "running",
"desired_state": "running",
"type": "on_demand",
"gpu": {
"slug": "rtx-4090-24gb",
"name": "RTX 4090",
"count": 1,
"vram_gb": 24
},
"template": {
"slug": "pytorch-cuda12",
"name": "PyTorch + CUDA 12"
},
"image": "pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime",
"disk_gb": 40,
"country": "DE",
"price": {
"running_kop_h": 2640,
"stopped_kop_h": 24,
"traffic_kop_gb": 0
},
"cost_so_far_kop": 1850,
"ssh": {
"host": "203.0.113.10",
"port": 40122,
"user": "root",
"command": "ssh -p 40122 root@203.0.113.10"
},
"urls": [
{
"label": "8888",
"url": "http://203.0.113.10:41001/"
}
],
"created_at": "2026-10-10T11:00:00.000Z",
"started_at": "2026-10-10T11:02:00.000Z",
"stop_reason": null
}/api/v1/instances/{id}Rename an instance
Only the name changes.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| idpath | string | yes | instance id |
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| name | stringnull | yes | New name (null clears it) |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 422 | validation_error | Invalid input. details.issues lists the fields |
| 404 | not_found | Not found, or it belongs to someone else |
Request
curl -X PATCH 'https://gpu.nz/api/v1i_8f2KQ1xZ' \
-H "Authorization: Bearer $GPUNZ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "trainer-2"
}'Response
{
"id": "i_8f2KQ1xZ",
"name": "trainer",
"status": "running",
"desired_state": "running",
"type": "on_demand",
"gpu": {
"slug": "rtx-4090-24gb",
"name": "RTX 4090",
"count": 1,
"vram_gb": 24
},
"template": {
"slug": "pytorch-cuda12",
"name": "PyTorch + CUDA 12"
},
"image": "pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime",
"disk_gb": 40,
"country": "DE",
"price": {
"running_kop_h": 2640,
"stopped_kop_h": 24,
"traffic_kop_gb": 0
},
"cost_so_far_kop": 1850,
"ssh": {
"host": "203.0.113.10",
"port": 40122,
"user": "root",
"command": "ssh -p 40122 root@203.0.113.10"
},
"urls": [
{
"label": "8888",
"url": "http://203.0.113.10:41001/"
}
],
"created_at": "2026-10-10T11:00:00.000Z",
"started_at": "2026-10-10T11:02:00.000Z",
"stop_reason": null
}/api/v1/instances/{id}/startStart
Starts a stopped instance. Requires a balance covering 2 hours of runtime.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| idpath | string | yes | instance id |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 402 | insufficient_funds | Not enough money for 2 hours of runtime. details.short_kop is how much |
| 404 | not_found | Not found, or it belongs to someone else |
| 409 | conflict | The state does not allow it: price changed, already destroying, limit reached |
Request
curl -X POST 'https://gpu.nz/api/v1i_8f2KQ1xZ' \
-H "Authorization: Bearer $GPUNZ_API_KEY"Response
{
"id": "i_8f2KQ1xZ",
"name": "trainer",
"status": "running",
"desired_state": "running",
"type": "on_demand",
"gpu": {
"slug": "rtx-4090-24gb",
"name": "RTX 4090",
"count": 1,
"vram_gb": 24
},
"template": {
"slug": "pytorch-cuda12",
"name": "PyTorch + CUDA 12"
},
"image": "pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime",
"disk_gb": 40,
"country": "DE",
"price": {
"running_kop_h": 2640,
"stopped_kop_h": 24,
"traffic_kop_gb": 0
},
"cost_so_far_kop": 1850,
"ssh": {
"host": "203.0.113.10",
"port": 40122,
"user": "root",
"command": "ssh -p 40122 root@203.0.113.10"
},
"urls": [
{
"label": "8888",
"url": "http://203.0.113.10:41001/"
}
],
"created_at": "2026-10-10T11:00:00.000Z",
"started_at": "2026-10-10T11:02:00.000Z",
"stop_reason": null
}/api/v1/instances/{id}/stopStop
Stops the instance. Only the disk is billed while stopped.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| idpath | string | yes | instance id |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 404 | not_found | Not found, or it belongs to someone else |
| 409 | conflict | The state does not allow it: price changed, already destroying, limit reached |
Request
curl -X POST 'https://gpu.nz/api/v1i_8f2KQ1xZ' \
-H "Authorization: Bearer $GPUNZ_API_KEY"Response
{
"id": "i_8f2KQ1xZ",
"name": "trainer",
"status": "running",
"desired_state": "running",
"type": "on_demand",
"gpu": {
"slug": "rtx-4090-24gb",
"name": "RTX 4090",
"count": 1,
"vram_gb": 24
},
"template": {
"slug": "pytorch-cuda12",
"name": "PyTorch + CUDA 12"
},
"image": "pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime",
"disk_gb": 40,
"country": "DE",
"price": {
"running_kop_h": 2640,
"stopped_kop_h": 24,
"traffic_kop_gb": 0
},
"cost_so_far_kop": 1850,
"ssh": {
"host": "203.0.113.10",
"port": 40122,
"user": "root",
"command": "ssh -p 40122 root@203.0.113.10"
},
"urls": [
{
"label": "8888",
"url": "http://203.0.113.10:41001/"
}
],
"created_at": "2026-10-10T11:00:00.000Z",
"started_at": "2026-10-10T11:02:00.000Z",
"stop_reason": null
}/api/v1/instances/{id}Destroy
Irreversible: the disk and its data are removed. Status becomes destroying, then destroyed.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| idpath | string | yes | instance id |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 404 | not_found | Not found, or it belongs to someone else |
| 409 | conflict | The state does not allow it: price changed, already destroying, limit reached |
Request
curl -X DELETE 'https://gpu.nz/api/v1i_8f2KQ1xZ' \
-H "Authorization: Bearer $GPUNZ_API_KEY"Response
{
"id": "i_8f2KQ1xZ",
"name": "trainer",
"status": "running",
"desired_state": "running",
"type": "on_demand",
"gpu": {
"slug": "rtx-4090-24gb",
"name": "RTX 4090",
"count": 1,
"vram_gb": 24
},
"template": {
"slug": "pytorch-cuda12",
"name": "PyTorch + CUDA 12"
},
"image": "pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime",
"disk_gb": 40,
"country": "DE",
"price": {
"running_kop_h": 2640,
"stopped_kop_h": 24,
"traffic_kop_gb": 0
},
"cost_so_far_kop": 1850,
"ssh": {
"host": "203.0.113.10",
"port": 40122,
"user": "root",
"command": "ssh -p 40122 root@203.0.113.10"
},
"urls": [
{
"label": "8888",
"url": "http://203.0.113.10:41001/"
}
],
"created_at": "2026-10-10T11:00:00.000Z",
"started_at": "2026-10-10T11:02:00.000Z",
"stop_reason": null
}/api/v1/instances/{id}/logsLogs
Last lines of the startup log.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| idpath | string | yes | instance id |
| tailquery | integer | no | How many lines (1–1000, default 200) |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 404 | not_found | Not found, or it belongs to someone else |
| 503 | provider_unavailable | Temporary service unavailability. Retry later |
Request
curl -X GET 'https://gpu.nz/api/v1i_8f2KQ1xZ' \
-H "Authorization: Bearer $GPUNZ_API_KEY"Response
{
"lines": [
"Starting container…",
"Ready."
]
}API keys
Issue and revoke keys
/api/v1/api-keysAPI keys
Your active keys (no secrets).
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
Request
curl -X GET 'https://gpu.nz/api/v1/api-keys' \
-H "Authorization: Bearer $GPUNZ_API_KEY"Response
{
"data": [
{
"id": "ak_3hT8Lw",
"name": "CI",
"prefix": "gpz_3fA9",
"scopes": [
"instances:read",
"instances:write"
],
"source": "console",
"last_used_at": "2026-10-10T11:30:00.000Z",
"created_at": "2026-10-01T09:00:00.000Z",
"expires_at": null
}
],
"next_cursor": null
}/api/v1/api-keysCreate a key
The secret is returned only in this response. You cannot grant permissions your key does not have.
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Name |
| scopes | array<"user:read" | "user:write" | "instances:read" | "instances:write" | "billing:read"> | yes | Permissions. You cannot grant more than your key has |
| expires_in_days | integernull | no | Lifetime in days (null — no expiry) |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 422 | validation_error | Invalid input. details.issues lists the fields |
| 409 | conflict | The state does not allow it: price changed, already destroying, limit reached |
Request
curl -X POST 'https://gpu.nz/api/v1/api-keys' \
-H "Authorization: Bearer $GPUNZ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "CI",
"scopes": [
"instances:read",
"instances:write"
],
"expires_in_days": 90
}'Response
{
"id": "ak_3hT8Lw",
"secret": "gpz_3fA9xK2mQp7vL0dR8sT4yW1bN6hJ5cE9fG2aZ8kP",
"name": "CI",
"prefix": "gpz_3fA9",
"scopes": [
"instances:read",
"instances:write"
],
"source": "api",
"last_used_at": null,
"created_at": "2026-10-10T09:00:00.000Z",
"expires_at": "2027-01-08T09:00:00.000Z"
}/api/v1/api-keys/{id}Revoke a key
The key stops working at once. You may revoke the key you are using.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| idpath | string | yes | key id |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No key, or the key is wrong, revoked or expired |
| 403 | forbidden | The key lacks the scope, or the account is blocked |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
| 404 | not_found | Not found, or it belongs to someone else |
Request
curl -X DELETE 'https://gpu.nz/api/v1ak_3hT8Lw' \
-H "Authorization: Bearer $GPUNZ_API_KEY"Terminal login
Device flow for gpunz login
/api/v1/auth/deviceTerminal login: start
Issues a device_code for the CLI and a short user_code for the browser. Codes live 10 minutes. Used by gpunz login.
Errors
| Status | Code | Meaning |
|---|---|---|
| 422 | validation_error | Invalid input. details.issues lists the fields |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
Request
curl -X POST 'https://gpu.nz/api/v1/auth/device' \
-H "Content-Type: application/json" \
-d '{
"client_name": "laptop"
}'Response
{
"device_code": "b1JQ3m7kZxR9aY2pD5sU8wE0tG4hK6nL1cV3fB7oM2i",
"user_code": "KQZD-7WXM",
"verification_uri": "https://gpu.nz/console/cli/auth",
"verification_uri_complete": "https://gpu.nz/console/cli/auth?code=KQZD-7WXM",
"expires_in": 600,
"interval": 3
}/api/v1/auth/device/tokenTerminal login: get the key
The CLI polls every interval seconds until the user approves the code in the browser. The key is issued once.
- While waiting: 400 authorization_pending. Polling too fast: 400 slow_down (increase the interval).
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| device_code | string | yes | device_code from POST /auth/device |
Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | authorization_pending | Device flow: waiting for approval in the browser |
| 400 | slow_down | Device flow: polling too often |
| 400 | access_denied | Device flow: denied in the browser |
| 400 | expired_token | Device flow: the code expired or was already used |
| 422 | validation_error | Invalid input. details.issues lists the fields |
| 429 | rate_limited | Too many requests. Retry-After says when to retry |
| 500 | internal | Internal error. Retry later; the request id helps support |
Request
curl -X POST 'https://gpu.nz/api/v1/auth/device/token' \
-H "Content-Type: application/json" \
-d '{
"device_code": "b1JQ3m7kZxR9aY2pD5sU8wE0tG4hK6nL1cV3fB7oM2i"
}'Response
{
"api_key": "gpz_9Kc2Lw8pQx4Rz1Tn6Vb3Mh7Jd0Fs5Ya2Ge8Xu1Pq",
"key_id": "ak_5qP2Vm",
"user": {
"email": "you@example.com"
}
}Objects
Fields that can be null are marked.
User
Profile of the key owner
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | yes | User id |
| stringnull | no | E-mail, null when not set | |
| name | string | yes | Display name |
| created_at | string | yes | Registration time |
| two_factor | boolean | no | Two-factor auth enabled |
| email_verified | boolean | no | E-mail is verified |
| telegram_linked | boolean | no | Telegram is linked |
Balance
Balance in kopecks; burn rate in kopecks per hour
| Name | Type | Required | Description |
|---|---|---|---|
| balance_kop | integer | no | Cash plus bonus, kopecks |
| available_kop | integer | no | Available now, including accrued but not yet posted usage |
| credit_limit_kop | integer | no | Credit limit |
| burn_kop_h | integer | no | Total burn across all instances, kopecks per hour |
| runway_hours | numbernull | no | Hours left at the current burn (null when idle) |
| currency | "RUB" | no | Currency |
Transaction
Wallet ledger entry
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | no | Transaction id |
| at | string | no | When it happened |
| type | "topup" | "usage" | "bandwidth" | "refund" | "promo_grant" | "promo_expire" | "adjustment" | "writeoff" | "reversal" | no | Kind of operation |
| amount_kop | integer | no | Balance change: positive is credit, negative is debit |
| description | string | no | Human description |
| instance_id | stringnull | no | Related instance id, if any |
GpuModel
GPU model with current supply
| Name | Type | Required | Description |
|---|---|---|---|
| slug | string | no | Model slug, used in the gpu= filter |
| name | string | no | Display name |
| vram_gb | integer | no | VRAM per GPU, GB |
| tier | "consumer" | "workstation" | "datacenter" | "legacy" | no | Class |
| available_gpus | integer | no | GPUs available right now |
| from_kop_h | integernull | no | Cheapest on-demand price per GPU, kopecks per hour |
| from_interruptible_kop_h | integernull | no | Cheapest interruptible price per GPU, kopecks per hour |
Offer
Offer: a server configuration with its price
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | yes | Offer id (used in POST /instances) |
| available | boolean | yes | Can be rented right now |
| verified | boolean | no | Verified datacenter |
| country | stringnull | no | Country, ISO-2 |
| region | stringnull | no | Region |
| gpu | object | yes | GPU |
| cpu | object | no | CPU |
| ram_gb | integernull | no | System RAM, GB |
| disk | object | no | Disk |
| network | object | no | Network |
| pcie | object | no | PCIe |
| cuda_max | numbernull | no | Highest CUDA version |
| driver | stringnull | no | Driver version |
| reliability | numbernull | no | Reliability, 0–1 |
| max_duration_days | integernull | no | Days left in the host contract |
| dlperf | numbernull | no | Deep-learning performance index |
| price | object | yes | Prices for the whole server (all GPUs), kopecks |
Template
Template: image and launch mode
| Name | Type | Required | Description |
|---|---|---|---|
| slug | string | no | Slug (used in template=) |
| name | string | no | Name |
| description | string | no | Description |
| image | string | no | Docker image |
| launch_mode | "ssh" | "jupyter" | "entrypoint" | no | Launch mode |
| ports | array<integer> | no | Container ports |
| env | object | no | Environment variables |
| onstart | stringnull | no | Command run at start |
| min_disk_gb | integer | no | Minimum disk, GB |
| recommended_disk_gb | integer | no | Recommended disk, GB |
| public | boolean | no | Visible to everyone |
| owner | "gpunz" | "me" | no | gpunz for the catalogue, me for your own template |
TemplateCreate
Own template
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Name |
| description | string | no | Description |
| image | string | yes | Docker image with a tag |
| launch_mode | "ssh" | "jupyter" | "entrypoint" | no | Launch mode (default ssh) |
| ports | array<integer> | no | Ports to publish |
| env | object | no | Environment variables (up to 30) |
| onstart | string | no | Command run at start |
| min_disk_gb | integer | no | Minimum disk |
| recommended_disk_gb | integer | no | Recommended disk |
SshKey
Public SSH key
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | no | Key id |
| name | string | no | Name |
| type | string | no | Key type |
| fingerprint | string | no | SHA256 fingerprint |
| created_at | string | no | Added |
SshKeyCreate
New SSH key
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | no | Name (optional) |
| public_key | string | yes | Line from the .pub file |
Instance
Instance (rental)
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | yes | Instance id |
| name | stringnull | no | Name |
| status | "creating" | "starting" | "running" | "stopping" | "stopped" | "destroying" | "destroyed" | "failed" | "outbid" | yes | Current state |
| desired_state | "running" | "stopped" | "destroyed" | no | Where it is heading |
| type | "on_demand" | "interruptible" | yes | Rental type |
| gpu | object | yes | GPU |
| template | object | no | Template |
| image | string | no | Docker image |
| disk_gb | integer | no | Disk, GB |
| country | stringnull | no | Country, ISO-2 |
| price | object | yes | Prices, kopecks per hour |
| cost_so_far_kop | integer | no | Charged so far, kopecks |
| ssh | objectnull | no | SSH access (null until the port is assigned) |
| urls | array<object> | no | Web interfaces of the template |
| created_at | string | no | Created |
| started_at | stringnull | no | First time running |
| stop_reason | stringnull | no | Why it stopped: user, low_balance, admin, provider |
InstanceCreate
Parameters of a new instance
| Name | Type | Required | Description |
|---|---|---|---|
| offer_id | string | yes | Offer id from GET /offers |
| template | string | yes | Template slug |
| disk_gb | integer | yes | Disk, GB |
| name | string | no | Name |
| ssh_key_ids | array<string> | no | Keys (default: all of yours) |
| type | "on_demand" | "interruptible" | no | Type (default on_demand) |
| image | string | no | Docker image, only for the custom template |
| env | object | no | Not supported yet: send an empty object or omit it |
| onstart | string | no | Not supported yet: send null or omit it |
InstancePatch
Instance changes
| Name | Type | Required | Description |
|---|---|---|---|
| name | stringnull | yes | New name (null clears it) |
InstanceLogs
Last log lines of the instance
| Name | Type | Required | Description |
|---|---|---|---|
| lines | array<string> | no | Lines |
ApiKey
API key (without the secret)
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | no | Key id |
| name | string | no | Name |
| prefix | string | no | Start of the key, for recognition |
| scopes | array<"user:read" | "user:write" | "instances:read" | "instances:write" | "billing:read"> | no | Permissions |
| source | "console" | "cli" | "api" | no | Where it was issued |
| last_used_at | stringnull | no | Last used |
| created_at | string | no | Created |
| expires_at | stringnull | no | Expires (null — never) |
ApiKeyCreate
New key
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Name |
| scopes | array<"user:read" | "user:write" | "instances:read" | "instances:write" | "billing:read"> | yes | Permissions. You cannot grant more than your key has |
| expires_in_days | integernull | no | Lifetime in days (null — no expiry) |
ApiKeyCreated
New key with its secret. The secret is shown once
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | no | Key id |
| secret | string | no | Secret gpz_… (save it now) |
| name | string | no | Name |
| prefix | string | no | Start of the key |
| scopes | array<string> | no | Permissions |
| source | string | no | Where it was issued |
| last_used_at | stringnull | no | Last used |
| created_at | string | no | Created |
| expires_at | stringnull | no | Expires |
DeviceCode
Device login codes (gpunz login)
| Name | Type | Required | Description |
|---|---|---|---|
| device_code | string | no | Secret for the CLI, never shown to the user |
| user_code | string | no | Code the user confirms in the browser |
| verification_uri | string | no | Approval page |
| verification_uri_complete | string | no | Approval page with the code filled in |
| expires_in | integer | no | Lifetime, seconds |
| interval | integer | no | Minimum polling interval, seconds |
DeviceTokenRequest
Token request by device_code
| Name | Type | Required | Description |
|---|---|---|---|
| device_code | string | yes | device_code from POST /auth/device |
DeviceToken
Issued key (once)
| Name | Type | Required | Description |
|---|---|---|---|
| api_key | string | no | Secret gpz_… |
| key_id | string | no | Key id |
| user | object | no | Owner |