API reference
Files
Upload inputs and download outputs.
Upload#
POST /files takes multipart/form-data and needs the figures:generate scope. It returns 201 with file_id, purpose, content_type, size_bytes, expires_at and created_at.
| Field | Type | Required | Default | Rules |
|---|---|---|---|---|
| file | file | yes | — | See the purpose limits below |
| purpose | string | no | image | image, mask or flowchart_attachment |
| Purpose | Accepted | Used by |
|---|---|---|
| image | PNG, JPEG or WebP up to 20 MB (checked by content, not by name) | Edits, text detections, upscales, conversions, reference images |
| mask | PNG up to 8 MB; white marks the area to redraw | POST /images/edits |
| flowchart_attachment | The FlowChart workspace formats, up to 32 MB | POST /flowcharts/generations |
Uploads can be used for 24 hours; after that the file_id is unknown (400 INVALID_REQUEST, FILE_NOT_FOUND). They are only inputs: they never appear in job responses, and they are not shared with anyone.
Uploads count against the same upload limits as the website. Beyond them the answer is 429 RATE_LIMITED with Retry-After and details.reason UPLOAD_RATE_LIMITED (per minute) or UPLOAD_DAILY_LIMIT_REACHED (per day, flowchart attachments).
An upload may send an optional Idempotency-Key header (1–255 visible ASCII characters). The same account, key and purpose always map to one file_id: a repeat returns the first file with 201, without uploading again or counting against the upload limits. The same key and purpose with different bytes returns 409 IDEMPOTENCY_CONFLICT. Without the header every upload creates a new file.
Download#
Each job output has a download_url that works without credentials for one hour; read the job again for a fresh link. GET /files/{file_id} with your credential downloads any of your files. Files are always served as attachments.
A signed download_url returns 404 NOT_FOUND once it has expired or if it was altered, and every link of an account that is banned or being deleted stops working the same way.
| Output | Can be passed to |
|---|---|
| PNG or JPEG | Every image endpoint (edits, text detections, upscales, conversions, reference images) |
| WebP | Edits, text detections, upscales, SVG vectorization and reference images; not PNG, PDF, TIFF or PPTX conversions |
| Flowchart SVG | POST /images/conversions to PNG, PDF, TIFF or PPTX |
| PDF, TIFF, EPS, PPTX, other SVG | Nothing: download only |
A conversion source larger than 20 MB (an 8K upscale, say) is refused with 400 INVALID_REQUEST (FILE_TOO_LARGE).
cURL#
curl -X POST https://scifig.ai/api/v1/files \
-H "Authorization: Bearer $SCIFIG_API_KEY" \
-F "file=@figure.png" \
-F "purpose=image"JavaScript#
import { readFile } from 'node:fs/promises';
const form = new FormData();
form.set('file', new Blob([await readFile('figure.png')]), 'figure.png');
form.set('purpose', 'image');
const response = await fetch('https://scifig.ai/api/v1/files', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.SCIFIG_API_KEY}`,
},
body: form,
});
const result = await response.json();
console.log(response.status, result);Python#
import os
import requests
headers = {
"Authorization": f"Bearer {os.environ['SCIFIG_API_KEY']}",
}
response = requests.post(
"https://scifig.ai/api/v1/files",
headers=headers,
files={"file": open("figure.png", "rb")},
data={"purpose": "image"},
timeout=60,
)
print(response.status_code, response.json())