Skip to Content
Pindown.ai is in early alpha - features may change
API GuideQuickstart

Quickstart

Welcome to the Pindown.ai API v1 - transform your automation data into beautiful, real-time dashboards and shareable reports.

Base URL

https://api.pindown.ai/v1

Authentication

All API endpoints require authentication via API Keys. You can generate API keys in your dashboard settings.

Creating an API Key

  1. Navigate to Dashboard → API Keys
  2. Click “Generate New API Key”
  3. Give your key a descriptive name (e.g., “Production Automation”)
  4. Select the required scopes/permissions
  5. Copy your API key immediately - it will only be shown once!

Using Your API Key

Include your API key in the Authorization header:

Authorization: Bearer pk_live_your_api_key_here

Security Note: Keep your API keys secure and never commit them to version control. Use environment variables in production.

API Overview

The Pindown.ai API v1 provides RESTful endpoints for managing your automation dashboards:

ResourceDescriptionEndpoint
PinsCreate and update visual pin-cards (stats, charts, tables)/v1/pins
Pin BlocksAdd dynamic content blocks (markdown, conditionals, images)/v1/pins/:pinId/blocks
PinboardsOrganize pins into shareable dashboards/v1/pinboards
DatasetsStore and manage data sources/v1/datasets

API Features

âś… Real-time Updates - Push data and see instant changes
âś… 14+ Pin Card Types - Stats, charts, tables, alerts, and more
âś… Template Variables - Dynamic content with {{variable}} syntax
âś… RBAC & Sharing - Granular permissions (owner, editor, viewer)
âś… Batch Operations - Update multiple pins in one request
âś… Scoped API Keys - Fine-grained access control

Quick Start

1. Create a Stat Card Pin

Create a simple stat card showing your automation metrics:

curl -X POST https://api.pindown.ai/v1/pins \ -H "Authorization: Bearer pk_live_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "data_type": "pin-card", "pin_type": "stat-cards", "pin_layout": "1x1", "content": { "cards": [{ "title": "Total Sales", "value": "$12,450", "change": "+23.5%", "trend": "up" }] }, "metadata": { "title": "Sales Dashboard", "tags": ["sales", "analytics"], "is_public": false } }'

Response:

{ "success": true, "data": { "pin_id": "p-abc123def456", "shareable_url": "https://pindown.ai/share/pin/p-abc123def456", "created_at": "2024-11-01T15:30:00Z" } }

2. Update Pin Data (Real-time)

Update your pin’s data to see instant changes on your dashboard:

curl -X PUT https://api.pindown.ai/v1/pins/p-abc123def456 \ -H "Authorization: Bearer pk_live_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "content": { "cards": [{ "title": "Total Sales", "value": "$15,230", "change": "+45.2%", "trend": "up" }] } }'

3. Create a Pinboard Dashboard

Organize multiple pins into a visual dashboard:

curl -X POST https://api.pindown.ai/v1/pinboards \ -H "Authorization: Bearer pk_live_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "title": "Marketing Dashboard", "description": "Real-time marketing metrics", "tags": ["marketing", "kpis"], "is_public": false }'

4. Add Pin to Pinboard

curl -X POST https://api.pindown.ai/v1/pinboards/pb-xyz789/pins \ -H "Authorization: Bearer pk_live_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "pin_id": "p-abc123def456", "position": { "x": 0, "y": 0, "w": 2, "h": 1 } }'

Response Format

All API v1 responses include standard HTTP status codes and consistent JSON structures:

Success Response (2xx)

{ "success": true, "data": { "pin_id": "p-abc123", "shareable_url": "https://pindown.ai/share/pin/p-abc123" } }

Error Response (4xx, 5xx)

{ "error": { "code": "VALIDATION_FAILED", "message": "Pin card type is required", "details": { "field": "pin_type", "expected": "stat-cards | line-chart | flexible-table | ..." } } }

Common Error Codes

CodeStatusDescription
UNAUTHORIZED401Invalid or missing API key
FORBIDDEN403Insufficient scopes/permissions
NOT_FOUND404Resource doesn’t exist
VALIDATION_FAILED400Invalid request body
RATE_LIMIT_EXCEEDED429Too many requests

Rate Limits

Rate limits are enforced per API key based on your subscription tier:

TierRequests/HourRequests/MinuteBest For
Starter (Free)16/hour1/minTesting API
Professional1,000/hour60/minProduction apps
Team5,000/hour300/minTeam automation

Rate Limit Headers

Every API response includes rate limit information:

X-RateLimit-Limit-Hour: 3000 X-RateLimit-Remaining-Hour: 2847 X-RateLimit-Reset-Hour: 2024-11-01T16:00:00Z X-RateLimit-Limit-Minute: 50 X-RateLimit-Remaining-Minute: 42 X-RateLimit-Reset-Minute: 2024-11-01T15:31:00Z X-RateLimit-Token-Cost: 2

