Developers

From an image to your workflow

Submit an image, follow its conversion, and download structured results through a simple REST API.

Create an API key

Quickstart

Send a JPG, PNG, BMP or TIFF image as multipart form data. The API returns 202 with a job ID. tableOnly=true extracts tables; false also extracts surrounding text.

cURL · POST /api/v1/jobs
curl -X POST 'https://jpg2excel.app/api/v1/jobs' \
  -H "Authorization: Bearer $JPG2EXCEL_API_KEY" \
  -H 'Idempotency-Key: invoice-2026-10-001' \
  -F 'file=@table.jpg' \
  -F 'tableOnly=true'
HTTP 202 · application/json
{
  "code": 0,
  "msg": "OK",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "queued",
    "filename": "table.jpg",
    "createdAt": "2026-10-08T08:00:00.000Z",
    "completedAt": null,
    "resultExpiresAt": null,
    "creditsUsed": 0,
    "error": null,
    "resultFormats": [],
    "statusUrl": "/api/v1/jobs/550e8400-e29b-41d4-a716-446655440000",
    "resultUrl": null
  }
}

This Python example submits a file, waits for completion and saves an Excel workbook. Set JPG2EXCEL_API_KEY in your server environment first.

Python · pip install requests
import os
import time
import uuid
import requests

base = "https://jpg2excel.app"
headers = {"Authorization": f"Bearer {os.environ['JPG2EXCEL_API_KEY']}"}
# Keep this value if you retry the same submission.
submission_key = str(uuid.uuid4())

with open("table.jpg", "rb") as image:
    response = requests.post(
        f"{base}/api/v1/jobs",
        headers={**headers, "Idempotency-Key": submission_key},
        files={"file": ("table.jpg", image, "image/jpeg")},
        data={"tableOnly": "true"},
        timeout=60,
    )
response.raise_for_status()
job = response.json()["data"]
deadline = time.monotonic() + 600

while job["status"] in ("queued", "processing"):
    if time.monotonic() > deadline:
        raise TimeoutError("Conversion is still running; query its job ID later.")
    time.sleep(2)
    response = requests.get(base + job["statusUrl"], headers=headers, timeout=30)
    if response.status_code == 429:
        time.sleep(int(response.headers.get("Retry-After", "5")))
        continue
    response.raise_for_status()
    job = response.json()["data"]

if job["status"] != "succeeded":
    raise RuntimeError(job.get("error") or job["status"])

result = requests.get(
    base + job["resultUrl"], headers=headers,
    params={"format": "xlsx"}, timeout=60,
)
result.raise_for_status()
with open("result.xlsx", "wb") as output:
    output.write(result.content)

Authentication

Use a Plus or Enterprise API key in the Authorization header. Team keys use team credits. Store secrets on your server; never expose them in browser code.

HTTP header
Authorization: Bearer j2e_live_YOUR_SECRET_KEY

jobs:write submits jobs. jobs:read reads job status, downloads results and checks usage. Limit each key to the permissions your integration needs.

MethodEndpointPurpose
POST/api/v1/jobsSubmit an image
GET/api/v1/jobs/{id}Read job status
GET/api/v1/jobs/{id}/resultDownload structured output
GET/api/v1/usageRead available credits and limits

Conversion jobs

Poll the status URL until the job succeeds or fails. Start with a 2-second interval and back off when requests are rate limited.

queuedprocessingsucceeded/failed
cURL · GET job status
curl 'https://jpg2excel.app/api/v1/jobs/JOB_ID' \
  -H "Authorization: Bearer $JPG2EXCEL_API_KEY"

Send an Idempotency-Key for each logical submission. Reuse it when retrying the same file and options so the job is not created or charged twice.

A repeated key returns the original job with HTTP 200. Reusing a key with a different file or options returns HTTP 409. Idempotency keys are scoped to the workspace.

Download results

Download XLSX, CSV or JSON after success. Use resultExpiresAt from the job response to know how long the result remains available.

cURL · GET XLSX result
curl 'https://jpg2excel.app/api/v1/jobs/JOB_ID/result?format=xlsx' \
  -H "Authorization: Bearer $JPG2EXCEL_API_KEY" \
  --output result.xlsx

xlsx

Editable Excel workbook

csv

First table as CSV for data pipelines

json

Structured tables in a JSON envelope

Results are available for 24 hours after completion. Save them to your own storage. TIFF uploads must be single-page; PDF is not supported by this endpoint.

Credits and limits

Web and API conversions share credits. Successful jobs spend credits; failed jobs release their reservation. Your plan sets file size, concurrency and request limits. API jobs always require credits.

cURL · GET workspace usage
curl 'https://jpg2excel.app/api/v1/usage' \
  -H "Authorization: Bearer $JPG2EXCEL_API_KEY"

API key limits reset each UTC calendar month. Member limits follow the team's monthly credit renewal and count completed and reserved credits. Limits do not add credits; a zero member limit blocks new conversions.

Enterprise includes 3 seats, including the owner. Additional seats cost $5/month or $50/year each. Team members share credits and concurrency limits; only the owner and admins manage team keys.

Errors and retries

Errors use the same JSON envelope: code, msg and data. Use the HTTP status and error code to decide whether to retry.

HTTP 429 · Retry-After: 60
{
  "code": 1006,
  "msg": "Workspace request rate limit reached.",
  "data": null
}
HTTPcodeWhat to do
4001001 / 2004 / 2005Check the request fields, file and options before retrying.
4011002Check your key. Expired and revoked keys cannot authenticate.
4023002 / 3003Add credits, or wait for the key or member monthly limit to reset.
4031003Check key scopes and the workspace subscription.
404 / 4101004 / 2007Check the job ID and workspace; expired results cannot be downloaded.
4091005The result is not ready, or the idempotency key was used for different input.
413 / 4152002 / 2003Reduce the file size or use a supported image format.
4291006Wait for Retry-After, then retry. Reduce request rate or concurrency.
5031007Retry with backoff and the same idempotency key.

A failed conversion is reported in the job's error field, even when the status request itself returns HTTP 200. Codes 2006, 2008 and 2009 indicate conversion failure, timeout and no detected table.