Developers

Build on 365 Pinterest

A public REST API and an MCP server, so your apps and AI clients can list boards, create and schedule pins, check the queue, and read analytics — plus WordPress + AI blog: connect a site, generate a draft with Workers AI, and publish it to WordPress with its Pinterest pin — all scoped to your own account.

Authentication

Every request authenticates with an API key, sent as a Bearer token. Create one in the dashboard — it is shown once, so copy it immediately. Keys are scoped to your account only: they can never see or touch another user's boards or pins. Revoke a key any time from the same page; revoked keys stop working immediately. Keys are app-level, not per Pinterest account: you can connect several Pinterest accounts in the dashboard and switch between them in the sidebar. API calls operate on your active (newest) account by default; pass account_id (query string for GET, body field for POST, tool argument for MCP) to target a specific connected account instead. An unknown account id returns 404.

Authorization header
Authorization: Bearer pk_live_YOUR_KEY_HERE

Rate limit: 60 requests per minute per key. Exceeding it returns HTTP 429 with a Retry-After header. Errors are plain JSON: { "error": "..." }. Base URL for every endpoint below: https://365pinterest.com

REST API reference

Versioned under /api/v1/. Creating a pin never publishes it directly — a future scheduledFor makes it SCHEDULED (the scheduler publishes it at the due time); otherwise it is a DRAFT. Replace pk_live_YOUR_KEY_HERE with your real key, and BOARD_ID / PIN_ID with real ids from the API.

GET/api/v1/account

Account status

Whether a Pinterest account is connected, the username, granted scopes, and how many boards are cached. Pass ?account_id= to target one of your connected accounts; omit it for the active (newest) account.

curl
curl https://365pinterest.com/api/v1/account \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE"
GET/api/v1/boards

List boards

All boards on the connected account (id, name, description, privacy, pin count). Served from the local cache when available, otherwise fetched live from Pinterest once and cached. Pass ?account_id= to list another connected account's boards.

curl
curl https://365pinterest.com/api/v1/boards \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE"
POST/api/v1/boards

Create a board

Creates a board on Pinterest and caches it. privacy is optional (PUBLIC, PROTECTED, or SECRET). Pass account_id in the body to create it on another connected account.

curl
curl -X POST https://365pinterest.com/api/v1/boards \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"name": "Weeknight dinners", "description": "Fast recipes for busy evenings", "privacy": "PUBLIC"}'
POST/api/v1/pins

Create a pin (JSON)

Creates a pin from an image URL. A future scheduledFor makes it SCHEDULED (published by the scheduler at that time); without one it is a DRAFT. Creation never publishes directly. boardId is the cached board id from List boards (a Pinterest board id is also accepted).

curl
curl -X POST https://365pinterest.com/api/v1/pins \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"title": "Creamy garlic pasta", "description": "Ready in 20 minutes.", "destinationUrl": "https://example.com/garlic-pasta", "boardId": "BOARD_ID", "imageUrl": "https://example.com/pasta.jpg", "scheduledFor": "2026-11-20T09:00:00Z"}'
POST/api/v1/pins

Create a pin (file upload)

Same as above, but uploads an image file (JPEG, PNG, or WebP, max 10 MB) instead of passing an imageUrl. The file is stored on Cloudinary first. Returns 503 when image uploads are not configured.

curl
curl -X POST https://365pinterest.com/api/v1/pins \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE" \
  -F "title=Creamy garlic pasta" \
  -F "boardId=BOARD_ID" \
  -F "scheduledFor=2026-11-20T09:00:00Z" \
  -F "file=@./pasta.jpg"
GET/api/v1/pins

List pins

Pins in your account, newest first. Filter with ?status= (DRAFT, SCHEDULED, POSTING, PUBLISHED, FAILED), ?boardId=, and ?limit= (default 50, max 100). Pass ?account_id= to list one connected account's pins; omit it to list pins across all your accounts.

curl
curl "https://365pinterest.com/api/v1/pins?status=SCHEDULED&limit=20" \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE"
POST/api/v1/pins/[id]/schedule

Schedule a pin

Moves a draft (or failed) pin to SCHEDULED for a future time. Published pins and pins currently publishing return 409.

curl
curl -X POST https://365pinterest.com/api/v1/pins/PIN_ID/schedule \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"scheduledFor": "2026-11-21T09:00:00Z"}'
POST/api/v1/pins/[id]/cancel

Cancel a scheduled pin

Cancels a scheduled pin: SCHEDULED back to DRAFT, with the scheduled time cleared. A pin that is not SCHEDULED returns 409.

curl
curl -X POST https://365pinterest.com/api/v1/pins/PIN_ID/cancel \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE"
GET/api/v1/queue

Get the queue

Up-next: scheduled pins ordered by scheduled time, with board names. These are the pins the scheduler will publish next. Pass ?account_id= for one account's queue; omit it for the queue across all your accounts.

curl
curl https://365pinterest.com/api/v1/queue \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE"
GET/api/v1/analytics

Account analytics

Account analytics for the last 30 days: total impressions, saves, clicks, and outbound clicks. Totals are honest zeros when Pinterest returns no data — numbers are never invented. Pass ?account_id= for one connected account; omit it for the active (newest) account.

curl
curl https://365pinterest.com/api/v1/analytics \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE"

WordPress + AI blog

