API Documentation

Complete reference for the Nelix REST API

Create a key on your API Keys page and start calling the endpoints below.

API Overview

Base URL: https://api.nelix.ai/v1

Authentication

Every request needs an API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Keys start with sk_ and are created on your API Keys page. The key is shown once, when you create it, and cannot be retrieved afterwards. You can give a key an expiry date; an expired key is rejected. Deleting a key takes effect within 60 seconds.

API Key Roles

Read
GET requests only: list jobs, read a job, read results
Write
Submit documents to POST /analyze + all Read permissions
Admin
Every method on every endpoint

Quota and Rate Limits

Each account has a monthly scan quota. Once it is used up, POST /analyze returns 429 with { "error": "Quota exceeded", "message": "Monthly quota exceeded. Used: <used>/<quota>" }. Quota and rate limits are agreed per customer.

Endpoints

Document Analysis

POST
Requires: Write
POST /analyze

Description

Submit a PDF document for security analysis. The API will scan for hidden text, layer manipulation, metadata injection, and other security signals. The request returns as soon as the document is queued; poll GET /jobs/{jobId} or GET /results/{jobId} for the verdict.

Request Body

The raw PDF bytes. Not multipart, not JSON: a multipart body fails the PDF check and returns 400. Maximum 10 MB.

Request Headers

Content-Type
required

application/pdf (or application/octet-stream)

X-File-Name
optional

The original file name, URL-encoded. Defaults to uploaded.pdf.

X-Job-Id
optional

Your own job id. Defaults to a UUID generated by the API.

Example Request

curl -X POST https://api.nelix.ai/v1/analyze \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/pdf" \
  -H "X-File-Name: document.pdf" \
  --data-binary @document.pdf

Response

{
  "jobId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "pending",
  "message": "File uploaded successfully and analysis started"
}

Errors

  • 400 — empty body, or the body is not a PDF
  • 413 — larger than 10 MB
  • 429 — the account's monthly scan quota is used up

List Jobs

GET
Requires: Read
GET /jobs

Description

The jobs submitted by your account, newest first, up to 100. There are no query parameters: filtering and paging are not implemented, and anything you send is ignored.

Example Request

curl https://api.nelix.ai/v1/jobs \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "jobs": [ ... ],
  "count": 4
}

Get Job

GET
Requires: Read
GET /jobs/{jobId}

Description

One job of your account, with its findings once the analysis has finished. status is pending, processing, completed or failed. A job id that is not yours returns 404.

Example Request

curl https://api.nelix.ai/v1/jobs/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "file_name": "document.pdf",
  "file_size": 1047,
  "page_count": 1,
  "processing_time_ms": 2493,
  "findings": [],
  "summary": "Analysis complete. Found 0 findings. Risk level: safe",
  "error": null,
  "created_at": "2026-09-06T08:05:21.896+00:00",
  "completed_at": "2026-09-06T08:05:27.160+00:00"
}

Finding Fields

Each entry of findings carries type (tiny_font, hidden_layer, obscured_text, suspicious_metadata, encoding_anomaly, outside_boundary, rendering_discrepancy, prompt_injection_jailbreak), severity (low, medium, high, critical), description, page_number, location (a normalised x0/x1/y0/y1 box), metadata (detector-specific, for example font_size) and text_content. Types and severities are lower-case.

Get Analysis Results

GET
Requires: Read
GET /results/{jobId}

Description

The analyzer's own result document for a finished job. While the job is still running the endpoint returns 202 with { "message": "Analysis not complete", "status": "processing" }; a job id that is not yours returns 404.

Example Request

curl https://api.nelix.ai/v1/results/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "findings": [ ... ],
  "metadata": {
    "job_id": "550e8400-e29b-41d4-a716-446655440000",
    "findings_count": 0,
    "risk_level": "safe",
    "page_count": 1,
    "processing_time_ms": 2493,
    "analyzed_at": "2026-09-06T08:05:27.160000"
  }
}

findings holds the same entries as the job row and risk_level is safe, low, medium, high or critical. Both keys are always present; the analyzer may add further top-level fields.

Response Codes

200
Success
202
Accepted - GET /results/{jobId} while the analysis is still running
400
Bad Request - empty body, or the body is not a PDF
401
Unauthorized - no Authorization header on the request
403
Forbidden - unknown, expired or deleted key, or a role that may not use this method
404
Not Found - no such job for this key, or an unknown path
413
Payload Too Large - the PDF is larger than 10 MB
429
Quota Exceeded - the account's monthly scan quota is used up (also returned by API Gateway throttling: 50 requests/s, burst 100)
500
Internal Server Error
503
Database service unavailable — retry after a short delay

401 and 403 are produced by the API gateway before your request reaches the service, so their bodies differ from the rest: 401 is { "message": "Unauthorized" } and 403 is { "Message": "User is not authorized…" }, while every other code uses { "error": "…" }.