A one-off job runs a command in a separate container using an existing service's image. Use it for a finite task whose tools and required files are already in that image. It is distinct from a scheduled cron job, a pre-deploy command, or an SSH session in a running service.
Check the execution environment first
The current Bex job implementation copies the service's resolved image, falling back to its configured image if no resolved image is available. It does not copy the service's environment variables, secret files, persistent disks, registry pull credentials, or CPU/memory requests into the job. The container still has any environment and files built into its image.
This differs from Render's service-configuration inheritance. Do not use a
service's working database connection as proof that a one-off job can run its
migration command. Do not put credentials in startCommand: commands are saved
in job history. Private images may fail to pull without separately available
cluster credentials.
The API accepts and records planId, but the current job creation path does not
apply it as container resource settings. Namespace policies may impose their own
limits. Do not use that field as a resource-sizing guarantee.
Your installation needs configured control-plane storage (BEX_CP_DB_URI) and
Kubernetes access. Without that storage, the job API returns 503. Creating a
job requires developer or admin access; viewing requires resource-read access,
and cancellation requires operate access. See workspace roles.
Create a job
Use an API bearer token, the API URL for your installation, and a
service ID returned by Bex. The image must be available to the cluster and
contain sh and the command's dependencies.
Start with a harmless command to check the execution path:
curl --fail-with-body --silent --show-error \
-X POST "$BEX_API_URL/v1/services/$SERVICE_ID/jobs" \
-H "Authorization: Bearer $BEX_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"startCommand":"printf \"one-off job ready\\n\""}'Save the returned job id as JOB_ID. The response includes serviceId,
startCommand, planId, status, and timestamps as they become available.
A 201 response is not proof of execution: job creation can return a record
already marked failed if Kubernetes creation failed.
Observe completion
curl --fail-with-body --silent --show-error \
"$BEX_API_URL/v1/services/$SERVICE_ID/jobs/$JOB_ID" \
-H "Authorization: Bearer $BEX_TOKEN"Poll periodically, with a timeout appropriate to the task, until status is
succeeded, failed, or canceled. pending and running are not terminal. List and get operations
refresh nonterminal status from Kubernetes, but a temporary cluster error can
leave the last known status visible.
List history with GET /v1/services/{id}/jobs. It returns an array of
{job, cursor} entries. Use the returned cursor for subsequent pages. Supported
filters include status, createdBefore, createdAfter, startedBefore,
startedAfter, finishedBefore, finishedAfter, and limit.
Bex creates jobs with no automatic retry and no explicit job execution deadline. Finished Kubernetes jobs are eligible for cleanup after one hour; this is not a promise of one hour of application-log retention. An installation administrator can inspect the job and pod logs in the service's namespace. Do not assume the service log endpoint includes one-off job output.
Cancel or retry deliberately
curl --fail-with-body --silent --show-error \
-X POST "$BEX_API_URL/v1/services/$SERVICE_ID/jobs/$JOB_ID/cancel" \
-H "Authorization: Bearer $BEX_TOKEN"Cancellation requests deletion of the Kubernetes job and marks its record
canceled. Verify that the pod and any external work have stopped before
starting a replacement.
Canceling an already terminal job returns 409. Cancellation does not reverse
external writes that the command already made.
A retry is a new job. Inspect partial effects before creating it, and make the task safe to repeat. For failures, distinguish an unavailable job service, a missing image, an image-pull failure, a missing shell/tool, and a command failure. Use audit logs to investigate who requested an operation; verify its actual result in job status and in the system the command changed.