Schedule and automate Pinterest Pins with Zernio API - Image pins, video pins, boards, destination links, and cover images
Quick Reference
| Property | Value |
|---|---|
| Title limit | 100 characters |
| Description limit | 500 characters |
| Images per pin | 1 |
| Videos per pin | 1 |
| Image formats | JPEG, PNG, WebP, GIF |
| Image max size | 32 MB |
| Video formats | MP4, MOV |
| Video max size | 2 GB |
| Video duration | 4 sec - 15 min |
| Scheduling | Yes |
| Inbox | No (Pinterest has no API-accessible inbox) |
| Analytics | No (via Zernio) |
Before You Start
Pinterest is a search engine, not a social feed. Pins are discovered through search and browse, not by followers. This means SEO (title, description, board name) matters more than posting time. Pins have a 3-6 month lifespan, unlike hours on other platforms. Also: boardId is effectively required -- always provide it.
Additional requirements:
- A Pinterest Board is required to pin to (create one in Pinterest or via the Boards API)
- No text-only pins (media is required)
- No carousels or multi-image posts (1 image or 1 video per pin)
- The
linkfield is critical for driving traffic
OAuth Scopes
When a Pinterest account is connected, Zernio requests these scopes:
| Scope | What it enables |
|---|---|
boards:read | List boards during connection and post creation |
boards:write | Create boards via the API |
pins:read | Read pins (permalinks, analytics) |
pins:write | Create pins |
user_accounts:read | Account identity and account analytics |
ads:read, ads:write | Pinterest Ads: read ad accounts, create and manage campaigns |
Zernio requests all scopes in a single OAuth flow when the account is connected (see Connecting Accounts); scopes cannot be requested individually. To check what a connected account can currently do, call Account Health: it reports posting and analytics capability derived from the scopes the user actually granted.
Quick Start
Create a Pin on Pinterest:
const { post } = await zernio.posts.createPost({
content: '10 Tips for Better Photography',
mediaItems: [
{ type: 'image', url: 'https://cdn.example.com/pin-image.jpg' }
],
platforms: [{
platform: 'pinterest',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: {
title: '10 Tips for Better Photography',
boardId: 'YOUR_BOARD_ID',
link: 'https://myblog.com/photography-tips'
}
}],
publishNow: true
});
console.log('Pin created!', post._id);result = client.posts.create_post(
content="10 Tips for Better Photography",
media_items=[
{"type": "image", "url": "https://cdn.example.com/pin-image.jpg"}
],
platforms=[{
"platform": "pinterest",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"title": "10 Tips for Better Photography",
"boardId": "YOUR_BOARD_ID",
"link": "https://myblog.com/photography-tips"
}
}],
publish_now=True
)
post = result.post
print(f"Pin created! {post['_id']}")curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "10 Tips for Better Photography",
"mediaItems": [
{"type": "image", "url": "https://cdn.example.com/pin-image.jpg"}
],
"platforms": [{
"platform": "pinterest",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"title": "10 Tips for Better Photography",
"boardId": "YOUR_BOARD_ID",
"link": "https://myblog.com/photography-tips"
}
}],
"publishNow": true
}'Boards
Every pin belongs to a board. List the boards on a connected account, or create a new one directly through the API (no reconnect needed; the boards:write scope is part of every Pinterest connection).
List Boards
const { data } = await zernio.connect.getPinterestBoards({
path: { accountId: 'YOUR_ACCOUNT_ID' }
});
console.log(data.boards); // [{ id, name, description, privacy, url }]boards = client.accounts.get_pinterest_boards("YOUR_ACCOUNT_ID")
print(boards["boards"])curl "https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/pinterest-boards" \
-H "Authorization: Bearer YOUR_API_KEY"Create a Board
Returns the new board's id, which you can use immediately as platformSpecificData.boardId when creating a pin. privacy accepts PUBLIC (default), PROTECTED, or SECRET.
const { data } = await zernio.connect.createPinterestBoard({
path: { accountId: 'YOUR_ACCOUNT_ID' },
body: {
name: 'Summer Recipes',
description: 'My favorite summer recipes',
privacy: 'PUBLIC'
}
});
console.log(data.board.id);result = client.accounts.create_pinterest_board(
"YOUR_ACCOUNT_ID",
name="Summer Recipes",
description="My favorite summer recipes",
privacy="PUBLIC",
)
print(result["board"]["id"])curl -X POST "https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/pinterest-boards" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Summer Recipes",
"description": "My favorite summer recipes",
"privacy": "PUBLIC"
}'Pinterest rejects duplicate board names on the same account, and secret boards you don't own can't be pinned to. Board creation errors from Pinterest are surfaced with the original message and a 502 status.
Content Types
Image Pin
A single image pinned to a board. The most common pin type. Use 2:3 aspect ratio (1000x1500 px) for optimal display in the Pinterest feed.
const { post } = await zernio.posts.createPost({
content: 'Modern kitchen renovation ideas for small spaces',
mediaItems: [
{ type: 'image', url: 'https://cdn.example.com/kitchen-ideas.jpg' }
],
platforms: [{
platform: 'pinterest',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: {
title: 'Modern Kitchen Renovation Ideas',
boardId: 'YOUR_BOARD_ID',
link: 'https://myblog.com/kitchen-renovation'
}
}],
publishNow: true
});
console.log('Image pin created!', post._id);result = client.posts.create_post(
content="Modern kitchen renovation ideas for small spaces",
media_items=[
{"type": "image", "url": "https://cdn.example.com/kitchen-ideas.jpg"}
],
platforms=[{
"platform": "pinterest",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"title": "Modern Kitchen Renovation Ideas",
"boardId": "YOUR_BOARD_ID",
"link": "https://myblog.com/kitchen-renovation"
}
}],
publish_now=True
)
post = result.post
print(f"Image pin created! {post['_id']}")curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Modern kitchen renovation ideas for small spaces",
"mediaItems": [
{"type": "image", "url": "https://cdn.example.com/kitchen-ideas.jpg"}
],
"platforms": [{
"platform": "pinterest",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"title": "Modern Kitchen Renovation Ideas",
"boardId": "YOUR_BOARD_ID",
"link": "https://myblog.com/kitchen-renovation"
}
}],
"publishNow": true
}'Video Pin
A single video pinned to a board. You can optionally set a custom cover image or auto-extract a frame at a specific time.
const { post } = await zernio.posts.createPost({
content: 'Quick 5-minute breakfast recipe',
mediaItems: [
{ type: 'video', url: 'https://cdn.example.com/recipe.mp4' }
],
platforms: [{
platform: 'pinterest',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: {
title: '5-Minute Breakfast Recipe',
boardId: 'YOUR_BOARD_ID',
link: 'https://myrecipes.com/quick-breakfast',
coverImageUrl: 'https://cdn.example.com/recipe-cover.jpg'
}
}],
publishNow: true
});
console.log('Video pin created!', post._id);result = client.posts.create_post(
content="Quick 5-minute breakfast recipe",
media_items=[
{"type": "video", "url": "https://cdn.example.com/recipe.mp4"}
],
platforms=[{
"platform": "pinterest",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"title": "5-Minute Breakfast Recipe",
"boardId": "YOUR_BOARD_ID",
"link": "https://myrecipes.com/quick-breakfast",
"coverImageUrl": "https://cdn.example.com/recipe-cover.jpg"
}
}],
publish_now=True
)
post = result.post
print(f"Video pin created! {post['_id']}")curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Quick 5-minute breakfast recipe",
"mediaItems": [
{"type": "video", "url": "https://cdn.example.com/recipe.mp4"}
],
"platforms": [{
"platform": "pinterest",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"title": "5-Minute Breakfast Recipe",
"boardId": "YOUR_BOARD_ID",
"link": "https://myrecipes.com/quick-breakfast",
"coverImageUrl": "https://cdn.example.com/recipe-cover.jpg"
}
}],
"publishNow": true
}'Media Requirements
Images
| Property | Requirement |
|---|---|
| Max images | 1 per pin |
| Formats | JPEG, PNG, WebP, GIF |
| Max file size | 32 MB |
| Recommended | 1000 x 1500 px (2:3) |
| Min dimensions | 100 x 100 px |
Aspect Ratios
| Ratio | Dimensions | Use Case |
|---|---|---|
| 2:3 | 1000 x 1500 px | Optimal - Standard Pin |
| 1:1 | 1000 x 1000 px | Square Pin |
| 1:2.1 | 1000 x 2100 px | Long Pin (max height) |
Best practice: Use 2:3 aspect ratio for optimal 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 | 2 GB |
| Duration | 4 seconds - 15 minutes |
| Aspect ratio | 2:3, 1:1, or 9:16 |
| Resolution | 1080p recommended |
| Frame rate | 25+ fps |
Video Specs
| Property | Minimum | Recommended |
|---|---|---|
| Resolution | 240p | 1080p |
| Bitrate | - | 10 Mbps |
| Audio | - | AAC, 128 kbps |
Platform-Specific Fields
All fields go inside platformSpecificData on the Pinterest platform entry.
| Field | Type | Default | Description |
|---|---|---|---|
boardId | string | -- | Effectively required. The board to pin to. Get board IDs via GET /v1/accounts/{accountId}/pinterest-boards, or create a board via POST on the same path. Aliases: board_id, board. |
title | string (max 100 chars) | First line of content | Pin title. Searchable by Pinterest users. |
link | string (URL) | -- | Destination link when users click the pin. Must be valid HTTPS. No URL shorteners. Most important field for driving traffic. Aliases: url. |
coverImageUrl | string (URL) | -- | Custom cover image for video pins. Aliases: cover_image_url, thumbnailUrl, thumbnail_url. |
coverImageKeyFrameTime | number (seconds) | 0 | Auto-extract a video frame at N seconds to use as cover. Ignored if coverImageUrl is set. |
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, it will not work.
Media URLs must be:
- Publicly accessible (no authentication required)
- Returning actual media bytes with the correct
Content-Typeheader - Not behind redirects that resolve to HTML pages
- Hosted on a fast, reliable CDN
Analytics
Included — Analytics is bundled with every paid account on the Usage plan.
Available metrics via the Analytics API:
| Metric | Available |
|---|---|
| Impressions | |
| Saves | |
| Clicks |
const analytics = await zernio.analytics.getAnalytics({
platform: 'pinterest',
fromDate: '2024-01-01',
toDate: '2024-01-31'
});
console.log(analytics.posts);analytics = client.analytics.get_analytics(
platform="pinterest",
from_date="2024-01-01",
to_date="2024-01-31"
)
print(analytics["posts"])curl "https://zernio.com/api/v1/analytics?platform=pinterest&fromDate=2024-01-01&toDate=2024-01-31" \
-H "Authorization: Bearer YOUR_API_KEY"What You Can't Do
These features are not available through Pinterest's API:
- Create Idea Pins (multi-page stories)
- Claim website
- Create Rich Pins (requires meta tags on your website)
- Access Pinterest Analytics (via Zernio)
- Create Shopping catalogs
- Edit or delete pins after creation (via Zernio)
- Create multi-image posts or carousels
Common Errors
Pinterest has a 21.1% failure rate across Zernio's platform (7,928 failures out of 37,646 attempts). Here are the most frequent errors and how to fix them:
| Error | Meaning | Fix |
|---|---|---|
| "Invalid URL or request data." | Pinterest could not process the URL or request data | Verify media URL is publicly accessible, returns actual media bytes, and uses HTTPS. |
| "Unable to reach the URL. Please check the URL is correct and try again." | Pinterest's servers cannot fetch your media | Test the URL in an incognito browser. Ensure no authentication is required and there are no redirects to HTML pages. |
| "Pinterest rate limit reached." | Too many API calls in a short window | Space out pins. Avoid bursts of 10+ pins at once. |
| "Pinterest requires a boardId. Provide platformSpecificData.boardId." | No board was specified in the request | Always provide boardId. List available boards with GET /v1/accounts/{accountId}/pinterest-boards. |
Inbox
Pinterest does not have inbox features available via API.
- No DMs -- Pinterest's messaging API is not available for third-party apps
- No comments -- Pin comments are not accessible via API
- No reviews -- Pinterest does not have a reviews system
Related Endpoints
- Connect Pinterest Account - OAuth flow
- Create Post - Pin creation and scheduling
- Upload Media - Image and video uploads
- Pinterest Boards - List boards for an account
- Create Pinterest Board - Create a new board