API Reference

REST API for managing particles, accounts, and billing programmatically.

Base URL

All API requests are made to:

https://api.runparticle.com/v1

All requests and responses use JSON. Include Content-Type: application/json for request bodies.

Authentication

Authenticate every request with your API key in the Authorization header:

Authorization: Bearer <api_key>

Your API key is stored locally at ~/.config/particle/credentials after your first CLI interaction. The only endpoint that does not require authentication is POST /v1/accounts (account creation).

Accounts

Create and manage your RunParticle account.

POST /v1/accounts

Auto-create a new account. Your SSH public key becomes your identity. Returns an API key for subsequent requests.

Request body

FieldTypeDescription
public_keystringYour SSH public key (e.g. contents of ~/.ssh/id_ed25519.pub)

Example request

curl
$ curl -X POST https://api.runparticle.com/v1/accounts \
  -H 'Content-Type: application/json' \
  -d '{"public_key": "ssh-ed25519 AAAA... user@host"}'

Example response

json — 201 Created
{
  "account_id": "a1b2c3d4e5f6",
  "api_key": "pk_a1b2c3d4e5f6..."
}
GET /v1/account

Get your account info including balance and particle count.

Example request

curl
$ curl https://api.runparticle.com/v1/account \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "id": "a1b2c3d4e5f6",
  "balance_cents": 976,
  "recovery_email": "user@example.com",
  "created_at": "2026-03-01T00:00:00Z"
}
PUT /v1/account/email

Set or update your recovery email. Used to recover your account if you lose your SSH key.

Request body

FieldTypeDescription
emailstringRecovery email address

Example request

curl
$ curl -X PUT https://api.runparticle.com/v1/account/email \
  -H 'Authorization: Bearer rp_k1_a1b2c3...' \
  -H 'Content-Type: application/json' \
  -d '{"email": "user@example.com"}'

Example response

json — 200 OK
{
  "email": "user@example.com"
}
POST /v1/account/recover

Send a new API key to your recovery email. Use this when you need to access your account from a new machine without your original SSH key.

Request body

FieldTypeDescription
emailstringThe recovery email on your account

Example request

curl
$ curl -X POST https://api.runparticle.com/v1/account/recover \
  -H 'Content-Type: application/json' \
  -d '{"email": "user@example.com"}'

Example response

json — 200 OK
{
  "message": "Recovery email sent"
}
POST /v1/account/rotate-key

Rotate your API key. Generates a new key and invalidates the old one.

Example request

curl
$ curl -X POST https://api.runparticle.com/v1/account/rotate-key \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "api_key": "pk_n3w4k5e6y7...",
  "message": "API key rotated. Old key is now invalid."
}

Images

List available OS images for creating particles.

GET /v1/images

List all available base OS images.

Example request

curl
$ curl https://api.runparticle.com/v1/images \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "images": [
    {
      "id": "ubuntu-24.04",
      "name": "ubuntu-24.04",
      "display_name": "Ubuntu 24.04 LTS",
      "default": true
    },
    {
      "id": "debian-12",
      "name": "debian-12",
      "display_name": "Debian 12 (Bookworm)",
      "default": false
    }
  ]
}

Particles

Create, manage, and monitor cloud VMs.

POST /v1/particles

Create and start a new particle.

Request body

FieldTypeDescription
namestringName for the particle (used as subdomain)
sizestringVM size tier: p1p5. Default: p1
imagestringBase OS image (e.g. ubuntu-24.04, debian-12). Default: ubuntu-24.04. See GET /v1/images for available options.

Example request

curl
$ curl -X POST https://api.runparticle.com/v1/particles \
  -H 'Authorization: Bearer rp_k1_a1b2c3...' \
  -H 'Content-Type: application/json' \
  -d '{"name": "myapp", "size": "p2"}'

Example response

json — 201 Created
{
  "id": "abc123",
  "name": "myapp",
  "size": "p2",
  "status": "running",
  "http_port": 80,
  "image": "ubuntu-24.04",
  "created_at": "2026-03-06T12:00:00Z"
}
GET /v1/particles

List all particles on your account.

Example request

curl
$ curl https://api.runparticle.com/v1/particles \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "particles": [
    {
      "id": "abc123",
      "name": "myapp",
      "size": "p2",
      "status": "running",
      "idle_policy": "sleep",
      "created_at": "2026-03-06T12:00:00Z"
    },
    {
      "id": "def456",
      "name": "staging",
      "size": "p1",
      "status": "stopped",
      "idle_policy": "sleep",
      "created_at": "2026-03-05T10:00:00Z"
    }
  ]
}
GET /v1/particles/:name

Get detailed info about a specific particle.

Example request

