# Jobs and Errors

Retrieve a job, download its workbook, and troubleshoot failed requests.

Canonical documentation: https://img2excel.net/docs/api/jobs

`GET /api/v1/jobs/{job_id}`

Synchronous endpoints return completed conversion results directly. Use the job endpoint for asynchronous processing, to check a pending idempotent retry, or to refresh an expired download URL while the result is retained. Synchronous conversion failures return `422` with a job response; job queries still return `200` for a found job, so always check `status`.

Retrieve the current state of a conversion job. Both Image to Excel and Handwriting to Excel use this endpoint.

## Request

| Parameter | Location | Required | Description |
| --- | --- | --- | --- |
| `job_id` | Path | Yes | The `id` returned by a create-job request. |
| `Authorization` | Header | Yes | `Bearer $IMG2EXCEL_API_KEY`. The key must belong to the job's account. |

```bash
curl --fail-with-body https://img2excel.net/api/v1/jobs/job_0123456789abcdef0123456789abcdef \
  -H "Authorization: Bearer $IMG2EXCEL_API_KEY"
```

A valid request returns **200 OK**, including when the conversion itself has failed. Always check the JSON `status`; an HTTP success does not mean the workbook is ready.

## Job Statuses

| Status | Meaning | Next action |
| --- | --- | --- |
| `queued` | The upload was accepted and is waiting to run. | Poll again after 2–3 seconds. |
| `processing` | Conversion is running. | Poll again after 2–3 seconds. |
| `succeeded` | The workbook is ready. | Download `result.download_url` and stop polling. |
| `failed` | Conversion could not complete. | Read `error.code` and `error.message`; stop polling. |
| `expired` | The result retention period has ended. | Stop polling. Submit a new job with a new idempotency key if needed. |

## Response

### Successful Conversion

```json
{
  "id": "job_0123456789abcdef0123456789abcdef",
  "type": "image-to-excel",
  "status": "succeeded",
  "credits_reserved": 1,
  "credits_used": 1,
  "created_at": "2026-09-07T12:00:00.000Z",
  "completed_at": "2026-09-07T12:00:18.000Z",
  "result": {
    "filename": "table_result.xlsx",
    "content_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    "size_bytes": 17330,
    "download_url": "https://signed-storage-url.example/...",
    "download_url_expires_in": 900
  }
}

```

The download URL above is illustrative. Use the URL returned by your own job.

| Field | Type | Description |
| --- | --- | --- |
| `id` | String | Job identifier. |
| `type` | String | `image-to-excel` or `handwriting-to-excel`. |
| `status` | String | One of the five states listed above. |
| `credits_reserved` | Integer | Credits required for the conversion. |
| `credits_used` | Integer | Credits consumed by the conversion. |
| `created_at` | String | UTC timestamp in ISO 8601 format. |
| `completed_at` | String or null | Completion timestamp; `null` before completion. |
| `result` | Object | Present for a successful job with an available result. |
| `error` | Object | Present when conversion failed. Contains `code` and `message`. |

### Result Fields

| Field | Type | Description |
| --- | --- | --- |
| `filename` | String | Suggested workbook filename. |
| `content_type` | String | XLSX MIME type. |
| `size_bytes` | Integer or null | Workbook size, when available. |
| `download_url` | String | Temporary signed download URL. |
| `download_url_expires_in` | Integer | URL lifetime in seconds: `900` (15 minutes). |

Results remain available for 24 hours after completion. If the download URL expires during that window, retrieve the job again to get a fresh URL. Do not log or publicly share signed download URLs.

### Failed Conversion

A conversion failure is reported in the job body, for example:

```json
{
  "id": "job_0123456789abcdef0123456789abcdef",
  "type": "image-to-excel",
  "status": "failed",
  "credits_reserved": 1,
  "credits_used": 0,
  "created_at": "2026-10-04T09:00:00.000Z",
  "completed_at": "2026-10-04T09:00:18.000Z",
  "error": {
    "code": "CONVERSION_FAILED",
    "message": "The conversion could not be completed."
  }
}
```

