Upload API

Get an API key from your account, then send images from any app.

One endpoint uploads an image from a file, a base64 string or a public URL, and returns its links and embed codes as JSON. It works with ShareX custom uploaders, n8n HTTP Request nodes, and any tool that can send a form upload.

Upload an image

POST https://pinpicx.app/v1/upload

key         required  your API key (or ?key=, X-API-Key header, or Bearer token)
image       required  a file, a base64 string, or an http(s) URL
name        optional  file name
expiration  optional  delete after N seconds (60 to 15552000)
album       optional  ID of one of your albums to put the image in
                      (the last part of the album link, /a/AbC12345)
curl -X POST "https://pinpicx.app/v1/upload?key=YOUR_KEY" \
  -F "[email protected]" \
  -F "expiration=86400"

A successful upload returns HTTP 200:

{
  "data": {
    "id": "aB3xK9pQ",
    "title": "photo",
    "url_viewer": "https://pinpicx.app/aB3xK9pQ",
    "url": "https://img.pinpicx.app/aB3xK9pQ/photo.jpg",
    "display_url": "https://img.pinpicx.app/aB3xK9pQ/m/photo.jpg",
    "width": 1920, "height": 1080, "size": 482113,
    "time": 1761235200, "expiration": 86400,
    "image":  { "filename": "photo.jpg", "mime": "image/jpeg", "url": "…" },
    "thumb":  { "filename": "photo.jpg", "mime": "image/jpeg", "url": "…/t/photo.jpg" },
    "medium": { "filename": "photo.jpg", "mime": "image/jpeg", "url": "…/m/photo.jpg" },
    "delete_url": "https://pinpicx.app/aB3xK9pQ/delete/…",
    "embed": { "html": "…", "html_full": "…", "bbcode": "…", "bbcode_full": "…", "markdown": "…" }
  },
  "success": true,
  "status": 200
}

If processing takes longer than a minute the response is HTTP 202 with the image's id; poll GET /v1/images/{id} until it returns 200.

Other endpoints

Method and pathWhat it does
GET /v1/imagesYour uploads, newest first. Query: page, per_page (max 100).
GET /v1/images/{id}One image's links and details.
DELETE /v1/images/{id}Delete with your key, or with ?delete_token=… for a guest upload.
POST /v1/reportsReport an image. Body: image_id, reason (illegal, nsfw, copyright, spam, other), details.

Errors

Errors return { "success": false, "status": 413, "error": { "code": "file_too_large", "message": "…" } }.

StatusCodeMeaning
400invalid_imageThe file could not be read as an image.
400invalid_expirationExpiration is outside 60 to 15552000 seconds.
401invalid_keyThe API key is missing, unknown or revoked.
413file_too_largeThe image is over 32 MB.
415unsupported_typeNot JPG, PNG, GIF, WebP, AVIF, BMP or TIFF. SVG and HEIC are not accepted.
422blocked_contentThis file was removed before and cannot be uploaded again.
404not_foundThe album doesn't exist or isn't yours.
403storage_fullYour account has used its plan's storage. Delete images or upgrade, then try again.
429rate_limitedYour account is over its plan's hourly upload limit; see the Retry-After header.
502url_fetch_failedThe image URL could not be downloaded.

Limits

Upload limits count across all of an account's keys and reset on a rolling one-hour window.

PlanAPI keysAPI uploads per hour
Free110
Pro5500
Business205,000

Versions

Every API path starts with its version: /v1/ is the current one. Changes that could break your code, such as renamed fields or a different response format, only ever come in a new version (/v2/), and /v1/ keeps working when it arrives. New optional fields may be added to /v1/ at any time, so ignore fields you don't use.

Integrations set up with the earlier /1/ paths (for example /1/upload) still work: they are the same as /v1/.

Get a key

Create an account, then open API keys and create a key for each app. Images uploaded with your key appear in My images.