curl
$ curl https://api.runparticle.com/v1/particles/myapp \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "id": "abc123",
  "name": "myapp",
  "size": "p2",
  "status": "running",
  "http_port": 80,
  "image": "ubuntu-24.04",
  "idle_policy": "sleep",
  "created_at": "2026-03-06T12:00:00Z"
}
POST /v1/particles/:name/start

Start a stopped particle. Resumes from where it left off with disk intact.

Example request

curl
$ curl -X POST https://api.runparticle.com/v1/particles/myapp/start \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "id": "abc123",
  "name": "myapp",
  "size": "p2",
  "status": "running",
  "http_port": 80,
  "idle_policy": "sleep",
  "created_at": "2026-03-06T12:00:00Z"
}
POST /v1/particles/:name/stop

Stop a running particle. Disk is preserved. You're only charged the stopped storage rate.

Example request

curl
$ curl -X POST https://api.runparticle.com/v1/particles/myapp/stop \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "id": "abc123",
  "name": "myapp",
  "size": "p2",
  "status": "stopped",
  "http_port": 80,
  "idle_policy": "sleep",
  "created_at": "2026-03-06T12:00:00Z",
  "stopped_at": "2026-03-07T14:00:00Z"
}
DELETE /v1/particles/:name

Permanently delete a particle and its disk. This action cannot be undone.

Example request

curl
$ curl -X DELETE https://api.runparticle.com/v1/particles/myapp \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

204 No Content
(empty response)
GET /v1/particles/:name/logs

Get serial console output for a particle. Useful for debugging boot issues.

Example request

curl
$ curl https://api.runparticle.com/v1/particles/myapp/logs \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "logs": "[    0.000000] Linux version 6.1.0 ...\n[    1.234567] EXT4-fs: mounted filesystem\n...",
  "offset": 4096,
  "status": "running"
}
GET /v1/particles/:name/status

Get detailed VM stats including uptime, resource usage, and idle policy.

Example request

curl
$ curl https://api.runparticle.com/v1/particles/myapp/status \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "id": "abc123",
  "name": "myapp",
  "size": "p2",
  "status": "running",
  "http_port": 80,
  "image": "ubuntu-24.04",
  "created_at": "2026-03-06T12:00:00Z",
  "idle_policy": "sleep",
  "vm_stats": {
    "vcpus": 2,
    "memory_total_bytes": 4294967296,
    "disk_total_bytes": 21474836480,
    "uptime_seconds": 13320,
    "vm_state": "Running"
  },
  "network_peers": 1,
  "healthy": true
}
POST /v1/particles/:name/duplicate

Clone a stopped particle to a new one. Creates an exact copy of the disk.

Request body

FieldTypeDescription
namestringName for the cloned particle

Example request

curl
$ curl -X POST https://api.runparticle.com/v1/particles/myapp/duplicate \
  -H 'Authorization: Bearer rp_k1_a1b2c3...' \
  -H 'Content-Type: application/json' \
  -d '{"name": "myapp-copy"}'

Example response

json — 201 Created
{
  "id": "def456",
  "name": "myapp-copy",
  "size": "p2",
  "status": "stopped",
  "http_port": 0,
  "created_at": "2026-03-07T14:00:00Z"
}
POST /v1/particles/:name/rebuild

Replace the particle's disk with a fresh copy of its base image. The particle must be stopped. Erases all data but keeps name, IP, and account.

Query parameters

FieldTypeDescription
imagestringOptional. Switch to a different base image (e.g. debian-12)

Example request

curl
$ curl -X POST https://api.runparticle.com/v1/particles/myapp/rebuild \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "id": "abc123",
  "name": "myapp",
  "size": "p2",
  "status": "stopped",
  "http_port": 80,
  "image": "ubuntu-24.04",
  "idle_policy": "sleep",
  "created_at": "2026-03-06T12:00:00Z",
  "stopped_at": "2026-03-07T10:00:00Z"
}
POST /v1/particles/:name/rename

Rename a particle. Updates the HTTP route to the new subdomain.

Request body

FieldTypeDescription
namestringNew name for the particle

Example request

curl
$ curl -X POST https://api.runparticle.com/v1/particles/myapp/rename \
  -H 'Authorization: Bearer rp_k1_a1b2c3...' \
  -H 'Content-Type: application/json' \
  -d '{"name": "production"}'

Example response

json — 200 OK
{
  "id": "abc123",
  "name": "production",
  "size": "p2",
  "status": "running",
  "http_port": 80,
  "idle_policy": "sleep",
  "created_at": "2026-03-06T12:00:00Z"
}
PUT /v1/particles/:name/resize

Resize a particle to a different size tier. The particle must be stopped.

Request body

FieldTypeDescription
sizestringTarget size tier: p1, p2, p4, p8, p16

