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.
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:
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:
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:
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.
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.
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.
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.
const remote = await fetchCommentsFromServer()
pindrop.applyRemoteComments(remote)Subscribe to events
on(event, callback): () => void
Subscribe to store events. Returns an unsubscribe function.
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.
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.
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.
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