Scheduling Pins
This guide walks you through the complete process of scheduling a pin to Pinterest using the Tailwind API.
Overview
Section titled “Overview”Scheduling a pin involves four steps:
- Get your Pinterest accounts
- Choose a board to pin to
- Create the post with a schedule time
- Verify the post was scheduled
Prerequisites
Section titled “Prerequisites”- A Tailwind account with at least one Pinterest account connected
- Your API key
- A media URL to pin (image or video)
Step 1: List Your Accounts
Section titled “Step 1: List Your Accounts”First, retrieve your Pinterest accounts to get the account ID you’ll use for scheduling.
curl -X GET https://api-v1.tailwind.ai/v1/accounts \ -H "Authorization: Bearer YOUR_API_KEY"Response:
{ "data": { "accounts": [ { "id": "123456", "userId": "987654321", "displayName": "My Pinterest", "username": "mypinterest", "avatarUrl": "https://...", "tokenAuthorized": true, "isDomainVerified": true, "createdAt": 1705314600 } ] }, "meta": { "requestId": "req_abc123" }}Note the id field (123456) - you’ll need this for subsequent requests.
Step 2: Get Available Boards
Section titled “Step 2: Get Available Boards”List the boards for your account to find where you want to pin.
curl -X GET https://api-v1.tailwind.ai/v1/accounts/123456/boards \ -H "Authorization: Bearer YOUR_API_KEY"Response:
{ "data": { "boards": [ { "id": "1106196864631757445", "name": "Recipe Ideas", "isCollaborator": false, "isSecret": false }, { "id": "1106196864631757446", "name": "Home Decor", "isCollaborator": false, "isSecret": false } ] }, "meta": { "requestId": "req_def456" }}Step 3: Create and Schedule the Post
Section titled “Step 3: Create and Schedule the Post”Create a post with all the pin details and a scheduled time.
The examples use a date in 2099 so the request remains valid when copied. Replace it with the future date and time you actually want.
curl -X POST https://api-v1.tailwind.ai/v1/accounts/123456/posts \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "mediaUrl": "https://example.com/my-beautiful-image.jpg", "title": "Amazing Recipe You Must Try", "description": "This delicious recipe will become your new favorite! Easy to make and perfect for weeknight dinners. #recipes #cooking #dinner", "url": "https://myblog.com/amazing-recipe", "boardId": "1106196864631757445", "altText": "A colorful plate of pasta with fresh vegetables", "sendAt": "2099-01-20T14:00:00Z" }'Response:
{ "data": { "post": { "id": "post_abc123", "status": "queued", "mediaUrl": "https://example.com/my-beautiful-image.jpg", "mediaType": "image", "title": "Amazing Recipe You Must Try", "description": "This delicious recipe will become your new favorite!...", "url": "https://myblog.com/amazing-recipe", "boardId": "1106196864631757445", "altText": "A colorful plate of pasta with fresh vegetables", "isSimplifiedPin": true, "sendAt": 4072600800, "sentAt": null, "createdAt": 1705320000, "pinId": null } }, "meta": { "requestId": "req_ghi789" }}The post is now scheduled! The status: "queued" confirms it’s in the queue.
Step 4: Verify Your Scheduled Post
Section titled “Step 4: Verify Your Scheduled Post”List your queued posts to verify everything looks correct.
curl -X GET "https://api-v1.tailwind.ai/v1/accounts/123456/posts?status=queued" \ -H "Authorization: Bearer YOUR_API_KEY"Scheduling a Video Pin
Section titled “Scheduling a Video Pin”To schedule a video pin, set mediaType to "video" and provide a URL to a video file (.mp4, .mov, or .qt). External video URLs are automatically uploaded and processed.
curl -X POST https://api-v1.tailwind.ai/v1/accounts/123456/posts \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "mediaUrl": "https://example.com/my-video.mp4", "mediaType": "video", "title": "Watch This Amazing Tutorial", "description": "Step-by-step guide to creating beautiful content #tutorial #video", "url": "https://myblog.com/tutorial", "boardId": "1106196864631757445", "sendAt": "2099-01-20T14:00:00Z" }'The response is the same as for image pins, with mediaType: "video".
Creating Draft Posts
Section titled “Creating Draft Posts”If you want to save a post without scheduling it, simply omit the sendAt field:
curl -X POST https://api-v1.tailwind.ai/v1/accounts/123456/posts \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "mediaUrl": "https://example.com/image.jpg", "title": "Draft Post", "description": "I will schedule this later", "boardId": "1106196864631757445" }'The post will be created with status: "draft". Including title, description, url, and boardId is recommended so the draft can be scheduled later without additional updates.
A draft is a Tailwind state, not a Pinterest draft. Nothing is created on Pinterest: the Pin does not appear in Pinterest’s own drafts or on the profile, and it stays unpublished until you schedule it with the endpoint below. Scheduling is the step that puts it into Tailwind’s publishing flow.
Scheduling a Draft Post
Section titled “Scheduling a Draft Post”To schedule a draft post later, use the schedule endpoint. The post must already have title, description, url, and boardId set. If the draft doesn’t have a boardId, you can provide one in the request body:
curl -X POST https://api-v1.tailwind.ai/v1/accounts/123456/posts/post_abc123/schedule \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "sendAt": "2099-01-25T09:00:00Z", "boardId": "1106196864631757445" }'Using Smart Schedule Timeslots
Section titled “Using Smart Schedule Timeslots”Instead of picking a specific time, you can use your smart schedule timeslots. First, list your timeslots:
curl -X GET https://api-v1.tailwind.ai/v1/accounts/123456/timeslots \ -H "Authorization: Bearer YOUR_API_KEY"Response:
{ "data": { "timeslots": [ { "id": "98765", "accountId": "123456", "dayPreference": 1, "timePreference": "09:00", "timezone": "America/New_York", "type": "auto-created", "sendAt": 4072600800 } ] }}The timeslot’s sendAt value is a Unix timestamp. Convert it to an ISO 8601 string before using it in a create or schedule request. For example, in JavaScript: new Date(timeslot.sendAt * 1000).toISOString().
Best Practices
Section titled “Best Practices”Pin Titles
Section titled “Pin Titles”- Keep titles under 100 characters
- Make them descriptive and keyword-rich
- Front-load the most important words
Pin Descriptions
Section titled “Pin Descriptions”- Use up to 500 characters
- Include relevant keywords naturally
- Add 2-5 relevant hashtags at the end
- Include a call to action
Alt Text
Section titled “Alt Text”- Describe the image for accessibility
- Keep it factual and descriptive
- Helps with Pinterest search too
Scheduling Times
Section titled “Scheduling Times”- Use ISO 8601 format, such as
2099-01-20T14:00:00Z - Use a time in the future
- Consider your audience’s timezone
Required Fields When Scheduling
Section titled “Required Fields When Scheduling”When scheduling a post (i.e., sendAt is provided), the following fields are required:
| Field | Description |
|---|---|
mediaUrl or uploadId |
Media source — a publicly accessible URL, or an uploadId from your own file upload (see Uploading Media). Exactly one is required. |
title |
Pin title (max 100 characters) |
description |
Pin description (max 500 characters) |
url |
Destination URL when the pin is clicked |
boardId |
Target board ID |
sendAt |
When to publish the pin (ISO 8601) |
If you omit sendAt, the post is saved as a draft and only a media source (mediaUrl or uploadId) is required.
Error Handling
Section titled “Error Handling”Common errors when scheduling:
| Error Code | Meaning | Solution |
|---|---|---|
| 400 | Invalid request | Check required fields and formats. When scheduling, title, description, url, and boardId are all required. A 400 from the schedule endpoint can also mean the post can’t be scheduled as it stands, such as a draft saved with multiple interval Boards. Retrying unchanged fails the same way. |
| 401 | Unauthorized | Verify your API key |
| 402 | Payment required | The account does not have an available scheduling credit or trial allowance. |
| 404 | Account not found | Check the account ID |
| 409 | Conflict | Another request is updating the account’s schedule (retry shortly), or the post changed status mid-request (read it back before retrying). |
| 422 | Unprocessable media | Ensure the media URL is publicly accessible and points to a valid file |
Example error response:
{ "error": { "code": "BAD_REQUEST", "message": "sendAt must be in the future" }, "meta": { "requestId": "req_xyz789" }}Next Steps
Section titled “Next Steps”- View JavaScript examples for a complete implementation
- Learn about rate limits
- Explore the MCP Server for AI-powered scheduling
