Skip to Content
Client SDKPins API

Pins API

The Pins API provides methods to create, read, update, delete, batch, and share pins with 43 typed pin_type + pin_config shapes.

Getting Started

import { PindownClient } from '@pindownai/client-js' const client = new PindownClient({ apiKey: process.env.PINDOWN_API_KEY }) // Access pins API const pins = client.pins

Create Pin

Create a new pin with unified structure:

const pin = await client.pins.create({ pin_type: 'stat-cards', pin_config: { cards: [{ title: 'Total Sales', value: '$125,430', change: '+18.2%', trend: 'up' }] }, pin_layout: '1x1', metadata: { title: 'Sales Dashboard', tags: ['sales', 'kpi'] } }) console.log(`Pin created: ${pin.id}`)

Get Pin

Retrieve a specific pin by ID:

const pin = await client.pins.get('p-abc123def456') console.log(`Title: ${pin.metadata.title}`) console.log(`Type: ${pin.metadata.pin_type}`) console.log(`Config:`, pin.metadata.pin_config)

List Pins

Get all your pins with pagination:

const page1 = await client.pins.list({ limit: 50, offset: 0 }) console.log(`Total pins: ${page1.total}`) page1.items.forEach(pin => { console.log(`- ${pin.title ?? pin.metadata?.title}`) })

Update Pin

Update pin content or metadata:

// Update pin config await client.pins.update('p-abc123', { pin_config: { cards: [{ title: 'Live Users', value: '1,234', change: '+5.2%', trend: 'up' }] } }) // Update metadata await client.pins.update('p-abc123', { metadata: { title: 'Updated Dashboard', tags: ['sales', 'updated', 'q4'] } })

Delete Pin

Delete a pin permanently:

try { await client.pins.delete('p-abc123') console.log('Pin deleted successfully') } catch (error) { console.error('Failed to delete pin:', error.message) }

Share Pin

Update sharing permissions:

// Make pin public with comments await client.pins.share('p-abc123', { is_public: true, allow_comments: true, require_sign_in: false, allow_edit: false }) // Public URL: https://pindown.ai/share/pin/p-abc123 // Make private again await client.pins.share('p-abc123', { is_public: false })

Pin Types

The Pins API supports various pin types with unified structure:

Stat Cards

{ pin_type: 'stat-cards', pin_config: { cards: [{ title: 'Revenue', value: '$125k', change: '+18%', trend: 'up' }] }, pin_layout: '1x1' }

Table (typed columns)

{ pin_type: 'table', pin_config: { columns: [ { id: 'product', name: 'Product', type: 'text' }, { id: 'sales', name: 'Sales', type: 'number' }, ], rows: [ { id: 'r1', cells: { product: 'Widget A', sales: 1250 } }, { id: 'r2', cells: { product: 'Widget B', sales: 890 } }, ], }, pin_layout: '2x2', }

Charts

{ pin_type: 'charts', pin_config: { chartType: 'line', title: 'API Calls', xAxis: 'name', yAxis: 'value', dataKeys: ['value'], data: [ { id: '1', name: 'Mon', value: 1200 }, { id: '2', name: 'Tue', value: 1450 }, { id: '3', name: 'Wed', value: 1680 }, ], }, pin_layout: '2x2', }

Markdown Pin

{ pin_type: 'markdown', pin_config: { content: '# Weekly Report\n\n## Key Highlights\n\n- Revenue up 18%' }, pin_layout: '2x2', metadata: { title: 'Weekly Report', tags: ['reports'] } }

Available Pin Types

  • markdown — Rich text (Yjs-backed on the server)
  • stat-cards — KPI cards with trends
  • charts — Line, bar, pie, area, radar, etc.
  • table — Tabular data
  • image, gallery, video, audio — Media
  • embed — YouTube, Vimeo, etc.
  • pdf-viewer, excel-viewer, csv-viewer, file-upload — File viewers & uploads
  • timeline, steps, roadmap, calendar, plan — Time and planning
  • mermaid, trace — Diagrams and execution traces
  • json-viewer, json-list, links, qr-code, social-handles — Structured data & links
  • user-story, chat, intro, text-media, business-card, notes, mastra
  • kanban-board, checklist, comparison, realtime-canvas

Full reference: Pin Types & Schemas · REST: Create a Pin


Error Handling

import { NotFoundError, ValidationError, RateLimitError } from '@pindownai/client-js' try { const pin = await client.pins.get('p-invalid') } catch (error) { if (error instanceof NotFoundError) { console.log('Pin not found') } else if (error instanceof ValidationError) { console.log('Invalid pin data:', error.message) } else if (error instanceof RateLimitError) { console.log('Rate limited (429 RATE_LIMITED)') } }

Next Steps