REST API
Jobs API
Every run on Railwail is a job. This endpoint returns its status, output, cost and timing; use it to collect video results and image runs that answered before they finished.
- URL
- GET /api/v1/jobs/{id}
- Key scope
- jobs, or the run's own scope
- Job id
- UUID
- Cost
- free, counts toward rate limit
Get a job
GET
/api/v1/jobs/{id}Where the id comes from
- Video:
job_idin the 202 answer of /videos/generations (and theLocationheader). - Images:
data[].job_idof /images/generations; a 202 answer also carries apollURL. - Chat: the
X-Railwail-Job-Idheader, or the part afterchatcmpl-in the responseid.
Example
curl "https://railwail.com/api/v1/jobs/$JOB_ID" \
-H "Authorization: Bearer $RAILWAIL_API_KEY"import os, requests
job = requests.get(
f"https://railwail.com/api/v1/jobs/{job_id}",
headers={"Authorization": f"Bearer {os.environ['RAILWAIL_API_KEY']}"},
timeout=60,
).json()
print(job["status"], job.get("output_url"))const res = await fetch(`https://railwail.com/api/v1/jobs/${jobId}`, {
headers: { Authorization: `Bearer ${process.env.RAILWAIL_API_KEY}` },
});
const job = await res.json();
console.log(job.status, job.output_url);const job = await rw.job(jobId);
console.log(job.status, job.output_url);Response
Shape of the answer; values are placeholders.
{
"id": "<uuid>",
"object": "job",
"status": "completed",
"model": {
"name": "<display name>",
"slug": "<slug>",
"category": "video",
"provider": "<infrastructure provider>",
"provider_model_id": "<id at the provider>"
},
"input": { "prompt": "<your prompt>" },
"output": <text, object or array, depending on the model>,
"output_url": "https://…/output.mp4",
"cost": { "credits": <number>, "currency": "credits" },
"tokens": { "input": <number>, "output": <number>, "total": <number> },
"timing": {
"created_at": <unix seconds>,
"queued_at": <unix seconds | null>,
"started_at": <unix seconds | null>,
"completed_at": <unix seconds | null>,
"latency_ms": <number | null>,
"duration_ms": <number | null>,
"duration_seconds": <number | null>
},
"source": "api",
"provider_job_id": "<provider id>",
"error": null
}output_url can be a temporary provider link: download the file when the job completes. cost.credits is the amount charged (held while the job runs).
Statuses
| Status | Meaning |
|---|---|
| queued | Accepted, waiting for the provider. |
| processing | Running. Each GET asks the provider for news. |
| completed | Done: read output or output_url. |
| failed | Did not finish; error says why. The held credits are refunded. |
| cancelled | Stopped at the provider; refunded like a failure. |
Polling
- Images: every 2–3 seconds. Video: every 5–10 seconds; most take one to several minutes.
- Stop on
completed,failedandcancelled, and give up after a deadline. - Every poll counts toward your key's rate limit (default 600 requests per minute).
Full polling loop
The video generation page has a complete loop in Python and Node, and rw.job() one for the npm SDK.
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | invalid_api_key | Missing, unknown, revoked or expired key. |
| 403 | insufficient_scope | The key has neither jobs nor the scope of the job's category. |
| 403 | forbidden | The job belongs to another account (type authentication_error today). |
| 404 | job_not_found | No job with this id. |
| 429 | rate_limit_exceeded | Too many requests; wait X-RateLimit-Reset seconds. |