Rate Limit Exceeded Response

{ "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded. You've used 51 tokens out of 50 per minute.", "details": { "limit": 50, "used": 51, "window": "minute", "resetAt": "2024-11-01T15:31:00Z", "tier": "hobby", "upgrade_url": "https://pindown.ai/pricing" } } }

API Examples

Explore comprehensive examples organized from simplest to most complex:

  1. Pin with Blocks - Create a simple pin and add content blocks (markdown, code, images)
  2. Datasets & Template Variables - Store data separately and reference it with {{variables}}
  3. Pinboard with Pins - Create visual dashboards with pins
  4. Pinboards with Pin Cards - Create visual dashboards with stats, charts, and tables
  5. Sharing Pins - Share individual pins with collaborators
  6. Sharing Pinboards - Share entire dashboards with your team
  7. Custom Roles & Permissions - Advanced role-based access control

SDKs and Examples

JavaScript/Node.js

const PINDOWN_API_KEY = process.env.PINDOWN_API_KEY; const API_BASE = 'https://api.pindown.ai/v1'; // Create a stat card pin async function createStatCard(title, value, change) { const response = await fetch(`${API_BASE}/pins`, { method: 'POST', headers: { 'Authorization': `Bearer ${PINDOWN_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ data_type: 'pin-card', pin_type: 'stat-cards', pin_layout: '1x1', content: { cards: [{ title, value, change, trend: change.startsWith('+') ? 'up' : 'down' }] }, metadata: { title: `${title} Card`, is_public: false } }) }); if (!response.ok) { throw new Error(`API Error: ${response.statusText}`); } return response.json(); } // Update pin data (real-time) async function updatePin(pinId, newContent) { const response = await fetch(`${API_BASE}/pins/${pinId}`, { method: 'PUT', headers: { 'Authorization': `Bearer ${PINDOWN_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ content: newContent }) }); return response.json(); } // Example: Update sales every 5 seconds const salesPinId = 'p-abc123'; setInterval(async () => { const newSales = await fetchSalesData(); // Your data source await updatePin(salesPinId, { cards: [{ title: 'Total Sales', value: `$${newSales.toLocaleString()}`, change: `+${((newSales / lastSales - 1) * 100).toFixed(1)}%`, trend: 'up' }] }); }, 5000);

Python

import requests import os from typing import Dict, Any PINDOWN_API_KEY = os.environ.get('PINDOWN_API_KEY') API_BASE = 'https://api.pindown.ai/v1' def create_stat_card(title: str, value: str, change: str) -> Dict[str, Any]: """Create a stat card pin""" response = requests.post( f'{API_BASE}/pins', headers={ 'Authorization': f'Bearer {PINDOWN_API_KEY}', 'Content-Type': 'application/json' }, json={ 'data_type': 'pin-card', 'pin_type': 'stat-cards', 'pin_layout': '1x1', 'content': { 'cards': [{ 'title': title, 'value': value, 'change': change, 'trend': 'up' if change.startswith('+') else 'down' }] }, 'metadata': { 'title': f'{title} Card', 'is_public': False } } ) response.raise_for_status() return response.json() def update_pin(pin_id: str, new_content: Dict[str, Any]) -> Dict[str, Any]: """Update pin data in real-time""" response = requests.put( f'{API_BASE}/pins/{pin_id}', headers={ 'Authorization': f'Bearer {PINDOWN_API_KEY}', 'Content-Type': 'application/json' }, json={'content': new_content} ) response.raise_for_status() return response.json() # Example: Update metrics from your automation if __name__ == '__main__': # Create pin result = create_stat_card('API Calls', '12,450', '+23.5%') pin_id = result['data']['pin_id'] print(f"Created pin: {pin_id}") # Update pin with new data update_pin(pin_id, { 'cards': [{ 'title': 'API Calls', 'value': '15,230', 'change': '+45.2%', 'trend': 'up' }] }) print("Pin updated successfully!")

Next Steps

Explore the complete API documentation:

  • Pins API - Create and manage pin-cards (stats, charts, tables, alerts)
  • Pinboards API - Build visual dashboards and organize pins
  • Datasets API - Store and manage data sources (JSON, markdown)
  • Blocks API - Add dynamic content blocks to pins

API Scopes

When creating an API key, you can grant fine-grained permissions:

ScopeAccessDescription
datasets:readRead-onlyList and view datasets
datasets:writeRead + WriteCreate, update, delete datasets
pins:readRead-onlyList and view pins
pins:writeRead + WriteCreate, update, delete pins
pins:shareShareUpdate sharing settings
pinboards:readRead-onlyList and view pinboards
pinboards:writeRead + WriteCreate, update, delete pinboards
pinboards:inviteInviteManage collaborators
*Full AccessAll permissions (use with caution)

Best Practice: Use the minimum required scopes for each API key. For example, a read-only dashboard only needs pins:read and pinboards:read.

Support