Connect a WordPress site, generate a blog draft with Workers AI, and publish it to WordPress with its Pinterest pin in one call. Writing a draft never publishes it — the draft is saved first, and the publish endpoint posts it. Publishing needs a board and an image to also create the pin; without them the WordPress post still publishes but no pin is made. Replace pk_live_YOUR_KEY_HERE with your real key, and SITE_ID / POST_ID / BOARD_ID with real ids from the API.

GET/api/v1/wordpress/sites

List WordPress sites

Your connected WordPress sites (id, site URL, site name, username). App passwords are stored encrypted and are never returned.

curl
curl https://365pinterest.com/api/v1/wordpress/sites \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE"
POST/api/v1/wordpress/sites

Connect a WordPress site

Connects a WordPress site with an application password (WordPress Users > Profile > Application Passwords). The site is verified against the live WordPress REST API before it is saved. Connecting a site that is already connected updates its saved details.

curl
curl -X POST https://365pinterest.com/api/v1/wordpress/sites \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"siteUrl": "https://example.com", "username": "editor", "appPassword": "abcd EFGH ijkl MNOP"}'
DELETE/api/v1/wordpress/sites/[id]

Disconnect a WordPress site

Removes a connected site and its blog posts. Linked Pinterest pins stay as normal pins. Unknown ids return 404.

curl
curl -X DELETE https://365pinterest.com/api/v1/wordpress/sites/SITE_ID \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE"
GET/api/v1/wordpress/blog-posts

List blog posts

Blog posts, newest first. Filter with ?siteId= and ?limit= (default 50, max 100). List entries omit contentHtml; the full body comes back when a draft is written or published.

curl
curl "https://365pinterest.com/api/v1/wordpress/blog-posts?limit=20" \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE"
POST/api/v1/wordpress/blog-posts

Write a blog post (AI draft)

Generates a blog draft with Workers AI for one of your connected sites and saves it as a DRAFT. tone is friendly, professional, or storytelling (default friendly); length is short, medium, or long (default medium). The response includes the full contentHtml.

curl
curl -X POST https://365pinterest.com/api/v1/wordpress/blog-posts \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"siteId": "SITE_ID", "topic": "10 weeknight dinners under 30 minutes", "keywords": ["quick dinners", "meal prep"], "tone": "friendly", "length": "medium"}'
POST/api/v1/wordpress/blog-posts/[id]/publish

Publish a blog post + pin

Publishes a draft to WordPress and creates its Pinterest pin in one call. Pass boardId (cached board id) or pinterestBoardId to make the pin; the Pinterest account is resolved from the board, or pass accountId instead. Without a board and an image the WordPress post still publishes but no pin is made. status is publish (default) or draft. imageUrl is an https cover image, or set generateImage to true to generate one with Workers AI (imagePrompt optional). title, contentHtml, excerpt, and tags are edited draft fields — they are validated and applied before posting. The response has the post, wordpressPostUrl, pin, pinterestPinId, and pinterestPinUrl.

curl
curl -X POST https://365pinterest.com/api/v1/wordpress/blog-posts/POST_ID/publish \
  -H "Authorization: Bearer pk_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"boardId": "BOARD_ID", "generateImage": true}'

MCP server

The same features are available to AI clients over the Model Context Protocol, at https://365pinterest.com/mcp (Streamable HTTP, stateless). Authenticate with the same Bearer API key. It works with Claude Desktop, Claude Code, and any standard MCP client.

Claude Desktop

Add this to your Claude Desktop config file (claude_desktop_config.json), replacing the placeholder key with a real one, then restart Claude Desktop.

claude_desktop_config.json
{
  "mcpServers": {
    "365-pinterest": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://365pinterest.com/mcp",
        "--header",
        "Authorization: Bearer pk_live_YOUR_KEY_HERE"
      ]
    }
  }
}

Claude Code

Run this once in your terminal (replace the placeholder key):

Terminal
claude mcp add --transport http 365-pinterest https://365pinterest.com/mcp --header "Authorization: Bearer pk_live_YOUR_KEY_HERE"

Available tools

  • account_status

    Connection status, username, scopes, board count. Optional account_id.

  • list_boards

    List boards (id, name, description, privacy, pin count). Optional account_id.

  • create_pin

    Create a draft pin, or a scheduled pin with scheduledFor. Optional account_id.

  • schedule_pin

    Schedule an existing draft pin for a future time.

  • list_pins

    List pins, filtered by status and/or board. Optional account_id (omit to list across all accounts).

  • get_queue

    Up-next scheduled pins, ordered by scheduled time. Optional account_id.

  • get_analytics

    Last-30-days totals: impressions, saves, clicks, outbound clicks. Optional account_id.

  • wordpress_sites

    List connected WordPress sites. App passwords are never returned.

  • connect_wordpress

    Connect a WordPress site with siteUrl, username, and appPassword. Verified against the live WordPress API first.

  • write_blog_post

    Generate a blog draft with Workers AI for a connected site. siteId and topic required; keywords, tone, and length optional.

  • publish_blog_post

    Publish a draft to WordPress and create its Pinterest pin. postId required; boardId or pinterestBoardId, status, image options, and edited draft fields optional.

  • list_blog_posts

    List blog posts, newest first. Optional siteId and limit (default 50, max 100).

Tools return structured JSON. Errors never leak internals — a missing or revoked key returns a JSON-RPC authentication error, and a request over the 60-per-minute limit returns a rate-limit error.