Create a pod
Creates a new pod. name is always required; supply exactly one of
gpu or cpu to select compute (a GPU or a CPU pod). Container
settings come from the body, from a template referenced by
templateId (body fields override the template’s), or both; image
is required unless templateId is set. See CreatePodRequest for
the full body.
Returns 201 with the created pod. Provisioning is asynchronous: the
pod starts in PROVISIONING, transitions through STARTING, and
reaches RUNNING once its container is healthy. Poll getPod (or
watch the pod’s status) to observe readiness rather than assuming
the pod is running when this call returns.
Checking what you can deploy
This endpoint places one specific GPU type. It does not search for capacity, and it does not fall back to a different GPU. To find out what is deployable before you call it, read the catalog:
- List GPU types
— GPU types with pricing, per-cloud ceilings, and, with
include=AVAILABILITY&product=POD, current pod stock. - List data centers
— locations, with
include=GPU_AVAILABILITYfor stock per data center.
Both accept filters that combine, so you can narrow by location and by
compute in one request — for example
GET /v2/catalog/datacenters?regions=EUROPE&include=GPU_AVAILABILITY
returns only European data centers, each carrying the GPU types
currently available there.
Deploying under region and GPU constraints
If you need a particular GPU in a particular geography, the working
pattern is read-then-create: narrow the catalog to an acceptable
(data center, GPU) set, then call this endpoint once per candidate in
your order of preference until one returns 201. The runnable sample
alongside this operation does exactly that.
Availability can change between the catalog read and the create call, so treat the catalog as a way to order your candidates, not as a reservation — a create can still fail for capacity on a GPU the catalog just reported as available.
Which failures are worth retrying:
| Status | Meaning | Do |
|---|---|---|
422 | The body does not match the contract. errors lists each violation. | Fix the request. Never retry. |
400 | The body matches the contract but was rejected — either it breaks a cross-field rule, or this GPU and data center combination could not be placed. | Try your next candidate. |
402 | Insufficient balance. | Stop; no candidate will succeed. |
403 | Your account cannot access the requested pool. | Skip this candidate, keep going. |
429 | Rate limited. | Back off using Retry-After, then resume. |
5xx | Transient upstream failure. | Retry the same candidate with backoff. |
400 covers both “your request breaks a rule” and “no capacity”,
because capacity exhaustion currently carries no machine-readable code
of its own — only a human-readable detail. A rule violation is
deterministic, so it fails identically on every candidate: if every
candidate returns 400, read the last detail as a problem with the
request rather than as absent capacity.
Authorizations
Runpod API key authentication. Generate an API key in the Runpod console and send it in the Authorization header as Bearer <api_key>. Keys are scoped to the permissions granted when created; requests may return 403 when a valid key lacks access to the requested resource or action.
Body
Request body for creating a pod. Exactly one of gpu or cpu
must be set — enforced at the handler layer. For CPU pods, memory
is derived by the API from the selected flavor's RAM multiplier;
clients provide only CPU flavor and vCPU count. CPU pods support
container disk and network volumes only; mounts.persistent is
invalid when cpu is set.
image is required unless templateId is set.
1"my-training-pod"
Arguments passed to the container entrypoint
""
Container disk in GB (ephemeral, wiped on restart)
x >= 150
Environment variables as key-value pairs
Docker image reference
"runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404"
Exposed ports, formatted as port/protocol
Container registry credential ID (for private images)
null
Cloud tier. Defaults to SECURE when omitted.
SECURE, COMMUNITY Preferred data centers for placement. Omit or pass an empty array to let the scheduler choose.
Enable global networking, giving the pod a private IP reachable across data centers. Requires an NVIDIA GPU and a global-networking-enabled data center (both enforced upstream). See GET /v2/catalog/datacenters (globalNetwork) for eligible data centers.
false
GPU request for a pod create. Carries the CUDA host constraints, which live here rather than at the body's top level so they are unrepresentable on a CPU pod.
Storage mounts attached to a pod. At-most-one of persistent or
network may be set today (mutually exclusive, enforced at the
handler with 400 if both are present). The network field is an
array for forward compatibility with eventual multi-network-volume
support, but maxItems is 1 today.
PATCH semantics:
- Omitting
mountsor sending{}leaves the existing mount unchanged. - An explicit
network: []is rejected with 400 (clearing mounts is not supported). - Mount kind is fixed at create — a PATCH that introduces a kind not present at create (persistent on a network pod, network on a persistent pod, or any mount on a previously-mountless pod) is rejected with 400.
- The
volumeIdof a network mount is immutable; a PATCH that names a differentvolumeIdis rejected with 400. - Partial mounts are not supported — every mount entry must
include the full schema (
size+pathfor persistent,volumeId+pathfor network). Missing required fields → 422.
Create-time flag telling the provisioner to start JupyterLab:
injects a generated JUPYTER_PASSWORD environment variable,
unless the request already sets one. Only images that honor
the convention start Jupyter from it (RunPod official images
do); expose 8888/http in ports to reach it.
Not part of the pod's readable config — never returned by GET and not changeable by PATCH.
true
Create-time flag telling the provisioner to set up SSH
access: injects a PUBLIC_KEY environment variable carrying
your account's registered SSH public keys, unless the request
already sets one. Requires registered keys (PUT /v2/account/ssh-keys) — with none registered the flag does
nothing and the pod has no SSH access. Only images that honor
the convention start sshd from it (all RunPod official images
do). Connect using the pod's ssh block; the ssh.direct
variant additionally needs a 22/tcp entry in ports.
Not part of the pod's readable config — never returned by GET and not changeable by PATCH.
true
ID of a pod template to base this pod on. The template is
resolved at create time into the same container settings you
could otherwise spread into this body (image, args, disk,
ports, env, registry, persistent mount, startSsh,
startJupyter, allowedCudaVersions); explicit body fields
override the template's, except env, which is merged per
key with body values winning. Sending either CUDA field
(gpu.allowedCudaVersions or gpu.minCudaVersion) replaces
the template's CUDA constraint entirely, and CPU pods ignore
it (like the persistent mount). The template is a one-time
source of settings: later template edits do not affect the
pod, and the created pod does not retain a link to the
template (template stays null). The template may be one
of your own or a public catalog template — see
GET /v2/catalog/templates (unknown or inaccessible ID →
404) — and must not be a serverless template (→ 422). CPU
pods do not inherit a template's persistent mount.
1"30zmvf89kd"
Response
Created
Reusable container configuration shared across templates, pods, and serverless endpoints. Adding a field here automatically propagates to all three resources.
Arguments passed to the container entrypoint
""
Container disk in GB (ephemeral, wiped on restart)
x >= 150
Environment variables as key-value pairs
Docker image reference
"runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404"
Exposed ports, formatted as port/protocol
Container registry credential ID (for private images)
null
"pod_abc123"
"my-training-pod"
Lifecycle status of a pod.
PROVISIONING— pod is being allocatedSTARTING— container is startingRUNNING— container is healthyEXITED— container exited (stopped)ERROR— container is in an unrecoverable error stateTERMINATED— pod has been permanently deleted
PROVISIONING, STARTING, RUNNING, EXITED, ERROR, TERMINATED Valid state transitions for the current status.
State transition to trigger on a pod.
start, stop, restart, terminate Storage mounts attached to a pod. At-most-one of persistent or
network may be set today (mutually exclusive, enforced at the
handler with 400 if both are present). The network field is an
array for forward compatibility with eventual multi-network-volume
support, but maxItems is 1 today.
PATCH semantics:
- Omitting
mountsor sending{}leaves the existing mount unchanged. - An explicit
network: []is rejected with 400 (clearing mounts is not supported). - Mount kind is fixed at create — a PATCH that introduces a kind not present at create (persistent on a network pod, network on a persistent pod, or any mount on a previously-mountless pod) is rejected with 400.
- The
volumeIdof a network mount is immutable; a PATCH that names a differentvolumeIdis rejected with 400. - Partial mounts are not supported — every mount entry must
include the full schema (
size+pathfor persistent,volumeId+pathfor network). Missing required fields → 422.
Cloud tier.
SECURE— Runpod-owned datacenter hardwareCOMMUNITY— community-hosted hardware
SECURE, COMMUNITY Data center where the pod is running (assigned by scheduler)
"US-TX-3"
CUDA version reported by the host machine. Retained while the pod is stopped — a stopped pod keeps its machine assignment and resumes onto the same host. Null means unknown or not applicable (CPU pods, or a host that has not reported one), not that CUDA is absent.
"12.8"
SSH connection details, via the Runpod proxy or directly to the pod's published 22/tcp port.
ID of the template this pod was created from
null
Current cost in USD per hour (0.0 when EXITED or TERMINATED)
0.35
Whether the pod is locked (prevents stopping or resetting)
false
Live utilization metrics. Null when the pod is not RUNNING.
"2026-03-13T20:00:00Z"
"2026-03-13T20:00:00Z"
Present for GPU pods; omitted from CPU pods.
Present for CPU pods; omitted from GPU pods.
Cluster membership; omitted from a standalone pod. Member pods are managed through /v2/clusters/{id} — they are excluded from GET /v2/pods by default (pass includeClusterPods=true to include them) and cannot be modified or deleted via the pod endpoints.