Example request

curl
$ curl -X PUT https://api.runparticle.com/v1/particles/myapp/resize \
  -H 'Authorization: Bearer rp_k1_a1b2c3...' \
  -H 'Content-Type: application/json' \
  -d '{"size": "p4"}'

Example response

json — 200 OK
{
  "id": "abc123",
  "name": "myapp",
  "size": "p4",
  "status": "stopped",
  "http_port": 80,
  "idle_policy": "sleep",
  "created_at": "2026-03-06T12:00:00Z"
}
PUT /v1/particles/:name/port

Set the default HTTP port that the proxy forwards traffic to for a particle. Default is 80. Any port can also be accessed directly via the URL pattern <name>-<port>-<acct>.runparticle.com.

Request body

FieldTypeDescription
http_portintegerPort number (1–65535)

Example request

curl
$ curl -X PUT https://api.runparticle.com/v1/particles/myapp/port \
  -H 'Authorization: Bearer rp_k1_a1b2c3...' \
  -H 'Content-Type: application/json' \
  -d '{"http_port": 8080}'

Example response

json — 200 OK
{
  "id": "abc123",
  "name": "myapp",
  "size": "p2",
  "status": "running",
  "http_port": 8080,
  "idle_policy": "sleep",
  "created_at": "2026-03-06T12:00:00Z"
}
PUT /v1/particles/:name/idle

Set the idle policy for a particle. Controls what happens when no SSH or HTTP activity is detected. Default policy is sleep (stops after 2 minutes of inactivity).

Request body

FieldTypeDescription
policystringOne of: none, on, sleep, schedule

Example request

curl
$ curl -X PUT https://api.runparticle.com/v1/particles/myapp/idle \
  -H 'Authorization: Bearer rp_k1_a1b2c3...' \
  -H 'Content-Type: application/json' \
  -d '{"policy": "on"}'

Example response

json — 200 OK
{
  "id": "abc123",
  "name": "myapp",
  "size": "p2",
  "status": "running",
  "http_port": 80,
  "idle_policy": "on",
  "created_at": "2026-03-06T12:00:00Z"
}
POST /v1/particles/:name/exec

Execute a command on a running particle via SSH and return the output.

Request body

FieldTypeDescription
commandstringThe shell command to execute

Example request

curl
$ curl -X POST https://api.runparticle.com/v1/particles/myapp/exec \
  -H 'Authorization: Bearer rp_k1_a1b2c3...' \
  -H 'Content-Type: application/json' \
  -d '{"command": "apt update"}'

Example response

json — 200 OK
{
  "exit_code": 0,
  "output": "Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease\nReading package lists... Done"
}

Snapshots

Create, list, restore, and delete point-in-time snapshots of a particle's disk.

POST /v1/particles/:name/snapshots

Create a named snapshot of a particle's disk.

Request body

FieldTypeDescription
namestringName for the snapshot

Example request

curl
$ curl -X POST https://api.runparticle.com/v1/particles/myapp/snapshots \
  -H 'Authorization: Bearer rp_k1_a1b2c3...' \
  -H 'Content-Type: application/json' \
  -d '{"name": "before-deploy"}'

Example response

json — 201 Created
{
  "id": "snap_a1b2c3",
  "particle_id": "myapp",
  "name": "before-deploy",
  "size_bytes": 2147483648,
  "created_at": "2026-03-07T10:30:00Z"
}
GET /v1/particles/:name/snapshots

List all snapshots for a particle.

Example request

curl
$ curl https://api.runparticle.com/v1/particles/myapp/snapshots \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "snapshots": [
    {
      "id": "snap_a1b2c3",
      "name": "before-deploy",
      "size_bytes": 2147483648,
      "created_at": "2026-03-07T10:30:00Z"
    }
  ]
}
POST /v1/particles/:name/snapshots/:snapshot/restore

Restore a snapshot. The particle must be stopped.

Example request

curl
$ curl -X POST https://api.runparticle.com/v1/particles/myapp/snapshots/before-deploy/restore \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "status": "restored"
}
DELETE /v1/particles/:name/snapshots/:snapshot

Delete a snapshot.

Example request

curl
$ curl -X DELETE https://api.runparticle.com/v1/particles/myapp/snapshots/before-deploy \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

204 No Content
(empty response)

Custom Domains

Set custom domains for your particles.

PUT /v1/particles/:name/domain

Set a custom domain for a particle. Point your domain's DNS to runparticle.com via a CNAME record.

Request body

FieldTypeDescription
domainstringCustom domain (e.g. app.example.com)

Example request

curl
$ curl -X PUT https://api.runparticle.com/v1/particles/myapp/domain \
  -H 'Authorization: Bearer rp_k1_a1b2c3...' \
  -H 'Content-Type: application/json' \
  -d '{"domain": "app.example.com"}'

