HTTP API reference
Base URL: https://www.security.run. Requests and responses use JSON. Authenticate private routes with Authorization: Bearer YOUR_SECURITY_RUN_CREDENTIAL. See Authentication before using the API.
Catalog and account
| Method | Path | Result |
|---|---|---|
| GET | /healthz |
Public service health. |
| GET | /v1/images |
Public image catalog under images, with credit rates. |
| GET | /v1/billing/config |
Public billing availability and trial settings. |
| GET | /auth/me |
Authenticated owner identity. |
| GET | /v1/billing/account |
Remaining, promotional, paid and spent credits; account limits. |
| GET | /v1/billing/history |
Recent credit activity under entries; each entry has amount_credits, kind, and Unix at time. |
| GET | /v1/billing/statements |
Stripe balance expressed in credits, plus invoices and hosted statement URLs. |
curl --fail-with-body https://www.security.run/v1/billing/account \
-H "Authorization: Bearer $SECURITY_RUN_API_KEY"
Read hourly_credits and egress_gib_credits from each image's pricing. Use the current catalog IDs rather than guessing image names. Older USD fields remain compatibility aliases; new clients should use credit fields.
Security desktop images have desktop: true and access: "rdp". Parrot, SIFT and REMnux also support SSH. Their sizes array contains Standard only; the gallery and SDKs use the same catalog.
Quote a session
POST /v1/sessions/quote accepts the same session input as launch. It returns rates, max_credits, egress_budget_credits, ttl_seconds, and the concurrency limit. These are informational upper limits. It does not create a session or spend credits, and launch does not require the full quoted amount.
curl --fail-with-body https://www.security.run/v1/sessions/quote \
-H "Authorization: Bearer $SECURITY_RUN_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"image":"ubuntu-24.04","ttl_seconds":1800,"egress_budget_credits":10}'
Create a session
POST /v1/sessions requires an Idempotency-Key header and returns 202 Accepted with a session object.
| Input | Type | Constraints |
|---|---|---|
image |
string, required | Exact catalog ID, such as ubuntu-24.04. |
ttl_seconds |
integer | 300–14,400; trial accounts are limited to 1,800. The raw HTTP default is 3,600, so explicitly send 1,800 for trial sessions. |
egress_budget_credits |
integer | 10–500; default 50. |
Idempotency-Key header |
string, required | 1–128 characters; unique per logical launch and reused for identical retries. |
curl --fail-with-body https://www.security.run/v1/sessions \
-H "Authorization: Bearer $SECURITY_RUN_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: case-482-linux' \
--data '{"image":"ubuntu-24.04","ttl_seconds":1800,"egress_budget_credits":10}'
The response includes id, image, state, ip, browser_url, created_at, expires_at, cleanup_status, and billing information. IP can be null until ready. Native credentials are retrieved separately. Timestamps are Unix seconds.
Use the exact same idempotency key and body after an uncertain response. A changed request body under a used key conflicts. A key does not create another VM when the original session has ended; use a new key for a new session.
Read, connect and destroy
| Method | Path | Result |
|---|---|---|
| GET | /v1/sessions |
Owner-scoped sessions array and next_cursor. |
| GET | /v1/sessions/{id} |
Current session without native credentials. |
| GET | /v1/sessions/{id}/connection |
Ready session plus native connection details. |
| POST | /v1/sessions/{id}/browser |
Short-lived, owner-authorized browser-gateway handoff URL. Normally handled by the web app. |
| DELETE | /v1/sessions/{id} |
Request teardown; 202 does not mean cleanup is already complete. |
For listing, send the returned next_cursor as the URL-encoded cursor query parameter until it is null. Both SDKs follow these pages automatically. A cursor belongs to its authenticated owner.
Poll a session with a delay of a few seconds while it starts. Once state is ready, retrieve /connection. It returns ip, port, protocol, browser_url, and a credentials object. Open the regular browser_url in the web app; it still requires the owner's sign-in.
For Linux security desktops, protocol is rdp, port is 3389, and ssh_port is 22. The same response contains both a desktop password and an SSH private_key, along with their shared username. Always use the returned username: SIFT uses sansforensics, REMnux uses remnux, and Parrot uses runner. Windows/FLARE credentials contain a password and have no SSH port.
curl --fail-with-body https://www.security.run/v1/sessions/ses_YOUR_SESSION_ID \
-H "Authorization: Bearer $SECURITY_RUN_API_KEY" \
-X DELETE
Poll until the terminal state and inspect cleanup_status. Repeat DELETE safely if the response was lost. There is no session extension, pause/resume, snapshot, in-place size-change, or remote command execution endpoint in this release.
Checkout
POST /v1/billing/checkout requires an Idempotency-Key and one of these JSON bodies:
{"kind":"trial","amount_usd":0}
{"kind":"topup","amount_usd":10}
Supported top-up amounts are 10, 25, 50 and 100 USD. These are purchase prices, not usage balances. The result contains an id and a Stripe-hosted url. Open that URL to complete card verification or payment; do not collect raw card details yourself.
GET /v1/billing/checkouts/{id} returns checkout fulfillment state. fulfilled means credits were granted; failed or rejected includes a reason. Any other state can still be pending. A successful browser redirect alone does not grant credits: verified Stripe webhook processing does.
Error responses
Errors normally include a human-readable detail. Billing errors also have a machine-readable code; request validation can return a structured detail array.
| Status | Typical meaning | Action |
|---|---|---|
| 400 | Invalid amount or cursor | Correct the request. |
| 401 | Missing, expired or invalid credential | Sign in again or check the supplied credential. |
| 402 | Not enough credits for the compute minimum | Add credits or activate an eligible trial. |
| 403 | Email confirmation, trial limit, or account hold | Follow the reason in the response. |
| 404 | Session/image unavailable to this owner | Check the ID, catalog and identity. |
| 409 | Not ready or conflicting request | Wait for readiness, or fix idempotency-key reuse. |
| 422 | Invalid request fields | Check names, types and limits. |
| 429 | Rate, concurrency or capacity limit | Back off; finish an existing session when applicable. |
| 503 | Temporary service or billing unavailability | Retry with backoff and preserve the launch key. |
The SDKs retry transient network failures and HTTP 429/502/503/504 up to three attempts. They do not turn a timeout into cancellation. See Troubleshooting for recovery steps.
Size and inactivity options
POST /v1/sessions and /v1/sessions/quote accept size: "small" | "standard". Omit it for Small on basic Linux terminals or Standard on desktops. Unsupported combinations fail before allocation. GET /v1/images includes the default size, resource specifications, pricing, and a sizes array. Existing sessions keep their launch size and rate.
Session creation also accepts idle_timeout_seconds: 0 | 900 (default 0 for API clients). The browser sends 900. The idle timer begins when the guest becomes ready. An authenticated POST /v1/sessions/{id}/activity records activity using server time. PATCH /v1/sessions/{id}/idle with {"enabled": false} disables idle cleanup; true re-enables it and resets the 15-minute timer. These operations are owner-scoped and never extend expires_at. Metadata includes idle_timeout_seconds and, when enabled, idle_expires_at.