API reference·7 min read

Endpoints

The full reference for every Operelio API endpoint: the request to send, the response you get back, and every field in it. Single-file and batch.

By Operelio team · Updated July 2026

On this page10
  1. 1.Base URL and how to read this page
  2. 2.POST /uploads
  3. 3.POST /jobs
  4. 4.GET /jobs/:id
  5. 5.GET /files/:id/download
  6. 6.Batch endpoints (Agency)
  7. 7.POST /jobs/batch
  8. 8.GET /jobs/batch/:id
  9. 9.GET /jobs/batch/:id/download
  10. 10.Frequently asked questions

Base URL and how to read this page

Every request goes to the same base URL, over HTTPS, with your API key in the Authorization header:

Base URL and auth
https://operelio.com/api/v1

Authorization: Bearer op_your_api_key_here

Each endpoint below shows the request to send and the response you get back. The long ids are examples; use the ones your own calls return. For how to build the configJson each tool needs, see the Tools and configJson guide.

POST /uploads

Upload one file so a job can run on it. Send it as multipart form data with the file in a field named "file". Accepts .xlsx, .xls, and .csv. Returns the file's id, which you pass as inputFileId when you create a job.

Request and response
curl -X POST https://operelio.com/api/v1/uploads \
  -H "Authorization: Bearer op_your_api_key_here" \
  -F "file=@contacts.csv"

# Response 200
{
  "id": "8f3b7a10-2c4d-4e6a-9b1f-0d5c8e2a7f34",
  "originalName": "contacts.csv",
  "sizeBytes": 12345
}
FieldWhat it is
idThe file's id (a UUID). Pass this as inputFileId when you create a job, or in the fileIds array for a batch.
originalNameThe filename you uploaded.
sizeBytesThe file size in bytes.

Uploading counts against your plan's file size cap and needs at least one job left in your monthly quota. A file you couldn't process is refused at upload, so nothing sits unused.

POST /jobs

Run one tool on one file. Send JSON with the file's id (inputFileId), the tool to run (toolType), and that tool's settings (configJson). Returns a job id with a status of "queued". The job runs in the background; poll it with GET /jobs/:id.

Request and response
curl -X POST https://operelio.com/api/v1/jobs \
  -H "Authorization: Bearer op_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "inputFileId": "8f3b7a10-2c4d-4e6a-9b1f-0d5c8e2a7f34",
    "toolType": "deduplicate",
    "configJson": { "columns": ["email"], "keepStrategy": "first" }
  }'

# Response 200
{
  "id": "3a9c1e57-6b8d-42f0-9a3e-7c1b5d0f2e88",
  "toolType": "deduplicate",
  "status": "queued",
  "createdAt": "2026-07-23T10:00:00.000Z"
}
SendWhat it is
inputFileIdThe id from POST /uploads. Every file tool needs it.
toolTypeWhich tool to run, e.g. "deduplicate". See the Tools and configJson guide for the full list.
configJsonThe tool's settings. The shape depends on the tool; capture it from the dashboard (see the Tools guide).

The response status is always "queued" at first. configJson is capped at 100 KB. Sending an unknown toolType returns 400 with the list of valid ones.

GET /jobs/:id

Check a job's status. Call this every couple of seconds until status is "completed" or "failed". While it runs, status moves queued → processing → completed (or failed). When it completes, outputFileId and outputFileName point to the result.

Request and response
curl https://operelio.com/api/v1/jobs/3a9c1e57-6b8d-42f0-9a3e-7c1b5d0f2e88 \
  -H "Authorization: Bearer op_your_api_key_here"

# Response 200
{
  "id": "3a9c1e57-6b8d-42f0-9a3e-7c1b5d0f2e88",
  "toolType": "deduplicate",
  "status": "completed",
  "outputFileId": "b2e60d94-1f7a-4c83-8d05-6a9e3b1c7f42",
  "outputFileName": "contacts_deduplicated.csv",
  "createdAt": "2026-07-23T10:00:00.000Z",
  "startedAt": "2026-07-23T10:00:01.000Z",
  "finishedAt": "2026-07-23T10:00:04.000Z",
  "errorMessage": null
}
FieldWhat it is
statusOne of: queued, processing, completed, failed.
outputFileIdThe result file's id once the job completes. null until then. Pass it to GET /files/:id/download.
outputFileNameThe result file's name once complete. null until then.
createdAt, startedAt, finishedAtWhen the job was created, picked up, and finished. startedAt and finishedAt are null until each happens.
errorMessageWhy the job failed, when status is "failed". null otherwise.

A job that failed still returns 200 here, with status "failed" and errorMessage set. That is different from a 4xx or 5xx, which means the request itself didn't reach the job. See Error handling.

GET /files/:id/download

Download a file by its id. Use the outputFileId from a completed job to get the result, or an input file's id to get back what you uploaded. The response is the file itself, not JSON.

