@pindownai/client-js
v1.3.6
Published
Official TypeScript/JavaScript client for the Pindown v1 Pins API
Downloads
757
Maintainers
Readme
@pindownai/client-js
Official TypeScript/JavaScript client for the Pindown v1 Pins API.
Requires a Workspace plan API key (pk_…).
Features
- Typed
pin_type+pin_configfor all 37 pin shapes - Full CRUD + batch + share on
/v1/pins - ESM + CJS, zero runtime dependencies (native
fetch)
Install
npm install @pindownai/client-jsQuick start
import { PindownClient } from '@pindownai/client-js'
import type { MarkdownPinConfig } from '@pindownai/client-js'
const client = new PindownClient({
apiKey: process.env.PINDOWN_API_KEY!,
})
const created = await client.pins.create({
pin_type: 'markdown',
pin_config: { content: '# Hello\n\nCreated via API.' },
metadata: { title: 'My doc', tags: ['docs'] },
})
const pin = await client.pins.get(created.id)
const content = (pin.metadata?.pin_config as MarkdownPinConfig | undefined)?.content
await client.pins.update(created.id, {
pin_config: { content: '# Updated body' },
metadata: { title: 'My doc (updated)' },
})
await client.pins.delete(created.id)Client-side rate limiting
The client performs local preflight rate limiting for /v1/pins* to reduce avoidable 429s.
It mirrors backend buckets (read_standard, read_batch, write_core) with the same 60s caps.
const client = new PindownClient({
apiKey: process.env.PINDOWN_API_KEY!,
})Pin types (importable interfaces)
Each pin type has its own *PinConfig interface:
import type {
PinTypeId,
PinConfigByType,
MarkdownPinConfig,
TablePinConfig,
StatCardsPinConfig,
CreateTypedPinRequest,
} from '@pindownai/client-js'Product types: PRODUCT_PIN_TYPES (same as ALL_PIN_TYPES)
Helpers
Use either:
createPin(pinType, input)/updatePin(pinId, pinType, input)for every type, or- generated named helpers:
createMarkdown,updateMarkdown,createTable,updateTable,createTimeline, etc.
await client.pins.createMarkdown({
title: 'Notes',
content: '# Hello',
tags: ['api'],
})
await client.pins.createStatCards({
title: 'KPIs',
cards: [{ title: 'Revenue', value: '$1k', change: '+5%', trend: 'up' }],
})
await client.pins.createTable({
title: 'Data',
columns: [{ id: 'name', name: 'Name', type: 'text' }],
rows: [{ id: 'r1', cells: { name: 'Item' } }],
})
await client.pins.createEmbed({
title: 'Video',
url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
type: 'youtube',
})
// Generic helper for any pin_type
await client.pins.createPin('timeline', {
title: 'Roadmap timeline',
items: [{ id: 'm1', title: 'Milestone 1' }],
})
// Generated update helper per type
await client.pins.updateMarkdown('p-abc123', {
content: '# Updated via updateMarkdown helper',
})Pins API surface
| Method | Endpoint |
|--------|----------|
| pins.create | POST /v1/pins |
| pins.get | GET /v1/pins/:id |
| pins.list | GET /v1/pins |
| pins.update | PUT /v1/pins/:id |
| pins.delete | DELETE /v1/pins/:id |
| pins.share | POST /v1/pins/:id/share |
| pins.batchGet | POST /v1/pins/batch/get |
| pins.batchCreate | POST /v1/pins/batch |
| pins.batchUpdate | PATCH /v1/pins/batch |
| pins.batchDelete | DELETE /v1/pins/batch |
Rate limits (server-enforced)
The server applies rolling 60-second buckets on /v1/pins* (scaled by subscription tier). When exceeded:
- HTTP 429
- Error code
RATE_LIMITED - Thrown as
RateLimitErrorin the client
Approximate base caps (before tier scaling):
| Bucket | Methods | Base max / 60s |
|--------|---------|----------------|
| read_standard | GET /pins, GET /pins/:id | 120 |
| read_batch | POST /pins/batch/get | 60 |
| write_core | POST, PUT, DELETE, batch mutations, share | 90 |
Errors
import {
AuthenticationError,
ForbiddenError,
NotFoundError,
ValidationError,
RateLimitError,
} from '@pindownai/client-js'Docs
https://docs.pindown.ai
License
MIT
