- **`source_url` should match the page where the action would naturally happen** — Pinterest sometimes rejects writes when `source_url` is just `/`. Use the board/pin URL the action targets (e.g. `/<username>/<board-slug>/`).
Resources
7Install
npx skillscat add imoonkey/openweb/src-sites-pinterest Install via the SkillsCat registry.
SKILL.md
Overview
Visual discovery and bookmarking platform. Social media archetype.
Workflows
Search and explore pins
searchPins(query)→ results with pinid, images, titles, board/pinner infogetPin(id)→ full pin detail with description, link, engagement stats
Explore boards and users
searchPins(query)→ results includepinner.usernameandboardsluggetBoard(username, slug)→ board detail with pin count, followersgetUserProfile(username)→ user profile with follower/following counts, bio
Quick search suggestions
searchTypeahead(term)→ autocomplete suggestions for pins, boards, users
Save a pin to a board (verified)
searchPins(query)orgetHomeFeed()→ find pin →id(=pin_id)searchPins(query)→ result includespinner.usernameandboardsluggetBoard(username, slug)→ target board →board_idsavePin(pin_id ← searchPins, board_id ← getBoard)→ response includes the saved-pin recordid(NOT the same aspin_id) and the chosenboard.id
Remove a saved pin (verified, requires cross-op chain)
savePin(...)→resource_response.data.id(saved-pin record id),resource_response.data.board.idunsavePin(id ← savePin response, board_id ← savePin response)—PinResource/delete/requires the saved-pin record id, not the originalpin_id. Inexample.jsonuse${prev.savePin.resource_response.data.id}and${prev.savePin.resource_response.data.board.id}so verify chains the IDs.
Follow and unfollow boards (verified)
searchPins(query)→ result includespinner.usernameandboardsluggetBoard(username, slug)→board_idfollowBoard(board_id)→ wrapsPOST /v3/boards/{board_id}/follow/inside/resource/ApiResource/update/unfollowBoard(board_id)→ wraps the same v3 URL inside/resource/ApiResource/delete/
Browse home feed and notifications
getHomeFeed()→ personalized recommended pinsgetNotifications()→ recent activity (repins, follows, comments)
Operations
| Operation | Intent | Key Input | Key Output | Notes |
|---|---|---|---|---|
| searchPins | search pins by keyword | query, scope, page_size | id, images, grid_title, description, pinner, board, bookmark | entry point; paginated via bookmark |
| getPin | get pin details | id ← searchPins | title, description, link, images, pinner, board, repin/reaction/comment counts | |
| getBoard | get board details | username + slug (e.g. WhoWhatWear/travel) |
name, description, pin_count, follower_count, owner, cover images | |
| getUserProfile | get user profile | username | full_name, about, follower/following/pin/board counts, image | |
| searchTypeahead | typeahead suggestions | term | label, type, id, images | |
| savePin | save pin to board | pin_id ← searchPins/getHomeFeed, board_id ← getBoard | resource_response.data.id (saved-pin record), resource_response.data.board.id | write; reverse: unsavePin |
| unsavePin | remove saved pin from board | id ← savePin (saved-pin record), board_id ← savePin | status | write; reverse: savePin. Use ${prev.savePin.resource_response.data.{id,board.id}} |
| followBoard | follow a board | board_id ← getBoard (URL /v3/boards/{board_id}/follow/) |
id, name, url, followed_by_me | write; routed via /resource/ApiResource/update/; reverse: unfollowBoard |
| unfollowBoard | unfollow a board | board_id ← getBoard (URL /v3/boards/{board_id}/follow/) |
status | write; routed via /resource/ApiResource/delete/; reverse: followBoard |
| getHomeFeed | personalized home feed | page_size | id, images, grid_title, pinner, board, bookmark | paginated via bookmark |
| getNotifications | notification feed | page_size | id, type, message, timestamp, actors, target, bookmark | paginated via bookmark |
Quick Start
# Search for cat pins
openweb pinterest exec searchPins '{"source_url":"/search/pins/?q=cats","data":"{\"options\":{\"query\":\"cats\",\"scope\":\"pins\",\"page_size\":25},\"context\":{}}"}'
# Get pin details
openweb pinterest exec getPin '{"source_url":"/pin/12345/","data":"{\"options\":{\"id\":\"12345\",\"field_set_key\":\"detailed\"},\"context\":{}}"}'
# Get board details
openweb pinterest exec getBoard '{"source_url":"/WhoWhatWear/travel/","data":"{\"options\":{\"slug\":\"WhoWhatWear/travel\",\"field_set_key\":\"detailed\"},\"context\":{}}"}'
# Get user profile
openweb pinterest exec getUserProfile '{"source_url":"/pinterest/","data":"{\"options\":{\"username\":\"pinterest\",\"field_set_key\":\"profile\"},\"context\":{}}"}'
# Save a pin to a board
openweb pinterest exec savePin '{"source_url":"/","data":"{\"options\":{\"pin_id\":\"PIN_ID\",\"board_id\":\"BOARD_ID\",\"section_id\":null},\"context\":{}}"}'
# Unsave a pin (uses PinResource/delete — id is the saved-pin record id from savePin response, NOT the original pin_id)
openweb pinterest exec unsavePin '{"source_url":"/","data":"{\"options\":{\"id\":\"SAVED_PIN_ID\",\"board_id\":\"BOARD_ID\"},\"context\":{}}"}'
# Follow a board (modern endpoint: /resource/ApiResource/update/ wrapping /v3/boards/{board_id}/follow/)
openweb pinterest exec followBoard '{"source_url":"/marthastewart/baking-and-dessert-recipes-and-ideas/","data":"{\"options\":{\"url\":\"/v3/boards/BOARD_ID/follow/\"},\"context\":{}}"}'
# Unfollow a board (same wrapped URL via /resource/ApiResource/delete/)
openweb pinterest exec unfollowBoard '{"source_url":"/marthastewart/baking-and-dessert-recipes-and-ideas/","data":"{\"options\":{\"url\":\"/v3/boards/BOARD_ID/follow/\"},\"context\":{}}"}'
# Get home feed
openweb pinterest exec getHomeFeed '{"source_url":"/","data":"{\"options\":{\"field_set_key\":\"hifi\",\"in_nux\":false,\"prependPartner\":false,\"page_size\":25},\"context\":{}}"}'
# Get notifications
openweb pinterest exec getNotifications '{"source_url":"/notifications/","data":"{\"options\":{\"field_set_key\":\"default\",\"page_size\":25},\"context\":{}}"}'Known Limitations
unsavePinrequires the saved-pin record id fromsavePin—PinResource/delete/takes the id returned insavePin'sresource_response.data.id(NOT the originalpin_id). When chaining manually, save the response fromsavePinand pass itsid+board.idtounsavePin. Inexample.json, use${prev.savePin.resource_response.data.id}and${prev.savePin.resource_response.data.board.id}(verify cross-op templating).- Board follow lives behind the "More actions" menu — Pinterest deprecated
/resource/BoardFollowingResource/. The modern follow/unfollow click is wrapped:POST /resource/ApiResource/{update,delete}/with bodydata={"options":{"url":"/v3/boards/{board_id}/follow/"},"context":{}}. The board's UI Follow button moved into the 3-dot menu — easy to miss when capturing HAR. - Write ops use form-encoded bodies —
POST /resource/{ResourceName}/{create,update,delete}/with form-encodedsource_url+datafields (wheredatais a JSON-string of{"options":{...},"context":{}}). Mirror this for any new write op unless HAR proves otherwise. source_urlshould match the page where the action would naturally happen — Pinterest sometimes rejects writes whensource_urlis just/. Use the board/pin URL the action targets (e.g./<username>/<board-slug>/).