Example response

json — 200 OK
{
  "id": "abc123",
  "name": "myapp",
  "size": "p2",
  "status": "running",
  "http_port": 80,
  "custom_domain": "app.example.com",
  "idle_policy": "sleep",
  "created_at": "2026-03-06T12:00:00Z"
}
DELETE /v1/particles/:name/domain

Remove the custom domain from a particle.

Example request

curl
$ curl -X DELETE https://api.runparticle.com/v1/particles/myapp/domain \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "id": "abc123",
  "name": "myapp",
  "size": "p2",
  "status": "running",
  "http_port": 80,
  "idle_policy": "sleep",
  "created_at": "2026-03-06T12:00:00Z"
}

SSH Keys

Manage SSH keys associated with your account.

GET /v1/keys

List all SSH keys on your account.

Example request

curl
$ curl https://api.runparticle.com/v1/keys \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "keys": [
    {
      "id": "a1b2c3d4",
      "public_key": "ssh-ed25519 AAAA... user@host",
      "name": "default",
      "created_at": "2026-03-01T00:00:00Z"
    },
    {
      "id": "e5f6g7h8",
      "public_key": "ssh-ed25519 BBBB... user@laptop",
      "name": "laptop",
      "created_at": "2026-03-05T00:00:00Z"
    }
  ]
}
POST /v1/keys

Add an SSH public key to your account.

Request body

FieldTypeDescription
public_keystringSSH public key contents

Example request

curl
$ curl -X POST https://api.runparticle.com/v1/keys \
  -H 'Authorization: Bearer rp_k1_a1b2c3...' \
  -H 'Content-Type: application/json' \
  -d '{"public_key": "ssh-ed25519 AAAA... user@laptop"}'

Example response

json — 201 Created
{
  "id": "i9j0k1l2",
  "name": "unnamed"
}
DELETE /v1/keys/:id

Remove an SSH key from your account.

Example request

curl
$ curl -X DELETE https://api.runparticle.com/v1/keys/2 \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

204 No Content
(empty response)

Billing

Manage your prepaid balance and view transaction history.

POST /v1/account/topup

Create a Stripe payment link to add funds. Returns a URL to complete the payment.

Request body

FieldTypeDescription
amountintegerAmount in cents to add (e.g. 2500 for $25.00). Minimum 1000 ($10).

Example request

curl
$ curl -X POST https://api.runparticle.com/v1/account/topup \
  -H 'Authorization: Bearer rp_k1_a1b2c3...' \
  -H 'Content-Type: application/json' \
  -d '{"amount": 2500}'

Example response

json — 200 OK
{
  "url": "https://checkout.stripe.com/c/pay/cs_live_..."
}
GET /v1/account/history

Get your transaction history including top-ups and usage charges.

Example request

curl
$ curl https://api.runparticle.com/v1/account/history \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "transactions": [
    {
      "id": "a1b2c3d4",
      "amount_cents": 2500,
      "type": "topup",
      "created_at": "2026-03-06T14:00:00Z"
    },
    {
      "id": "e5f6g7h8",
      "amount_cents": -24,
      "type": "usage",
      "created_at": "2026-03-06T15:00:00Z"
    }
  ]
}
GET /v1/account/usage

Get per-particle usage breakdown for a time period.

Query parameters

FieldTypeDescription
periodstringTime period: day, week, month, all. Default: month

Example request

curl
$ curl https://api.runparticle.com/v1/account/usage?period=month \
  -H 'Authorization: Bearer rp_k1_a1b2c3...'

Example response

json — 200 OK
{
  "period": "month",
  "start": "2026-03-01T00:00:00Z",
  "end": "2026-03-07T00:00:00Z",
  "total_cents": 130,
  "particles": [
    {
      "particle_id": "abc123",
      "name": "myapp",
      "size": "p2",
      "status": "running",
      "compute_hours": 48.2,
      "total_cents": 116
    }
  ]
}

Webhooks

Internal webhook endpoints used by third-party services.

POST /v1/stripe/webhook

Receives payment confirmation events from Stripe. This endpoint is called by Stripe, not by users directly. It verifies the webhook signature and credits the account balance upon successful payment.

Note: This endpoint is for Stripe's internal use. You do not need to call it directly. Payments are processed automatically after completing Stripe checkout.

CLI

Endpoints used by the particle CLI for self-management.

GET /v1/cli/version

Get the latest CLI version and download URL. Used by particle upgrade for self-updates. This endpoint is public and does not require authentication.

Example request

curl
$ curl https://api.runparticle.com/v1/cli/version

Example response

json — 200 OK
{
  "version": "abc1234"
}