API Reference

Complete reference for the img.pro REST API. All requests go to https://api.img.pro/v1.

Authentication

Include your API key as a Bearer token:

http
Authorization: Bearer YOUR_API_KEY

Sign up at img.pro, then create a key from the dashboard.

The upload and import endpoints work without authentication. Anonymous uploads expire after 30 days and are rate limited by IP (20/hour, 100/day). Include a Bearer token for ownership, permanent storage, and higher limits.

Keep your API key secret

Never expose your API key in client-side code or public repositories.

POST /v1/upload

Upload an image file. Authentication optional. The filename is taken from the multipart file part — clients can’t override it.

Parameter Type Required Description
file File Yes Image file. Supported: JPEG, PNG, GIF, WebP, AVIF, HEIC, SVG, BMP, ICO. Max 70 MB (10 MB for SVG, 20 MB anonymous).
caption string No Free-text caption / description for the image.
ttl string No Time-to-live: seconds (e.g., 3600) or duration (5m90d). Omit for permanent storage.
any field string No Any other field is stored as attribution metadata (e.g., author, license, source_url)

Authenticated

Request
bash
curl -X POST "https://api.img.pro/v1/upload" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@photo.jpg" \
  -F "caption=Hero shot from launch day"
Response
json
{
  "id": "abc123",
  "link": "https://img.pro/abc123",
  "caption": "Hero shot from launch day",
  "extension": "jpeg",
  "width": 1920,
  "height": 1080,
  "filesize": 245678,
  "created_at": 1704067200
}

Anonymous (no auth)

Request
bash
curl -X POST "https://api.img.pro/v1/upload" \
  -F "file=@photo.jpg"

Same response shape, plus expires_at and an upgrade hint pointing to registration. Anonymous uploads are rate-limited — sign up for an API key to remove the cap.

Response
json
{
  "id": "abc123",
  "link": "https://img.pro/abc123",
  "extension": "jpeg",
  "width": 1920,
  "height": 1080,
  "filesize": 245678,
  "expires_at": 1706659200,
  "created_at": 1704067200,
  "upgrade": {
    "type": "register",
    "url": "https://img.pro/auth/register?from_cta=api",
    "message": "Sign up for permanent storage, larger files (70 MB), and higher limits",
    "label": "Create Account"
  }
}

Response field notes

  • id, link, extension, and created_at — always present.
  • caption — sits under link when set; omitted otherwise.
  • status — only present while "processing" or "failed".
  • non_editable: true — only present for SVG/BMP/ICO (formats Cloudflare can't transform); everything else is editable by default.
  • nsfw — only present when flagged by moderation.
  • expires_at — only present for ephemeral uploads.

POST /v1/import

Import an image from a URL. Authentication optional. The filename is derived from the URL path — clients can’t override it.

Parameter Type Required Description
url string Yes Image URL to import (must be publicly accessible, 30s timeout).
caption string No Free-text caption / description.
ttl string No Time-to-live (e.g., 7d). Omit for permanent storage.
external_id string No External dedup key — unique per team. If a non-expired record with this ID already exists, it is returned (HTTP 200, X-Deduplicated: true) instead of re-fetching the URL.
any field string No Stored as attribution metadata.
Request
bash
curl -X POST "https://api.img.pro/v1/import" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/image.jpg",
    "caption": "Imported from example.com",
    "external_id": "ext-12345"
  }'
Response
json
{
  "id": "def456",
  "link": "https://img.pro/def456",
  "caption": "Imported from example.com",
  "extension": "jpeg",
  "width": 2560,
  "height": 1440,
  "filesize": 384291,
  "external_id": "ext-12345",
  "source_url": "https://example.com/image.jpg",
  "created_at": 1704067200
}

source_url is set automatically to the imported URL.

GET /v1/media

List media with cursor-based pagination.

Parameter Type Required Description
ids string No Comma-separated IDs to fetch specific items
limit integer No 1–100 (default: 50)
cursor string No Pagination cursor from previous response
Request
bash
curl "https://api.img.pro/v1/media?limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
Response
json
{
  "data": [
    {
      "id": "abc123",
      "link": "https://img.pro/abc123",
      "caption": "Hero shot from launch day",
      "extension": "jpeg",
      "width": 1920,
      "height": 1080,
      "filesize": 245678,
      "created_at": 1704067200
    }
  ],
  "next_cursor": "eyJpZCI6MTIzfQ",
  "has_more": true
}

GET /v1/media/:id

Get a single media item. Public media can be fetched without authentication.

Request
bash
curl "https://api.img.pro/v1/media/abc123" \
  -H "Authorization: Bearer YOUR_API_KEY"
Response
json
{
  "id": "abc123",
  "link": "https://img.pro/abc123",
  "caption": "Hero shot from launch day",
  "extension": "jpeg",
  "width": 1920,
  "height": 1080,
  "filesize": 245678,
  "created_at": 1704067200
}

PATCH /v1/media/:id

Update editable fields. Only the params below (plus arbitrary attribution metadata) are accepted — sending tags, namespace, nsfw, tool, defaults, or description returns 422.