Failed conversions do not consume credits. Check the returned message before retrying: a new conversion needs a new idempotency key. Reusing the previous key retrieves the same failed job.

## Poll and Download

Install `requests` with `pip install requests`, set `IMG2EXCEL_API_KEY`, and replace `job_id` with your job's ID. This example makes at most 60 status requests. Network or HTTP errors stop the script; production integrations should handle transient failures using the retry guidance below.

```python
import os
import time
import requests

job_id = "job_0123456789abcdef0123456789abcdef"
headers = {"Authorization": f"Bearer {os.environ['IMG2EXCEL_API_KEY']}"}

for _ in range(60):
    response = requests.get(
        f"https://img2excel.net/api/v1/jobs/{job_id}",
        headers=headers,
        timeout=30,
    )
    response.raise_for_status()
    job = response.json()

    if job["status"] == "succeeded":
        xlsx = requests.get(job["result"]["download_url"], timeout=60)
        xlsx.raise_for_status()
        with open(job["result"]["filename"], "wb") as output:
            output.write(xlsx.content)
        break
    if job["status"] in ("failed", "expired"):
        raise RuntimeError(job.get("error", {"code": job["status"]}))

    time.sleep(2)
else:
    raise TimeoutError("IMG2Excel conversion did not finish in time")

```

## Request Errors

A rejected HTTP request returns a non-2xx status and an error object:

```json
{
  "error": {
    "code": "INVALID_API_KEY",
    "message": "A valid API key is required."
  }
}
```

| HTTP status | Code | Cause | What to do |
| --- | --- | --- | --- |
| 400 | `INVALID_REQUEST` | The body cannot be parsed as multipart form data. | Send a file using your client's multipart upload support. |
| 400 | `INVALID_FILE` | The `file` field is missing or is not a file. | Attach an image under the field name `file`. |
| 400 | `INVALID_IDEMPOTENCY_KEY` | The retry key exceeds 200 characters. | Shorten the header value. |
| 401 | `INVALID_API_KEY` | The key is missing, invalid, expired, revoked, or lacks the required conversion scope. | Check the Bearer header and key in [API settings](https://img2excel.net/settings/api). |
| 403 | `API_ACCESS_REQUIRED` | The account does not have API access. | Purchase the Business or Professional credit package. |
| 404 | `JOB_NOT_FOUND` | The job does not exist or belongs to another account. | Check the ID and use a key belonging to the account that created it. |
| 409 | `JOB_CONFLICT` | A conversion job could not be created because of a conflict. | Retry with the original idempotency key to recover an existing job. |
| 413 | `FILE_TOO_LARGE` | The file exceeds 4MB. | Reduce the image size before uploading. |
| 429 | `RATE_LIMITED` | Too many jobs were created in the last minute. | Wait for `Retry-After`, then retry with the same idempotency key. |
| 429 | `CONCURRENCY_LIMITED` | The account has too many queued or processing jobs. | Wait for a running job to finish before submitting another. |

Credit and recognition failures can occur **after** a job has been accepted. They appear as `status: "failed"` with `error.code` and `error.message` when you retrieve the job, rather than necessarily rejecting the upload request. Check your credit balance if the message reports insufficient credits.

## Limits and Retries

| Limit | Value |
| --- | --- |
| New jobs per account | 30 per minute, across both conversion endpoints |
| Concurrent queued or processing jobs | Business: 3; Professional: 10 |
| File size | Up to 4MB |
| Download URL lifetime | 15 minutes |
| Result retention | 24 hours after successful completion |

For `429` responses, honor `Retry-After` when present. For transient `5xx` responses or network failures, retry with exponential backoff and jitter. Reuse the original idempotency key when retrying an upload; retry status requests using the same job ID. Set an overall polling deadline in your application.

Do not automatically retry invalid requests or authentication errors. Correct the request first. For a persistent failure, contact [support](mailto:support@img2excel.net) with the job ID and error code, without including your API key or download URL.

---

OpenAPI 3.1: https://img2excel.net/api/openapi.json
Complete API documentation: https://img2excel.net/docs/api/llms-full.txt
