---
title: "Submit a managed async job"
method: POST
path: "/jobs/v1/runs"
---

# Submit a managed async job

`POST /jobs/v1/runs`

## Request

- Base URL: `https://api.run402.com`
- URL: `https://api.run402.com/jobs/v1/runs`
- Auth: HTTP bearer

## Headers

- `Idempotency-Key` string, required

## Request body

- ManagedJobSubmitRequest
  - `job_type` string, required: Whitelisted managed job type configured by run402.
  - `input` object, required
    - `input_json` object, required
  - `max_cost_usd_micros` integer, required: Hard customer charge ceiling in micro-USD.
  - `callback_url` string, uri: Optional absolute https URL pushed once when the job reaches a terminal state (completed/failed/cancelled), so you need not poll GET /jobs/v1/runs/{job_id}. http and malformed URLs are rejected (400 invalid_job_request, code INVALID_CALLBACK_URL). Delivery is durable (at-least-once, retried, dead-lettered) and unsigned; the body is the canonical webhook envelope { id, type, created_at, schema_version, idempotency_key, payload } where type is one of job_completed/job_failed/job_cancelled and payload is { job_id, status, artifacts?, error? }. The Run402-Webhook-Id header equals the idempotency_key (<job_id>:terminal) — dedupe on it and re-fetch authoritative state via GET before acting; the callback is a trigger, not the source of truth. Submit-only; never returned on read.

## Response `200`

Idempotency hit

- ManagedJobResponse
  - `job_id` string, required
  - `job_type` string, required
  - `status` 'queued' | 'running' | 'completed' | 'failed' | 'cancelled', required
  - `created_at` string, date-time, required
  - `started_at` string, date-time
  - `completed_at` string, date-time
  - `artifacts` object: Per-artifact download references for a completed job, keyed by filename. sha256/size_bytes are omitted for legacy jobs created before per-artifact integrity capture.
  - `metadata` object
    - `wall_seconds` integer
    - `cost_usd_micros` integer
    - `raw_cost_usd_micros` integer
    - `absorbed_overage_usd_micros` integer
    - `image_digest` string
    - `spot_rate_usd_hr_micros` integer
    - `on_demand_rate_usd_hr_micros` integer
    - `instance_type` string
    - `az` string
    - `peak_rss_gb` number
    - `interrupt_count` integer
    - `attempt_count` integer
    - `billing_status` string
  - `error` object
    - `code` string, required
    - `message` string, required

## Other responses

- `202`: Job accepted
- `409`: Idempotency-key conflict
- `429`: Project job quota exceeded
- `503`: Platform job queue full; Retry-After header is set

---

[API](https://skmtc.dev/run402/apis/run402-api.md) · [All operations](https://skmtc.dev/run402/apis/run402-api/llms.txt) · [OpenAPI document](https://skmtc.dev/run402/apis/run402-api/revisions/893607557f50?raw)
