imgpile API
Upload, share, and manage images and videos programmatically.
https://imgpile.com/api/v1 โ all endpoints
https://cdn.imgpile.com/api/v1/media โ file uploads only (see below)
Concepts
imgpile has two core objects. Understanding the difference will save you time.
Media
A single file (image or video). Has a direct CDN URL โ ideal for hotlinking, embedding, or sharing.
Post
A shareable page containing one or more media items. Has a title, description, voting, comments, and tags.
/media. Use urls.original from the response. Done.
/posts with the media IDs.
Quick Start
Upload a single file and get a direct CDN URL. Perfect for ShareX, Discord bots, or any script that just needs to host an image.
Note: uploads go to cdn.imgpile.com, not imgpile.com.
curl -X POST https://cdn.imgpile.com/api/v1/media \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "[email protected]"Response:
{
"message": "Media created successfully",
"media": {
"slug": "abc1234",
"type": "image/jpeg",
"urls": {
"original": "https://cdn.imgpile.com/f/abc1234.jpg",
...
}
}
}Upload multiple files, then group them into a post with metadata, voting, and comments.
1. Upload each file to cdn.imgpile.com and keep the returned media ID:
curl -X POST https://cdn.imgpile.com/api/v1/media \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "[email protected]"
# Returns: { "media": { "id": 12345, ... } }2. Create a post with those IDs:
curl -X POST https://imgpile.com/api/v1/posts \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"media_ids": [12345, 12346]}'
# Returns: { "post": { "slug": "xyz789", ... } }3. (Optional) Add a title and description:
curl -X PATCH https://imgpile.com/api/v1/posts/xyz789 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "My post", "description": "Summer 2026"}'Your post is now live at https://imgpile.com/p/xyz789
Upload an image from a browser or Node.js:
const formData = new FormData();
formData.append('file', fileInput.files[0]);
const response = await fetch('https://cdn.imgpile.com/api/v1/media', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
},
body: formData,
});
const { media } = await response.json();
console.log(media.urls.original); // https://cdn.imgpile.com/f/abc1234.jpgAuthentication
Read endpoints (GET) are public and don't require authentication. All other endpoints require a bearer token.
curl https://imgpile.com/api/v1/postsFor authenticated requests, pass your token in the Authorization header:
curl -H "Authorization: Bearer YOUR_TOKEN" https://cdn.imgpile.com/api/v1/media -F "[email protected]"File uploads target cdn.imgpile.com; see Media โ Upload for details.
Generate a token in the Introduction section above.
Errors
The API returns standard HTTP status codes. Error responses include a JSON body with a message (or error) field describing what went wrong.
Status codes
| Code | Meaning |
|---|---|
200 | OK โ request succeeded |
201 | Created โ resource was created |
400 | Bad Request โ malformed request |
401 | Unauthenticated โ missing or invalid token |
403 | Forbidden โ you don't have permission for this action |
404 | Not Found โ resource doesn't exist |
422 | Validation failed โ request body has invalid fields |
429 | Rate Limited โ too many requests, slow down |
451 | Unavailable for Legal Reasons โ file matched a banned hash |
500 | Server Error โ something went wrong on our end |
Example error responses
401 Unauthenticated
{ "message": "Unauthenticated." }403 Forbidden
{ "message": "This action is unauthorized." }422 Validation failed
{
"message": "The file field is required.",
"errors": {
"file": ["The file field is required."]
}
}429 Rate limited
{ "message": "Too Many Attempts." }Check the Retry-After response header for seconds until the limit resets.
451 Banned content
{ "error": "This file is not allowed." }API Pagination
List endpoints (GET /posts, GET /media) return paginated results. The default page size is 10; you can request up to 250 with ?limit=N.
Use ?page=N to navigate pages. The response includes pagination metadata:
{
"data": [ ... ],
"links": {
"first": "https://imgpile.com/api/v1/posts?page=1",
"last": "https://imgpile.com/api/v1/posts?page=42",
"prev": null,
"next": "https://imgpile.com/api/v1/posts?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"to": 10,
"per_page": 10,
"total": 421,
"last_page": 42
}
}When iterating, follow links.next until it's null, or check meta.current_page against meta.last_page.
Content Filtering
By default, list endpoints (GET /posts, GET /media) only return safe content (moderation status approved). To also include adult content (nsfw), pass ?nsfw=1:
curl https://imgpile.com/api/v1/posts?nsfw=1Banned content (rejected, i.e. spam or abuse) is never returned to public feed endpoints regardless of the ?nsfw flag.
Every post and media response includes a moderation_status field so you can warn, blur, or hide flagged items in your client:
{
"moderation_status": "approved" | "pending" | "nsfw" | "rejected",
...
}approvedโ safe for all audiences.pendingโ awaiting automated moderation.nsfwโ adult content; only returned from public endpoints when?nsfw=1.rejectedโ spam/abuse; never returned to public endpoints.
Hidden posts are accessible by their slug but never appear in feeds. Private posts require an ?key=xxx query parameter (the owner can find this in the post's share link).
Rate Limits
- Public requests (no token): 30 requests/minute per IP
- Authenticated requests: 120 requests/minute per user
- File uploads: 1,000 files/day per user/IP
- Max file size: 100 MB
- Accepted types: image/* and video/*
Rate limit headers are included in every response (X-RateLimit-Limit, X-RateLimit-Remaining).
The Media object
Returned by media endpoints and embedded inside post responses.
| Field | Type | Description |
|---|---|---|
| slug | string | Unique 7-character identifier. Used in URLs. |
| filename | string | Storage filename (same as slug). |
| title | string|null | User-provided title. |
| description | string|null | User-provided description. |
| type | string | MIME type โ e.g. image/jpeg, video/mp4. |
| width | integer | Pixel width. |
| height | integer | Pixel height. |
| moderation_status | enum | One of approved, pending, nsfw, or rejected. See Content Filtering. |
| processed | boolean | false while sized variants are being generated; true when ready. |
| created_at | timestamp | ISO 8601 timestamp. |
| urls | object | CDN URLs at every available size โ see Direct Image URLs. |
| user | object|null | The uploader (username, avatar). Null for guest uploads. |
The Post object
A shareable container for one or more media items.
| Field | Type | Description |
|---|---|---|
| id | integer | Numeric ID. Use slug for URLs. |
| slug | string | Unique 7-character identifier. Used in URLs. |
| title | string|null | Post title. |
| description | string|null | Post description. |
| score | integer | Net vote score (upvotes minus downvotes). |
| view_count | integer | Total page views. |
| media_count | integer | Number of media items in this post. |
| moderation_status | enum | One of approved, pending, nsfw, or rejected. See Content Filtering. |
| isUpvotedByUser | boolean | Whether the authenticated user has upvoted this post. |
| isDownvotedByUser | boolean | Whether the authenticated user has downvoted this post. |
| created_at | timestamp | ISO 8601 timestamp. |
| user | object|null | The author (username, avatar). Null for guest posts. |
| media | array | Array of Media objects. Only included on single-post requests. |
| first_media | object|null | The first media (preview). Only included in feed responses. |
| Owner-only fields (returned to the post's owner only): | ||
| visibility | enum | public, hidden, or private. |
| access_key | string|null | Required to view a private post. Append as ?key=xxx. |
Media endpoints
Individual files (images or videos). Each media has a direct CDN URL you can hotlink or embed anywhere.
Send uploads to https://cdn.imgpile.com/api/v1/media โ not imgpile.com. Files are stored on a dedicated origin; POSTing to the main host will fail.
Every other endpoint uses imgpile.com/api/v1 as usual.
Upload an image or video. Send as multipart/form-data.
| Parameter | Description |
|---|---|
| filerequired | The file to upload. Max 100 MB. Accepts image/* and video/*. |
| post_idoptional | Attach to an existing post. |
curl -X POST https://cdn.imgpile.com/api/v1/media \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "[email protected]"{
"message": "Media created successfully",
"media": {
"slug": "abc1234",
"filename": "abc1234",
"type": "image/jpeg",
"width": 1920,
"height": 1080,
"moderation_status": "approved",
"urls": {
"original": "https://cdn.imgpile.com/f/abc1234.jpg",
...
}
}
}List media items with filtering and pagination.
| Parameter | Description |
|---|---|
| tag | Filter by tag name |
| sort | latest (default) or random |
| period | day, week, month, year, all |
| limit | Results per page (max 250, default 10) |
| username | Filter by username |
| nsfw | Set to 1 to include NSFW content. Default: SFW only. |
curl https://imgpile.com/api/v1/media?limit=20{
"data": [
{
"slug": "abc1234",
"type": "image/jpeg",
"width": 1920,
"height": 1080,
"moderation_status": "approved",
"urls": { ... }
},
...
],
"links": { ... },
"meta": { "current_page": 1, "total": 421 }
}Get a single media item by its slug.
curl https://imgpile.com/api/v1/media/abc1234{
"data": {
"slug": "abc1234",
"type": "image/jpeg",
"width": 1920,
"height": 1080,
"moderation_status": "approved",
"urls": { ... }
}
}Update media you own.
| Parameter | Description |
|---|---|
| title | Media title |
| description | Media description |
curl -X PATCH https://imgpile.com/api/v1/media/abc1234 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "New title"}'{
"message": "Media updated successfully"
}Delete media you own.
curl -X DELETE https://imgpile.com/api/v1/media/abc1234 \
-H "Authorization: Bearer YOUR_TOKEN"{
"message": "Media deleted successfully."
}Post endpoints
Shareable pages that contain one or more media items. Have a title, description, voting, comments, and tags.
List public posts with filtering and pagination.
| Parameter | Description |
|---|---|
| tag | Filter by tag name |
| sort | latest (default) or random |
| period | day, week, month, year, all |
| limit | Results per page (max 250, default 10) |
| username | Filter by username |
| nsfw | Set to 1 to include NSFW content. Default: SFW only. |
curl https://imgpile.com/api/v1/posts?sort=latest{
"data": [
{
"id": 30713,
"slug": "MSGhYqy",
"title": "Sunset photos",
"score": 12,
"view_count": 245,
"media_count": 3,
"moderation_status": "approved",
"user": { "username": "alice", ... },
"first_media": { ... }
},
...
]
}Get a single post with paginated media.
| Parameter | Description |
|---|---|
| mediaPage | Page number for media (default 1) |
| perPage | Media items per page (default 10) |
| key | Required for private posts. The owner can find this in the share link. |
curl https://imgpile.com/api/v1/posts/MSGhYqy
# Private post with key:
curl "https://imgpile.com/api/v1/posts/xyz789?key=ab12cd34ef"{
"data": {
"id": 30713,
"slug": "MSGhYqy",
"title": "Sunset photos",
"description": "...",
"score": 12,
"view_count": 245,
"moderation_status": "approved",
"user": { "username": "alice", ... },
"media": [ ... ]
}
}Create a new post from uploaded media.
| Parameter | Description |
|---|---|
| media_idsrequired | Array of media IDs to include in the post |
curl -X POST https://imgpile.com/api/v1/posts \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"media_ids": [12345, 12346]}'{
"message": "Post created successfully",
"post": {
"id": 30720,
"slug": "rtWJdHr"
}
}Update a post you own.
| Parameter | Description |
|---|---|
| title | Post title (max 255) |
| description | Post description |
| visibility | public, hidden, or private. Setting to private auto-generates an access_key. |
| is_nsfw | Boolean. Mark the post as adult content so it's gated behind the viewer's NSFW toggle. Once set, the post will not auto-resolve below nsfw. |
| media_order | Array of media slugs in desired order |
curl -X PATCH https://imgpile.com/api/v1/posts/rtWJdHr \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "Updated title", "visibility": "private"}'{
"message": "Post updated successfully",
"visibility": "private",
"access_key": "ab12cd34ef"
}Delete a post you own.
curl -X DELETE https://imgpile.com/api/v1/posts/rtWJdHr \
-H "Authorization: Bearer YOUR_TOKEN"{
"message": "Post deleted successfully"
}Users
Get a user's posts.
curl https://imgpile.com/api/v1/users/alice/posts{
"data": [
{
"id": 30713,
"slug": "MSGhYqy",
"title": "Sunset photos",
"score": 12,
"moderation_status": "approved",
"first_media": { ... }
},
...
]
}Get a user's media.
curl https://imgpile.com/api/v1/users/alice/media{
"data": [
{
"slug": "abc1234",
"type": "image/jpeg",
"moderation_status": "approved",
"urls": { ... }
},
...
]
}Get a user's comments (paginated).
curl https://imgpile.com/api/v1/users/alice/commentsGet a user's followers (paginated).
curl https://imgpile.com/api/v1/users/alice/followersGet the users this user is following (paginated).
curl https://imgpile.com/api/v1/users/alice/followingFollow a user.
curl -X POST https://imgpile.com/api/v1/users/alice/follow \
-H "Authorization: Bearer YOUR_TOKEN"{
"message": "User followed."
}Unfollow a user.
curl -X DELETE https://imgpile.com/api/v1/users/alice/follow \
-H "Authorization: Bearer YOUR_TOKEN"{
"message": "User unfollowed."
}Voting
Upvote a post. Calling again removes the upvote.
curl -X POST https://imgpile.com/api/v1/posts/123/upvote \
-H "Authorization: Bearer YOUR_TOKEN"{
"message": "Post upvoted successfully",
"score": 13
}Downvote a post. Calling again removes the downvote.
curl -X POST https://imgpile.com/api/v1/posts/123/downvote \
-H "Authorization: Bearer YOUR_TOKEN"{
"message": "Post downvoted successfully",
"score": 11
}Upvote a comment. Calling again removes the upvote.
curl -X POST https://imgpile.com/api/v1/comments/456/upvote \
-H "Authorization: Bearer YOUR_TOKEN"Downvote a comment. Calling again removes the downvote.
curl -X POST https://imgpile.com/api/v1/comments/456/downvote \
-H "Authorization: Bearer YOUR_TOKEN"Direct Image URLs
Every uploaded file is served via the CDN. The media response includes a urls object with all available sizes:
https://cdn.imgpile.com/f/{filename}.{ext} โ Original
https://cdn.imgpile.com/f/{filename}_xs.{ext} โ Extra small
https://cdn.imgpile.com/f/{filename}_sm.{ext} โ Small
https://cdn.imgpile.com/f/{filename}_md.{ext} โ Medium
https://cdn.imgpile.com/f/{filename}_lg.{ext} โ Large
https://cdn.imgpile.com/f/{filename}_xl.{ext} โ Extra large
https://cdn.imgpile.com/f/{filename}_thumb.jpg โ Thumbnail (videos)
Comments
Add a comment to a post.
curl -X POST https://imgpile.com/api/v1/posts/MSGhYqy/comments \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"content": "Nice shot!"}'{ "success": true, "comment": { "id": 456, "content": "Nice shot!", "user_id": 1, "post_id": 12345 } }Delete a comment you own.
curl -X DELETE https://imgpile.com/api/v1/comments/123 \ -H "Authorization: Bearer YOUR_TOKEN"{ "success": true, "message": "Comment deleted successfully" }