curl --request DELETE \
--url https://ndi-api.nace.ai/v1/jobs/{job_id} \
--header 'X-API-Key: <api-key>'{
"error": {
"code": "invalid_request",
"detail": null,
"message": "Request body has extra fields that this operation does not accept.",
"request_id": "req-01j9k2n3p4q5r6s7t8v9",
"retryable": false
}
}{
"error": {
"code": "invalid_request",
"detail": null,
"message": "Request body has extra fields that this operation does not accept.",
"request_id": "req-01j9k2n3p4q5r6s7t8v9",
"retryable": false
}
}delete_job
Hide a job from listings and delete its content, keeping it for billing. Cost class: fast.
The row survives with its content-free billing fields, so units keep
answering and GET /v1/usage still counts the work; GET /v1/jobs stops
returning it. Reading it by id still works, with deleted_at set — the
same reasoning as an expired payload, where a 404 would conflate “gone” with
“never existed”.
The job’s input, result, artifact files and source snapshot are
removed by the reaper’s payload-expiry leg on its next sweep (minutes), with
the same for an automatic search’s delegated child: the delete only marks
the payload as expired now, so slow storage work stays out of the request.
Afterwards the job reads as result_state="expired" (a zero-retention job
keeps not_retained). The same sweep deletes the perception-cache
entries this job produced or consumed; one that another retained job of
the same tenant still reads stops serving hits and goes once that job’s
content expires.
input and result always go at that sweep. Only artifact files that
another retained job of the same tenant still uses (it reused this job’s
Parse result, whose URLs point at them) are kept until that job’s content
expires; a later sweep deletes them. A job still queued or running that
reuses this job’s Parse result fails result_expired. Bring-your-own-bucket
files are never deleted.
A job still queued or running is cancelled first, so hitting delete stops the compute rather than paying for a run nobody will ever see. A job that finished under us is simply hidden: there was nothing left to stop, and refusing the delete over a race the caller cannot see would be noise.
Temporal is not declared as a dependency here because asking for the
client connects: most deletes are of finished runs and need it for nothing,
so an outage must not fail work that is entirely in Postgres.
There is no project-level route to pair with ?project_id=: a run’s
fan-out is one job per file, and the console deletes the group the same way
it renames it — per job, over the ids it already holds.
curl --request DELETE \
--url https://ndi-api.nace.ai/v1/jobs/{job_id} \
--header 'X-API-Key: <api-key>'{
"error": {
"code": "invalid_request",
"detail": null,
"message": "Request body has extra fields that this operation does not accept.",
"request_id": "req-01j9k2n3p4q5r6s7t8v9",
"retryable": false
}
}{
"error": {
"code": "invalid_request",
"detail": null,
"message": "Request body has extra fields that this operation does not accept.",
"request_id": "req-01j9k2n3p4q5r6s7t8v9",
"retryable": false
}
}