commit cac7a950f24f820f38b473a8770a3a1546b9e3f6 Author: Zhongwei Li Date: Sun Nov 30 08:50:52 2025 +0800 Initial commit diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..2b84b7b --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,12 @@ +{ + "name": "pinterest-api", + "description": "Interacts with the Pinterest API.", + "version": "0.0.0-2025.11.28", + "author": { + "name": "Tim Green", + "email": "rawveg@gmail.com" + }, + "skills": [ + "./skills/pinterest-api" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e1aa76e --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# pinterest-api + +Interacts with the Pinterest API. diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..a23db64 --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,68 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:rawveg/skillsforge-marketplace:pinterest-api", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "08ac67333681cc912c3563cffaa1e16c611a2bbe", + "treeHash": "356bc3e6707f6766880e5556c5031a31fef0bd75b514bc15c57f08dc629acc44", + "generatedAt": "2025-11-28T10:27:53.411173Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "pinterest-api", + "description": "Interacts with the Pinterest API." + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "6ecdb332a8d66cf1a246afbcce62e8090910bdb6d6ee3c0932d96bd1efb55be2" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "d727b65767aed59859c6bce89f25ecb5b7c171bee7a2b23c582ffdca5ebce398" + }, + { + "path": "skills/pinterest-api/plugin.json", + "sha256": "6e5154f57b6537eab77b777f8db6d8ac7bb01dd5b8d4cb8ceb889cc491135f2c" + }, + { + "path": "skills/pinterest-api/SKILL.md", + "sha256": "4477d214a430ee35efd45aac137ce1e8f0a8065336804db0d46a360855154d46" + }, + { + "path": "skills/pinterest-api/references/llms.md", + "sha256": "73909ada35c9eaaa29e2986b9e5d8c059408ed0d269f19e6de8f3e3588896a74" + }, + { + "path": "skills/pinterest-api/references/api.md", + "sha256": "f968e661fb3a95be2635a04f2bad641a314c5af80db59affbe4ca7b6619b2735" + }, + { + "path": "skills/pinterest-api/references/llms-small.md", + "sha256": "d8c42e8a50df73d16abe6e4b541628f74d37b480075c3ce2f8bff0213e571d2b" + }, + { + "path": "skills/pinterest-api/references/index.md", + "sha256": "7cb1dcbe2c58d87b79d734e70f4137acdb57680993a8ecd5bb3052c904c65e41" + }, + { + "path": "skills/pinterest-api/references/llms-full.md", + "sha256": "2d40521fb241cbf0db1fd7308f18fab4eb7a8687ede156250f6d17371f1e395c" + } + ], + "dirSha256": "356bc3e6707f6766880e5556c5031a31fef0bd75b514bc15c57f08dc629acc44" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file diff --git a/skills/pinterest-api/SKILL.md b/skills/pinterest-api/SKILL.md new file mode 100644 index 0000000..d31ab39 --- /dev/null +++ b/skills/pinterest-api/SKILL.md @@ -0,0 +1,476 @@ +--- +name: pinterest-api +description: Pinterest API v5 Development - Authentication, Pins, Boards, Analytics +--- + +# Pinterest API Skill + +Comprehensive assistance with Pinterest API v5 development, including OAuth authentication, pin/board management, analytics, and API integration patterns. + +## When to Use This Skill + +This skill should be triggered when: +- Implementing Pinterest OAuth 2.0 authentication flows +- Creating, updating, or managing Pins and Boards via API +- Integrating Pinterest analytics and metrics into applications +- Building Pinterest API clients or SDKs +- Working with Pinterest user account data +- Debugging Pinterest API requests or responses +- Implementing Pinterest sharing features in web/mobile apps +- Setting up Pinterest business account integrations +- Working with Pinterest ad account APIs + +## Key Concepts + +### Pinterest API v5 Overview +- **Base URL**: `https://api.pinterest.com/v5/` +- **Authentication**: OAuth 2.0 with access tokens +- **Rate Limiting**: Token-based rate limits (varies by endpoint) +- **Response Format**: JSON +- **Required Headers**: `Authorization: Bearer {access_token}` + +### Core Resources +- **Pins**: Individual pieces of content (images, videos) saved to Pinterest +- **Boards**: Collections that organize Pins by theme or topic +- **Sections**: Subsections within Boards for additional organization +- **User Account**: Pinterest user profile and account information +- **Ad Accounts**: Business accounts for advertising functionality + +### Access Levels +- **Public Access**: Read-only access to public data +- **User Authorization**: Full access to user's Pins, Boards, and account +- **Business Access**: Additional analytics and ad account management (requires appropriate roles) + +## Quick Reference + +### OAuth 2.0 Authentication Flow + +#### Step 1: Generate Authorization URL +```javascript +// Redirect user to Pinterest authorization page +const authUrl = `https://www.pinterest.com/oauth/?client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&response_type=code&scope=boards:read,pins:read,user_accounts:read`; + +window.location.href = authUrl; +``` + +#### Step 2: Exchange Code for Access Token +```bash +# After user authorizes, exchange authorization code for access token +curl -X POST https://api.pinterest.com/v5/oauth/token \ + --header "Authorization: Basic {BASE64_ENCODED_CLIENT_CREDENTIALS}" \ + --header "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "grant_type=authorization_code" \ + --data-urlencode "code={AUTHORIZATION_CODE}" \ + --data-urlencode "redirect_uri={REDIRECT_URI}" +``` + +**Base64 Encoding Client Credentials:** +```bash +# Encode client_id:client_secret +echo -n "your_client_id:your_client_secret" | base64 +``` + +**Response:** +```json +{ + "access_token": "pina_ABC123...", + "token_type": "bearer", + "expires_in": 2592000, + "refresh_token": "DEF456...", + "scope": "boards:read,pins:read,user_accounts:read" +} +``` + +### Pin Management + +#### Create a Pin +```bash +curl -X POST https://api.pinterest.com/v5/pins \ + -H "Authorization: Bearer {ACCESS_TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{ + "link": "https://example.com/my-article", + "title": "My Amazing Pin Title", + "description": "Detailed description of the pin content", + "board_id": "123456789", + "media_source": { + "source_type": "image_url", + "url": "https://example.com/image.jpg" + } + }' +``` + +#### Get Pin Details +```bash +curl -X GET https://api.pinterest.com/v5/pins/{PIN_ID} \ + -H "Authorization: Bearer {ACCESS_TOKEN}" +``` + +**Response:** +```json +{ + "id": "987654321", + "created_at": "2025-01-15T10:30:00", + "link": "https://example.com/my-article", + "title": "My Amazing Pin Title", + "description": "Detailed description of the pin content", + "board_id": "123456789", + "media": { + "media_type": "image", + "images": { + "150x150": { "url": "...", "width": 150, "height": 150 }, + "400x300": { "url": "...", "width": 400, "height": 300 }, + "originals": { "url": "...", "width": 1200, "height": 800 } + } + } +} +``` + +#### Update a Pin +```bash +curl -X PATCH https://api.pinterest.com/v5/pins/{PIN_ID} \ + -H "Authorization: Bearer {ACCESS_TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{ + "title": "Updated Pin Title", + "description": "Updated description", + "link": "https://example.com/updated-link" + }' +``` + +#### Delete a Pin +```bash +curl -X DELETE https://api.pinterest.com/v5/pins/{PIN_ID} \ + -H "Authorization: Bearer {ACCESS_TOKEN}" +``` + +### Board Management + +#### Create a Board +```bash +curl -X POST https://api.pinterest.com/v5/boards \ + -H "Authorization: Bearer {ACCESS_TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "My New Board", + "description": "A collection of my favorite ideas", + "privacy": "PUBLIC" + }' +``` + +**Privacy Options:** `PUBLIC`, `PROTECTED`, `SECRET` + +#### List User's Boards +```bash +curl -X GET https://api.pinterest.com/v5/boards \ + -H "Authorization: Bearer {ACCESS_TOKEN}" +``` + +#### Get Board Pins +```bash +curl -X GET https://api.pinterest.com/v5/boards/{BOARD_ID}/pins \ + -H "Authorization: Bearer {ACCESS_TOKEN}" +``` + +### User Account + +#### Get Current User Account +```bash +curl -X GET https://api.pinterest.com/v5/user_account \ + -H "Authorization: Bearer {ACCESS_TOKEN}" +``` + +**Response:** +```json +{ + "account_type": "BUSINESS", + "id": "123456789", + "username": "myusername", + "website_url": "https://example.com", + "profile_image": "https://i.pinimg.com/...", + "follower_count": 1500, + "following_count": 320, + "board_count": 25, + "pin_count": 450 +} +``` + +### Analytics + +#### Get Pin Analytics +```bash +curl -X GET "https://api.pinterest.com/v5/pins/{PIN_ID}/analytics?start_date=2025-01-01&end_date=2025-01-31&metric_types=IMPRESSION,SAVE,PIN_CLICK" \ + -H "Authorization: Bearer {ACCESS_TOKEN}" +``` + +**Available Metrics:** +- `IMPRESSION` - Number of times pin was shown +- `SAVE` - Number of times pin was saved +- `PIN_CLICK` - Number of clicks to pin destination +- `OUTBOUND_CLICK` - Clicks to external website +- `VIDEO_START` - Video plays started + +**Response:** +```json +{ + "all": { + "daily_metrics": [ + { + "date": "2025-01-01", + "data_status": "READY", + "metrics": { + "IMPRESSION": 1250, + "SAVE": 45, + "PIN_CLICK": 89 + } + } + ] + } +} +``` + +### Error Handling + +#### Common Error Response +```json +{ + "code": 3, + "message": "Requested pin not found" +} +``` + +**Common Error Codes:** +- `1` - Invalid request parameters +- `2` - Rate limit exceeded +- `3` - Resource not found +- `4` - Insufficient permissions +- `8` - Invalid access token + +#### Python Error Handling Example +```python +import requests + +def create_pin(access_token, board_id, title, image_url): + url = "https://api.pinterest.com/v5/pins" + headers = { + "Authorization": f"Bearer {access_token}", + "Content-Type": "application/json" + } + data = { + "board_id": board_id, + "title": title, + "media_source": { + "source_type": "image_url", + "url": image_url + } + } + + try: + response = requests.post(url, headers=headers, json=data) + response.raise_for_status() + return response.json() + except requests.exceptions.HTTPError as e: + error_data = e.response.json() + print(f"Error {error_data.get('code')}: {error_data.get('message')}") + return None + except requests.exceptions.RequestException as e: + print(f"Request failed: {str(e)}") + return None +``` + +### JavaScript/Node.js Integration + +```javascript +// Pinterest API Client Example +class PinterestClient { + constructor(accessToken) { + this.accessToken = accessToken; + this.baseUrl = 'https://api.pinterest.com/v5'; + } + + async request(endpoint, options = {}) { + const url = `${this.baseUrl}${endpoint}`; + const headers = { + 'Authorization': `Bearer ${this.accessToken}`, + 'Content-Type': 'application/json', + ...options.headers + }; + + const response = await fetch(url, { + ...options, + headers + }); + + if (!response.ok) { + const error = await response.json(); + throw new Error(`Pinterest API Error: ${error.message}`); + } + + return response.json(); + } + + async createPin(boardId, title, imageUrl, description = '', link = '') { + return this.request('/pins', { + method: 'POST', + body: JSON.stringify({ + board_id: boardId, + title: title, + description: description, + link: link, + media_source: { + source_type: 'image_url', + url: imageUrl + } + }) + }); + } + + async getUserBoards() { + return this.request('/boards'); + } + + async getPinAnalytics(pinId, startDate, endDate) { + const params = new URLSearchParams({ + start_date: startDate, + end_date: endDate, + metric_types: 'IMPRESSION,SAVE,PIN_CLICK' + }); + return this.request(`/pins/${pinId}/analytics?${params}`); + } +} + +// Usage +const client = new PinterestClient('your_access_token'); +const pin = await client.createPin('board_id', 'Pin Title', 'https://example.com/image.jpg'); +``` + +## Reference Files + +This skill includes comprehensive documentation in `references/`: + +- **api.md** - Complete Pinterest API v5 endpoint reference extracted from official documentation + +Use `view` to read reference files when detailed information about specific endpoints is needed. + +## Working with This Skill + +### For Beginners +1. Start by understanding OAuth 2.0 authentication flow (see Quick Reference above) +2. Get your API credentials from Pinterest Developer Portal +3. Test authentication with curl commands before implementing in your application +4. Use the provided Python/JavaScript examples as starting templates + +### For API Integration +1. Implement OAuth flow to obtain access tokens +2. Store refresh tokens securely for long-term access +3. Use the Pin/Board management examples for CRUD operations +4. Implement proper error handling for rate limits and API errors + +### For Analytics & Business Features +1. Ensure you have appropriate business account access +2. Use analytics endpoints to track Pin performance +3. Aggregate metrics across date ranges for reporting +4. Implement caching to avoid unnecessary API calls + +### Best Practices +- **Token Security**: Never expose access tokens in client-side code or version control +- **Rate Limiting**: Implement exponential backoff for rate limit errors +- **Pagination**: Use cursor-based pagination for large result sets +- **Webhooks**: Consider using webhooks for real-time updates instead of polling +- **Scopes**: Request only the minimum OAuth scopes needed for your application + +## Common Patterns + +### Pagination +```bash +# Initial request +curl -X GET "https://api.pinterest.com/v5/boards/{BOARD_ID}/pins?page_size=25" \ + -H "Authorization: Bearer {ACCESS_TOKEN}" + +# Follow-up with bookmark from response +curl -X GET "https://api.pinterest.com/v5/boards/{BOARD_ID}/pins?page_size=25&bookmark={BOOKMARK}" \ + -H "Authorization: Bearer {ACCESS_TOKEN}" +``` + +### Bulk Operations +```python +# Create multiple pins efficiently +def bulk_create_pins(access_token, board_id, pin_data_list): + results = [] + for pin_data in pin_data_list: + result = create_pin( + access_token, + board_id, + pin_data['title'], + pin_data['image_url'] + ) + results.append(result) + time.sleep(0.5) # Respect rate limits + return results +``` + +## Resources + +### Official Documentation +- Pinterest API v5 Docs: https://developers.pinterest.com/docs/api/v5/ +- API Quickstart: https://github.com/pinterest/api-quickstart +- OAuth Documentation: https://developers.pinterest.com/docs/getting-started/authentication/ + +### OAuth Scopes +Common scopes you'll need: +- `boards:read` - Read board data +- `boards:write` - Create/update boards +- `pins:read` - Read pin data +- `pins:write` - Create/update pins +- `user_accounts:read` - Read user account data +- `ads:read` - Read ad account analytics (business accounts) + +### Rate Limits +- Pinterest implements per-user rate limiting +- Typical limits: 1000 requests per hour per user +- Rate limit headers in response: + - `X-RateLimit-Limit` + - `X-RateLimit-Remaining` + - `X-RateLimit-Reset` + +## Notes + +- Pinterest API v5 is the current version (as of 2025) +- All endpoints require authentication via OAuth 2.0 +- Access tokens expire after 30 days +- Use refresh tokens to obtain new access tokens +- Business accounts have access to additional analytics features +- Video pins require special handling compared to image pins +- Some features require app review by Pinterest + +## Troubleshooting + +### "Invalid access token" +- Verify token hasn't expired (30-day lifetime) +- Use refresh token to obtain new access token +- Check Authorization header format: `Bearer {token}` + +### "Insufficient permissions" +- Verify OAuth scopes include required permissions +- Business features require verified business account +- Some operations require board/pin ownership + +### "Rate limit exceeded" +- Implement exponential backoff +- Cache responses when possible +- Use webhooks instead of polling +- Check `X-RateLimit-Reset` header for retry time + +### "Media upload failed" +- Verify image URL is publicly accessible +- Check image meets size requirements (max 10MB) +- Ensure image format is supported (JPG, PNG, GIF) +- For video, use video-specific endpoints + +## Updating + +This skill was generated from Pinterest's official API documentation. To get the latest API changes: +1. Visit https://developers.pinterest.com/docs/api/v5/ +2. Check changelog for API updates +3. Review deprecation notices +4. Update OAuth scopes if new features added diff --git a/skills/pinterest-api/plugin.json b/skills/pinterest-api/plugin.json new file mode 100644 index 0000000..40605cd --- /dev/null +++ b/skills/pinterest-api/plugin.json @@ -0,0 +1,15 @@ +{ + "name": "pinterest-api", + "description": "Interacts with the Pinterest API.", + "version": "1.0.0", + "author": { + "name": "Tim Green", + "email": "rawveg@gmail.com" + }, + "homepage": "https://github.com/rawveg/claude-skills-marketplace", + "repository": "https://github.com/rawveg/claude-skills-marketplace", + "license": "MIT", + "keywords": ["pinterest-api", "pinterest", "social media", "social media marketing", "Claude Code"], + "category": "productivity", + "strict": false +} diff --git a/skills/pinterest-api/references/api.md b/skills/pinterest-api/references/api.md new file mode 100644 index 0000000..92e2549 --- /dev/null +++ b/skills/pinterest-api/references/api.md @@ -0,0 +1,134 @@ +# Pinterest-Api - Api + +**Pages:** 1 + +--- + +## Pinterest Developers
+ +--- diff --git a/skills/pinterest-api/references/index.md b/skills/pinterest-api/references/index.md new file mode 100644 index 0000000..3a83f34 --- /dev/null +++ b/skills/pinterest-api/references/index.md @@ -0,0 +1,7 @@ +# Pinterest-Api Documentation Index + +## Categories + +### Api +**File:** `api.md` +**Pages:** 1 diff --git a/skills/pinterest-api/references/llms-full.md b/skills/pinterest-api/references/llms-full.md new file mode 100644 index 0000000..dceaaa5 --- /dev/null +++ b/skills/pinterest-api/references/llms-full.md @@ -0,0 +1,123 @@ +Pinterest Developers
\ No newline at end of file diff --git a/skills/pinterest-api/references/llms-small.md b/skills/pinterest-api/references/llms-small.md new file mode 100644 index 0000000..f02e43f --- /dev/null +++ b/skills/pinterest-api/references/llms-small.md @@ -0,0 +1,123 @@ +Pinterest Developers
\ No newline at end of file diff --git a/skills/pinterest-api/references/llms.md b/skills/pinterest-api/references/llms.md new file mode 100644 index 0000000..1579b28 --- /dev/null +++ b/skills/pinterest-api/references/llms.md @@ -0,0 +1,123 @@ +Pinterest Developers
\ No newline at end of file