Request
curl -O -J https://operelio.com/api/v1/files/b2e60d94-1f7a-4c83-8d05-6a9e3b1c7f42/download \
  -H "Authorization: Bearer op_your_api_key_here"

The -O -J flags tell curl to save the file under the name Operelio sends in the Content-Disposition header, instead of printing it to the screen. In your own code, read that header to name the file.

Batch endpoints (Agency)

When you have many files to run through the same tool with the same settings, batch does it in one request instead of one job per file. Batch is on the Agency plan. It supports six tools: Excel to CSV, CSV to Excel, Clean Headers, Health Check, Deduplicate, and Transpose.

One batch counts as a single API call against your rate limit, no matter how many files. An Agency batch takes up to 50 files and 500,000 rows across all of them.

POST /jobs/batch

Create a batch: one tool, one configJson, many files. Upload each file first with POST /uploads, then pass their ids in the fileIds array. Returns a batchId plus ready-made URLs to poll progress and download the combined result.

Request and response
curl -X POST https://operelio.com/api/v1/jobs/batch \
  -H "Authorization: Bearer op_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "fileIds": ["8f3b7a10-...", "1c2d3e4f-...", "9a8b7c6d-..."],
    "toolType": "deduplicate",
    "configJson": { "columns": ["email"], "keepStrategy": "first" }
  }'

# Response 200
{
  "batchId": "e7d9c1b2-3a45-4f60-8c17-2b9e0d5a3f18",
  "jobIds": ["...", "...", "..."],
  "pollUrl": "https://operelio.com/api/v1/jobs/batch/e7d9c1b2-3a45-4f60-8c17-2b9e0d5a3f18",
  "downloadUrl": "https://operelio.com/api/v1/jobs/batch/e7d9c1b2-3a45-4f60-8c17-2b9e0d5a3f18/download"
}
FieldWhat it is
batchIdThe batch's id.
jobIdsOne job id per file, in upload order. Each file becomes its own job.
pollUrlA full URL to poll the batch's progress. Use it as-is; you don't have to build it.
downloadUrlA full URL to download every finished file as one ZIP.

fileIds must be unique. A batch of N files counts as N jobs against your monthly quota, but one call against the rate limit.

GET /jobs/batch/:id

Poll a batch. Returns a progress summary and the status of every job in it. Poll the pollUrl from the create step every couple of seconds until progress shows no jobs still processing.

Response
# Response 200
{
  "batchId": "e7d9c1b2-3a45-4f60-8c17-2b9e0d5a3f18",
  "toolType": "deduplicate",
  "createdAt": "2026-07-23T10:00:00.000Z",
  "progress": { "total": 3, "completed": 2, "failed": 0, "processing": 1 },
  "jobs": [
    {
      "id": "...",
      "status": "completed",
      "inputFile": { "id": "...", "originalName": "list-a.csv" },
      "outputFile": { "id": "...", "originalName": "list-a_deduplicated.csv" },
      "errorMessage": null
    }
  ]
}
FieldWhat it is
progress.totalHow many files are in the batch.
progress.completed, failed, processingCounts by state. Jobs still queued aren't counted in any of these, so early on the three can add up to less than total.
jobs[]One entry per file, with its status, its input and output file, and an errorMessage if it failed.

GET /jobs/batch/:id/download

Download every successful file in the batch as one ZIP. Call the downloadUrl once the batch has finished. If some files failed, you still get a ZIP of the ones that worked; if every file failed, this returns 400 because there is nothing to download.

Request
curl -O -J https://operelio.com/api/v1/jobs/batch/e7d9c1b2-3a45-4f60-8c17-2b9e0d5a3f18/download \
  -H "Authorization: Bearer op_your_api_key_here"
# Saves e.g. deduplicate_batch_2026-07-23_e7d9c1.zip

As with single-file downloads, -O -J saves the ZIP under the name in the Content-Disposition header. That name includes the tool, the date, and a short batch code, so two batches never overwrite each other.

Frequently asked questions

Are jobs synchronous or asynchronous?

Asynchronous. POST /jobs returns immediately with a job id; you poll GET /jobs/:id until status is "completed" or "failed". Most jobs finish in under 10 seconds, so a 2-second poll interval is plenty.

What do the ids look like?

Every file, job, and batch id is a UUID, like 8f3b7a10-2c4d-4e6a-9b1f-0d5c8e2a7f34. You never make them up; you read them from one response and pass them to the next call.

How do I know what configJson a tool needs?

That is the one part that changes per tool. The Tools and configJson guide lists every toolType and shows how to capture the exact configJson from the dashboard, so you copy a working shape rather than guess it.

Do API jobs count toward my monthly quota?

Yes. Every job counts as one against your monthly job quota (750 on Team, 2,000 on Agency), the same as running it in the dashboard. A batch of N files counts as N jobs.

Ready to get started?

Upload a file and run your first transformation. Free, no credit card required.