Parameter Type Required Description
caption string No Update caption. Send empty string or null to clear.
public boolean No Flip the media’s public/private state. true / 1 / "true" = public; false / 0 / "false" = private.
ttl string No New TTL (e.g., 7d) or null to make permanent.
any field string|null No Merged with existing attribution metadata. null removes the field.
Request
bash
curl -X PATCH "https://api.img.pro/v1/media/abc123" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"caption": "Updated caption", "public": true, "camera": null}'
Response
json
{
  "id": "abc123",
  "link": "https://img.pro/abc123",
  "caption": "Updated caption",
  "extension": "jpeg",
  "width": 1920,
  "height": 1080,
  "filesize": 245678,
  "created_at": 1704067200
}

DELETE /v1/media/:id

Permanently delete a media item and all its CDN variants. Returns 204 No Content.

Request
bash
curl -X DELETE "https://api.img.pro/v1/media/abc123" \
  -H "Authorization: Bearer YOUR_API_KEY"

Batch Operations

PATCH /v1/media/batch

Update editable fields on up to 100 items at once. Same field restrictions as the single-item PATCH — caption, public, and ttl apply uniformly to every id in the batch.

Parameter Type Required Description
ids string[] Yes Array of media IDs (max 100).
caption string No Same caption applied to every item (empty string or null clears).
public boolean No Flip every item’s public/private state in one call.
ttl string No Same TTL applied to every item (e.g. 7d) or null to make all permanent.
any field string|null No Merged into every item’s attribution metadata. null removes the field.
Request
bash
curl -X PATCH "https://api.img.pro/v1/media/batch" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ids": ["abc123", "def456"], "ttl": "7d", "public": false}'
Response
json
{
  "updated": 2
}

DELETE /v1/media/batch

Delete up to 100 items by ID.

Parameter Type Required Description
ids string[] Yes Array of media IDs to delete (max 100).
Request
bash
curl -X DELETE "https://api.img.pro/v1/media/batch" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ids": ["abc123", "def456"]}'
Response
json
{
  "deleted": 2
}

GET /v1/usage

Current quota and usage statistics.

Request
bash
curl "https://api.img.pro/v1/usage" \
  -H "Authorization: Bearer YOUR_API_KEY"
Response
json
{
  "monthly": {
    "uploads": 42,
    "uploads_limit": 5000,
    "uploads_remaining": 4958,
    "resets_at": 1709251200
  },
  "totals": {
    "media_stored": 142,
    "storage_used_bytes": 52428800,
    "storage_limit_bytes": 5368709120,
    "storage_remaining_bytes": 5316280320
  },
  "plan": "free"
}

Image Transforms

Transforms live as query parameters on the link field. Convert formats, adjust color/tone, blur or sharpen, rotate or flip, remove backgrounds with one param, and strip EXIF before sharing — all inline via the URL.

text
https://img.pro/{id}?format=webp&brightness=1.1&metadata=none
Documented surface: format, brightness, contrast, gamma, saturation, blur, sharp, rotate, flip, segment, background, metadata. See the Image Transforms reference for value ranges, defaults, and combining examples. Anything that needs explicit dimensions (resize, crop, face crop) lives in the image tools.

Custom Fields

Any field you send that isn't a reserved name is stored as attribution metadata.

Set fields

Include them alongside other parameters — no wrapper needed:

Request
bash
curl -X POST "https://api.img.pro/v1/upload" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@photo.jpg" \
  -F "caption=Sunset over the Pacific" \
  -F "author=Jane Doe" \
  -F "license=cc-by-4.0"

Read fields

Custom fields appear at the top level of the response — what you send is what you get back:

Response
json
{
  "id": "abc123",
  "link": "https://img.pro/abc123",
  "caption": "Sunset over the Pacific",
  "extension": "jpeg",
  "author": "Jane Doe",
  "license": "cc-by-4.0",
  "created_at": 1704067200
}

Update fields

PATCH merges with existing attribution metadata. Set a field to null to remove it:

Request
bash
curl -X PATCH "https://api.img.pro/v1/media/abc123" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"alt_text": "A vivid sunset", "camera": null}'

Reserved fields

These names are used by the system. Sending them in upload metadata is silently ignored; sending them on PATCH returns 422 (with the exception of caption, public, ttl, and external_id, which are valid PATCH targets):
id name link extension width height filesize status tags tag_mode namespace external_id date caption description editable non_editable nsfw expires_at created_at tool defaults public ttl file

Errors

Every error includes a machine-readable error code and a human-readable message. Some include an action object — see the Error Reference for full details.

401unauthorizedMissing or invalid API key
403forbiddenKey lacks required permission
403quota_exceededUpload or storage limit reached
404not_foundMedia item not found
409external_id_duplicateAnother item uses this external_id
422validation_errorInvalid parameters (per-field errors)
429rate_limitedToo many requests
500upload_failedServer error during upload
500import_failedServer error during import
502fetch_failedCould not fetch import URL

Quota Headers

Every authenticated response includes quota information in headers:

X-Monthly-Uploads-UsedUploads used this billing period
X-Monthly-Uploads-LimitMonthly upload limit
X-Monthly-Uploads-RemainingUploads remaining
X-Storage-UsedStorage used (bytes)
X-Storage-LimitStorage limit (bytes)
X-Storage-RemainingStorage remaining (bytes)