Posts
Create Pinterest pins through the shared posts API with image pins and video pins with board selection.
Publish pins to Pinterest boards through the shared posts surface. Every destination must include an explicit boardId.
Quick Start
Create a pin in under a minute:
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.createPost({
createPostBody: {
"text": "Ship day",
"mediaUrls": [
"https://cdn.onepostly.com/media/product.jpg"
],
"mediaKind": "image",
"destinations": [
{
"accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
"boardId": "1234567890123456789"
}
]
},
});
console.log(response);{
"post": {
"id": "b3e1a7c2-8f4d-4e6a-9c1b-2d3e4f5a6b7c",
"text": "Ship day",
"mediaUrls": [
"https://cdn.onepostly.com/media/product.jpg"
],
"mediaKind": "image",
"status": "queued",
"scheduledFor": null,
"timezone": null,
"destinations": [
{
"id": "d4e5f6a7-8b9c-4d0e-8f1a-2b3c4d5e6f7a",
"accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
"platform": "pinterest",
"status": "draft",
"externalPostId": "17895695668004550",
"externalUrl": "https://www.pinterest.com/pin/17895695668004550/",
"errorCode": null,
"errorMessage": null,
"publishedAt": "2026-08-25T10:00:00.000Z",
"metrics": null
}
],
"createdAt": "2026-08-25T10:00:00.000Z",
"updatedAt": "2026-08-25T10:00:00.000Z"
}
}The response is 202 Accepted with status: "queued". When published, the destination carries the pin id (externalPostId) and a https://www.pinterest.com/pin/PIN_ID/ link. Poll GET /v1/posts/:id or receive webhooks.
Content Types
Image Pin
A single image pinned to a board. Use 2:3 aspect ratio (1000 × 1500 px) for optimal display in the Pinterest feed.
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.createPost({
createPostBody: {
"text": "10 Tips for Better Photography",
"mediaUrls": [
"https://cdn.example.com/photo.jpg"
],
"mediaKind": "image",
"destinations": [
{
"accountId": "YOUR_PINTEREST_ACCOUNT_ID",
"boardId": "YOUR_BOARD_ID",
"link": "https://myblog.com/photography-tips"
}
]
},
});
console.log(response);{
"post": {
"id": "b3e1a7c2-8f4d-4e6a-9c1b-2d3e4f5a6b7c",
"text": "10 Tips for Better Photography",
"mediaUrls": [
"https://cdn.example.com/photo.jpg"
],
"mediaKind": "image",
"status": "queued",
"scheduledFor": null,
"timezone": null,
"destinations": [
{
"id": "d4e5f6a7-8b9c-4d0e-8f1a-2b3c4d5e6f7a",
"accountId": "YOUR_PINTEREST_ACCOUNT_ID",
"platform": "pinterest",
"status": "draft",
"externalPostId": "17895695668004550",
"externalUrl": "https://www.pinterest.com/pin/17895695668004550/",
"errorCode": null,
"errorMessage": null,
"publishedAt": "2026-08-25T10:00:00.000Z",
"metrics": null
}
],
"createdAt": "2026-08-25T10:00:00.000Z",
"updatedAt": "2026-08-25T10:00:00.000Z"
}
}Video Pin
A single video pinned to a board. Video uploads are processed asynchronously on Pinterest. The pin becomes visible once processing completes. Add coverImageUrl to set a custom cover; otherwise Pinterest extracts a frame from the video.
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.createPost({
createPostBody: {
"text": "5-Minute Breakfast Recipe",
"mediaUrls": [
"https://cdn.example.com/recipe.mp4"
],
"mediaKind": "video",
"destinations": [
{
"accountId": "YOUR_PINTEREST_ACCOUNT_ID",
"boardId": "YOUR_BOARD_ID",
"link": "https://myrecipes.com/quick-breakfast",
"coverImageUrl": "https://cdn.example.com/recipe-cover.jpg"
}
]
},
});
console.log(response);{
"post": {
"id": "b3e1a7c2-8f4d-4e6a-9c1b-2d3e4f5a6b7c",
"text": "5-Minute Breakfast Recipe",
"mediaUrls": [
"https://cdn.example.com/recipe.mp4"
],
"mediaKind": "video",
"status": "queued",
"scheduledFor": null,
"timezone": null,
"destinations": [
{
"id": "d4e5f6a7-8b9c-4d0e-8f1a-2b3c4d5e6f7a",
"accountId": "YOUR_PINTEREST_ACCOUNT_ID",
"platform": "pinterest",
"status": "draft",
"externalPostId": "17895695668004550",
"externalUrl": "https://www.pinterest.com/pin/17895695668004550/",
"errorCode": null,
"errorMessage": null,
"publishedAt": "2026-08-25T10:00:00.000Z",
"metrics": null
}
],
"createdAt": "2026-08-25T10:00:00.000Z",
"updatedAt": "2026-08-25T10:00:00.000Z"
}
}Media Requirements
Images
| Property | Requirement |
|---|---|
| Max images | 1 per pin |
| Formats | JPEG, PNG, WebP, GIF |
| Max file size | 32 MB |
| Recommended | 1000 × 1500 px (2:3 aspect ratio) |
| Min dimensions | 100 × 100 px |
Aspect ratios
| Ratio | Dimensions | Use Case |
|---|---|---|
| 2:3 | 1000 × 1500 px | Optimal, Standard Pin |
| 1:1 | 1000 × 1000 px | Square Pin |
| 1:2.1 | 1000 × 2100 px | Long Pin (max height) |
Use 2:3 for the best display in the Pinterest feed.
GIFs
Pinterest supports animated GIFs. They auto-play in the feed and are treated as images (not video). Max file size is 32 MB, but keeping under 10 MB is recommended for fast loading.
Videos
| Property | Requirement |
|---|---|
| Max videos | 1 per pin |
| Formats | MP4, MOV |
| Max file size | 64 MB through Onepostly |
| Duration | 4 seconds - 15 minutes |
| Aspect ratio | 2:3, 1:1, or 9:16 |
| Property | Minimum | Recommended |
|---|---|---|
| Resolution | 240p | 1080p |
| Frame rate | 25 fps | 30 fps |
Media URL Requirements
These do not work as media URLs:
- Google Drive returns an HTML download page, not the file
- Dropbox returns an HTML preview page
- OneDrive / SharePoint returns HTML
- iCloud returns HTML
Test your URL in an incognito browser window. If you see a webpage instead of the raw image or video, the URL will not work.
Media URLs must be publicly accessible, return actual media bytes with the correct Content-Type, and use HTTPS.
Destination Parameters
Every Pinterest destination accepts the following parameters:
Prop
Type
The post text is the Pin description, capped at 800 characters; longer requests are rejected with VALIDATION_ERROR. The title falls back to the first line of the post text when omitted.
The Pin title is derived from the first line of the post text, not the whole
text. To set a different title, pass title explicitly.
Schedule
Add scheduledFor (local wall time) and timezone to create a scheduled pin:
timezonedefaults toUTC. Use an IANA name likeEurope/Istanbul- Do not append
Zor an offset toscheduledFor: it is local wall time - Max 1 year ahead
- Cancel with
DELETE /v1/posts/:idany time before it publishes
Remote Delete
Removes the pin from the board:
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.deletePostDestination({
destinationId: "d4e5f6a7-8b9c-4d0e-8f1a-2b3c4d5e6f7a",
});
console.log(response);{
"post": {
"id": "b3e1a7c2-8f4d-4e6a-9c1b-2d3e4f5a6b7c",
"text": "Ship day",
"mediaUrls": [
"https://cdn.onepostly.com/media/product.jpg"
],
"mediaKind": "image",
"status": "queued",
"scheduledFor": null,
"timezone": null,
"destinations": [
{
"id": "d4e5f6a7-8b9c-4d0e-8f1a-2b3c4d5e6f7a",
"accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
"platform": "pinterest",
"status": "draft",
"externalPostId": "17895695668004550",
"externalUrl": "https://www.pinterest.com/pin/17895695668004550/",
"errorCode": null,
"errorMessage": null,
"publishedAt": "2026-08-25T10:00:00.000Z",
"metrics": null
}
],
"createdAt": "2026-08-25T10:00:00.000Z",
"updatedAt": "2026-08-25T10:00:00.000Z"
}
}Publish Errors
| Code | Cause | Fix |
|---|---|---|
VALIDATION_ERROR | Missing destinations[].boardId, a non-HTTPS link, or a shortened link | Send a board id and a full HTTPS destination URL |
MEDIA_REQUIRED | No media URL passed | Add at least one entry to mediaUrls |
INVALID_MEDIA | Unsupported type, size, or a multi-image pin | Pinterest pins accept one image or one video |
MEDIA_UNFETCHABLE | Pinterest could not download the URL | Use a public HTTPS URL |
MEDIA_UPLOAD_FAILED | Video upload or processing failed | Retry; check the file plays correctly |
BOARD_NOT_FOUND | The board id does not exist | List boards and pass a valid id |
TOKEN_INVALID | Connection token expired or revoked | Reconnect the account |
PERMISSION_DENIED | Connection lacks pins:write | Reconnect the account |
UNSUPPORTED_FEATURE | Thread, quote, or reply sent to Pinterest | Remove them. They are not Pinterest concepts |
UNSUPPORTED_MEDIA_KIND | mediaKind: "text", "stories", or "multi-image" | Use image or video |
RATE_LIMITED | Pinterest throttled the request | Retry later |