Pindrop.js API Reference

All methods are available on the object returned by Pindrop.init().

Discover elements

getCommentableElements(): CommentableElement[]

Returns semantic, visible elements on the page with their selectors, labels, and bounding rects. Useful for agents and automated workflows that need to orient themselves before placing comments.

typescript
const elements = pindrop.getCommentableElements()
// [{ selector: '#hero', label: 'Ship feedback faster.', rect: { x, y, width, height } }, ...]

Programmatic pin

addComment(options): Comment | null

Programmatically add a comment without clicking. Returns the created Comment (including its id for follow-up actions), or null if the target element is not found.

Target by CSS selector:

typescript
const comment = pindrop.addComment({
  selector: '#submit-btn',
  text: 'Button label is too vague',
  author: 'QA Bot',
})

Target by viewport coordinates (0–1 fractions). Useful when reasoning from a screenshot:

typescript
const comment = pindrop.addComment({
  x: 0.7,
  y: 0.85,
  text: 'This chart looks misaligned',
  author: 'Agent',
})

Attach agent metadata to distinguish automated comments from human ones:

typescript
const comment = pindrop.addComment({
  selector: '#chart',
  text: 'Y-axis scale looks inconsistent',
  author: 'Claude',
  meta: { source: 'agent', model: 'claude-sonnet-4-6' },
})

Programmatic reply

addReply(options): Reply | null

Append a reply to an existing comment. Returns the created Reply, or null if the parent comment is not found.

typescript
const reply = pindrop.addReply({
  commentId: comment.id,
  text: 'Specifically the bar at index 3.',
  author: 'Claude',
})

Mark as resolved

resolveComment(id: string, author?: string): Comment | null

Marks a comment as resolved. Returns the updated Comment with resolved: true, resolvedBy, and resolvedAt set, or null if not found.

typescript
const resolved = pindrop.resolveComment(comment.id, 'Alice')

Reopen a comment

reopenComment(id: string): void

Reopens a previously resolved comment.

Delete a comment

deleteComment(id: string): void

Permanently removes a comment from the store.

Read comment store

getComments(): Comment[]

Returns the current array of all comments in the store.

typescript
const open = pindrop.getComments().filter(c => !c.resolved)

Apply remote comments

applyRemoteComments(incoming: Comment[]): void

Merges an array of comments fetched from a remote source into the local store and refreshes the UI. New comments are marked unread. Existing comments preserve local read state unless their content or replies have changed. Use this when polling a backend for updates instead of reloading the page.

typescript
const remote = await fetchCommentsFromServer()
pindrop.applyRemoteComments(remote)

Subscribe to events

on(event, callback): () => void

Subscribe to store events. Returns an unsubscribe function.

typescript
pindrop.on('comment:add', (comment) => console.log(comment))
pindrop.on('comment:resolve', (comment) => {})
pindrop.on('reply:add', ({ comment, reply }) => {})

Available events: comment:add, comment:delete, comment:resolve, comment:reopen, comment:read, comment:unread, reply:add, anchor:lost, mode:change, import:complete, export:complete.

Serialize comments

export(): string

Returns all comments as a JSON string. Pass to a file download or send to a server.

typescript
const json = pindrop.export()

Restore comments

import(json: string): ImportResult

Merges a JSON string (from export()) into the current comment store. Returns counts of what changed.

typescript
const result = pindrop.import(json)
// result: { added: number, merged: number, unanchored: number }

Update current user

setUser(user: { name: string }): void

Updates the current user name used for new comments and replies.

typescript
pindrop.setUser({ name: 'Alice' })

Show or hide overlay

toggle(): void

Shows or hides the entire Pindrop UI overlay.

Re-evaluate scopes

refresh(): void

Re-evaluates scope visibility. Call after a route change or modal open/close when using getScope/isScopeActive.

Remove from page

destroy(): void

Removes the Pindrop overlay from the page and cleans up all event listeners.

Last updated March 29, 2026