JavaScript API

Quick Start

import PlaidClient from 'plaid-client';

const client = await PlaidClient.login('http://localhost:8080', 'user@example.com', 'password');

// Create a project
const project = await client.projects.create('My Project');

// Create a document
const doc = await client.documents.create(project.id, 'Document 1');

// List a project's documents (paginated; the client returns the full list)
const docs = await client.projects.listDocuments(project.id);

// Batch multiple operations atomically
const results = await client.batched(async (b) => {
  b.tokens.create(tokenLayerId, textId, 0, 5);
  b.tokens.create(tokenLayerId, textId, 6, 11);
});

Client

constructor(baseUrl, token, [options], [options.timeout], [options.batchTimeout])

Create a new PlaidClient instance

ParameterTypeDescription
baseUrl string The base URL for the API
token string The authentication token
options optional object Client options
options.timeout optional number =30000] - Per-request timeout in ms (0 or null disables it)
options.batchTimeout optional number =180000] - Timeout for batch submissions in ms (0 or null disables it)
health(baseUrl, [options]) static

Liveness, version and database size, with NO authentication and no client instance — for a launcher or status page checking whether a server is up before anyone logs in.

ParameterTypeDescription
baseUrl string The API base URL
options optional object
info(baseUrl, [options]) static

The limits this server enforces, with NO authentication and no client instance. See the instance method for the shape.

ParameterTypeDescription
baseUrl string The API base URL
options optional object
inviteUrl(appUrl, code) static

Build the link to hand someone for an invite code. The server never sees an app URL, so the app that minted the invite is the one that names it. Both SPAs use HashRouter, so the code rides in the fragment — which also keeps it out of server access logs.

ParameterTypeDescription
appUrl string Where the SPA lives, e.g. "https://plaid.example.org/igt/"
code string The code returned by invites.create()
lookupInvite(baseUrl, code, [options]) static

Describe an invite code, with NO authentication — this is what a signup page calls before the redeemer has an account. Returns the kind of link ("signup" or "password-reset"), its status ("active", "used", "expired", "revoked"), and the project it grants access to, if any.

Throws a 404-shaped error if the code is unknown. A known-but-dead code resolves normally with a non-"active" status, so the page can say why.

ParameterTypeDescription
baseUrl string The API base URL
code string The invite code
options optional object
redeemInvite(baseUrl, code, credentials, [credentials.email], [credentials.displayName], credentials.password, [options]) static

Redeem an invite code, with NO authentication.

For a signup invite, pass email and password to create the account (and optionally displayName); the invite's grants are applied in the same transaction. For a password reset link, pass password only. Resolves to a logged-in client, exactly like login() — the redeemer just chose these credentials, so there is no reason to send them to a login form to retype them.

ParameterTypeDescription
baseUrl string The API base URL
code string The invite code
credentials object
credentials.email optional string The new account's email address, which becomes its id and login (signup only)
credentials.displayName optional string How the new user is shown in the UI; defaults to the local part of the email (signup only)
credentials.password string Desired password (min 8 characters)
options optional object
login(baseUrl, userId, password, [options]) static

Authenticate and return a new client instance with token. This is the single auth entry point — there is no client.login resource.

ParameterTypeDescription
baseUrl string The base URL for the API
userId string User ID for authentication
password string Password for authentication
options optional object Client options forwarded to the constructor (e.g. { timeout })
enterStrictMode(documentId)

Enter strict mode for a specific document, requiring document version headers so that conflicting concurrent writes are rejected.

ParameterTypeDescription
documentId string The ID of the document to track versions for
exitStrictMode()

Exit strict mode and stop tracking document versions for writes.

batch()

Open a batch: a view of this client with the same bundles, on which every write of project data queues instead of going out. submit() sends the queued operations as ONE atomic request (larger than the server's cap, as consecutive requests with the results concatenated in queue order, each atomic on its own, so a failure in a later one leaves the earlier ones committed, and the error it throws carries committed, the count saved, and committedResults, their results) and resolves to one result per operation; abort() drops them. A call made on the client itself is never touched by an open batch, and a read or an out-of-band signal made on the batch goes over the wire now (see the note at the top of http.js).

const b = client.batch();
b.tokens.bulkCreate(sentenceOps);
b.tokens.bulkCreate(wordOps);
const [sentRes, wordRes] = await b.submit();

Server-side a batch runs sequentially in one transaction: a child op sees parents created earlier in the same batch, and any op's failure rolls the whole batch back. A batch is not nestable. Prefer batched(), which submits or aborts for you.

batched(fn)

Run fn with a batch, then submit all queued ops as submit() does (ONE atomic request up to MAX_BATCH_OPS operations, consecutive requests past it), or abort the batch if fn throws. fn receives the batch and makes its writes on it; it must NOT call submit() itself. Resolves to the batch results array ([] if fn queued nothing).

const [sentRes, wordRes] = await client.batched(async (b) => {
  b.tokens.bulkCreate(sentenceOps);
  b.tokens.bulkCreate(wordOps);
});

A write made on client inside fn is not part of the batch: it goes over the wire at once, as it would anywhere else. See batch().

ParameterTypeDescription
fn (batch: PlaidClient) => (void | Promise)
beginOperation(message, [opts])

Begin a LOGICAL OPERATION: a user-meaningful action ("Merge morphemes", "Re-transcribe") implemented as many low-level writes, possibly across several batches and even a service round-trip. Until endOperation(), every write is stamped with a client-minted ?group-id= (and the message) so the audit log shows the whole run as ONE expandable entry labeled message, with each write's own description underneath.

Grouping is orthogonal to batches: a batch is a transaction boundary, an operation is an intent boundary. An operation is NOT atomic — if write 3 of 5 fails, writes 1–2 stay committed (and logged under the group). Use a batch inside the operation for any step that must be all-or-nothing.

Nesting flattens: a beginOperation while one is open is a no-op that joins the outer operation (the outer label wins), and the matching endOperation is likewise a no-op. The label is recorded on the FIRST write, so an operation that is never ended (crash, closed tab) is still labeled in the log.

"Every write" is the writes of project data. Reads never join, and neither do the out-of-band signals shaped like a write (a document lock taken or renewed, a stopped service request, a service reporting itself, an admin control), and neither does a broadcast message (messages.sendMessage): none of them is audited, so there would be nothing under the label.

kind says what kind of operation this is, for a program reading the log: one of assistant-plan, service-run, import, bulk-edit, guess-adoption, repair or review (the server refuses any other). ref is a short string naming what the operation came from, in the shape its kind documents (the core manual, "Kinds of operation"). Both are recorded from the first write like the label, and a nested operation keeps the outer one's.

keys (from keySeed()) makes a run of the operation send the same requests as an earlier run with the same keys: the nth keyed request that joins it takes the Idempotency-Key <seed>.<n> and the document-version its first run claimed, so a request that landed is answered from its first send and writes nothing again. The count starts at 0 at each outermost begin. A nested operation joins the outer one's keys, unless it brings its own: then it numbers from 0 under its own seed until its matching end, and the outer numbering resumes after it.

ParameterTypeDescription
message string Human label for the operation.
opts optional object Optional { id, kind, ref, keys }. id adopts an existing group id instead of minting one (a service joining the requester's operation; requestService propagates an open operation to the service automatically). kind, ref and keys are described above.
endOperation([message])

End the current logical operation. With no argument this is purely local (no request). Pass a refined message to relabel the group now that the outcome is known (e.g. endOperation('Merged 3 morphemes')) — that sends one PATCH, skipped if the operation never wrote anything. A refine from a nested (flattened) endOperation is ignored; the outer label wins.

ParameterTypeDescription
message optional string Optional refined label.
withOperation(message, fn, [opts])

Run fn as one logical operation (see beginOperation), ending it when fn settles — including on throw. fn receives a setMessage(msg) callback to refine the label once the outcome is known.

await client.withOperation('Merge morphemes', async (setMessage) => {
  await client.batched(async (b) => { ... });
  setMessage(`Merged ${n} morphemes`);
});

The kind and reference (see beginOperation) come after fn:

await client.withOperation('Import ELAN corpus', run, { kind: 'import', ref: 'format:elan' });
ParameterTypeDescription
message string Human label for the operation.
fn function The work to run; receives setMessage(msg) to refine the label once the outcome is known.
opts optional object Optional { kind, ref, id, keys }, as for beginOperation.

Admin

admin.server()

Everything about the server in one read: version and JVM uptime, database size and per-table row counts, media directory usage, backup configuration and the backups on disk, and the settings an operator gets asked to confirm. Carries no secrets. Runs a count per table and walks the media directory, so open it, do not poll it. Admin only.

admin.backup()

Take a database backup right now, outside the nightly schedule. Resolves to the backup block with ok reporting whether the snapshot succeeded. Uses VACUUM INTO, which only reads, so it is safe while people are working. Admin only.

admin.locks()

Documents currently held by an editing lock, with who holds each and when it expires on its own. Admin only.

admin.releaseLock(documentId)

Drop the lock on a document whoever holds it. Idempotent. For a client that went away without releasing one. Admin only.

ParameterTypeDescription
documentId string The document ID
admin.rateLimits()

Live login and invite rate-limit buckets: the address, the account where there is one, failures inside the window, the limit, and whether it is currently blocking. Admin only.

admin.clearRateLimits([opts], [opts.ip], [opts.userId])

Forget recorded rate-limit failures. With ip, clears that address, narrowed to one account with userId. With neither, clears every bucket. Only ever unblocks. Admin only.

ParameterTypeDescription
opts optional object
opts.ip optional string Clear only this address
opts.userId optional string Narrow to one account on that address
admin.logs([opts], [opts.limit], [opts.q], [opts.level], [opts.status], [opts.user], [opts.method])

What the server has logged, structured and filtered, from an in-memory buffer kept whether or not a log file is configured. requests is one entry per HTTP request (method, path, status, duration, and who made it), events is everything else, with a stack trace where there was one. They are buffered separately so a burst of requests cannot evict an error. Both come newest first, matched counts what passed the filters, and request stats describe the filtered set. Covers Plaid's own log stream since the last restart: for library messages and older history, see logFile. Admin only.

ParameterTypeDescription
opts optional object
opts.limit optional number Max entries per kind (default 200, max 2000)
opts.q optional string Substring of any field, case-insensitive
opts.level optional string Minimum level for events, e.g. "warn"
opts.status optional string "2xx".."5xx", an exact code, or "failures"
opts.user optional string Only requests made by this account
opts.method optional string Only requests with this HTTP method
admin.logFile([opts], [opts.lines])

The tail of the configured log file, as text lines. The only place third-party library messages and anything from before the last restart can be read. Resolves with an error string instead of lines when no log file is configured or it does not exist yet. Admin only.

ParameterTypeDescription
opts optional object
opts.lines optional number How many lines (default 200, max 2000)
admin.userData([opts], [opts.prefix], [opts.pattern], [opts.includeValues])

Private user-data entries across every account, each carrying its userId. /users/:userId/data has always been owner-or-admin; this is the same reach across accounts at once. Transparently follows pagination cursors and returns the full flat array. Admin only.

Narrow with prefix (the literal head of a key) and/or pattern, a GLOB over the whole key (* any run, ? one character) — the way to ask for a key convention identified by a segment in the middle, e.g. igt:assistant:*:meta:*. Values come only with includeValues, and are recased like any other body (see userData.put).

ParameterTypeDescription
opts optional object
opts.prefix optional string Only keys starting with this
opts.pattern optional string Only keys matching this GLOB
opts.includeValues optional boolean Also return each entry's value
admin.userDataPage([opts], [opts.prefix], [opts.pattern], [opts.includeValues], [opts.limit], [opts.cursor])

One page of private user-data entries across accounts, ordered by (user, key). Admin only.

ParameterTypeDescription
opts optional object
opts.prefix optional string Only keys starting with this
opts.pattern optional string Only keys matching this GLOB
opts.includeValues optional boolean Also return each entry's value
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page

Api Tokens

apiTokens.list(userId)

List a user's named API tokens. Never includes the signed token string itself — that is only returned once, by create(). Transparently follows pagination cursors and returns the full flat array.

ParameterTypeDescription
userId string The user ID who owns the tokens
apiTokens.listPage(userId, [opts], [opts.limit], [opts.cursor])

Fetch a single page of a user's named API tokens.

ParameterTypeDescription
userId string The user ID who owns the tokens
opts optional object
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
apiTokens.iterPages(userId, [opts], [opts.pageSize])

Async-iterate a user's named API tokens page by page; yields each page's entries array.

ParameterTypeDescription
userId string The user ID who owns the tokens
opts optional object
opts.pageSize optional number Per-request page size
apiTokens.create(userId, name)

Mint a named API token for a user. The returned token is the signed credential and is shown ONLY here — store it immediately. API tokens do not expire and survive password changes / logout; revoke to kill.

ParameterTypeDescription
userId string The user ID who will own the token
name string A human label, e.g. "Stanza parser"
apiTokens.revoke(userId, tokenId)

Revoke a named API token (soft-revoke; idempotent).

ParameterTypeDescription
userId string The user ID who owns the token
tokenId string The token ID to revoke

Audit

audit.list([opts], [opts.startTime], [opts.endTime], [opts.opTypes], [opts.kinds])

The audit log across every project, oldest first. Same fold, window and op-type filter as the per-project read, with the entity scope dropped. Admin only. Transparently follows pagination cursors and returns the full flat array.

ParameterTypeDescription
opts optional object
opts.startTime optional string Only operations at or after this instant
opts.endTime optional string Only operations at or before this instant
opts.opTypes optional string[]|string Only these op types (e.g. ['span-layer/create']). An entry appears when one of its operations matches, carrying only the ones that did.
opts.kinds optional string[]|string Only the entries of operations of these kinds (e.g. ['review']), each whole
audit.listPage([opts], [opts.order], [opts.limit], [opts.cursor])

Fetch a single page of the instance-wide audit log. Admin only.

ParameterTypeDescription
opts optional object
opts.order optional "asc"|"desc" "desc" pages newest-first, which is what a feed wants. A cursor belongs to the direction that made it.
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
audit.iterPages()

Async-iterate the instance-wide audit log page by page. Admin only.

Comments

comments.create(entityType, entityId, body, [opts], [opts.anchorLabel])

Post a comment on an entity. Requires write access to the entity's project, or to the vocabulary for a vocab-item; the author is the authenticated caller. Comments are not audited and do not bump the document version.

A comment outlives its anchor: deleting the entity does not delete the comment. anchorLabel is the caption shown once that happens ("Gloss of ktab, sentence 4"), so pass what the comment is about.

ParameterTypeDescription
entityType 'document'|'text'|'token'|'span'|'relation'|'vocab-item' What kind of thing is being commented on
entityId string The commented entity's id
body string The comment text (1..10000 characters)
opts optional object
opts.anchorLabel optional string What the comment is about, in words (at most 200 characters)
comments.get(id)

Read one comment.

ParameterTypeDescription
id string The comment id
comments.update(id, body)

Edit a comment's body. Only the comment's AUTHOR may do this - not maintainers, not admins. Sets edited on the comment.

ParameterTypeDescription
id string The comment id
body string The replacement text
comments.delete(id)

Delete a comment. The author may delete their own; a project maintainer (or admin) may delete any.

ParameterTypeDescription
id string The comment id
comments.list(projectId, [filters], [filters.documentId], [filters.entityType], [filters.entityId])

List comments in a project, oldest first. Transparently follows pagination cursors and returns the full flat array.

ParameterTypeDescription
projectId string The project to read
filters optional object Narrow the scope
filters.documentId optional string Every comment anywhere in one document
filters.entityType optional string With entityId, one entity's thread
filters.entityId optional string With entityType, one entity's thread
comments.listPage(projectId, [opts], [opts.limit], [opts.cursor], [opts.documentId], [opts.entityType], [opts.entityId])

Fetch a single page of a project's comments.

ParameterTypeDescription
projectId string The project to read
opts optional object
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
opts.documentId optional string Every comment anywhere in one document
opts.entityType optional string With entityId, one entity's thread
opts.entityId optional string With entityType, one entity's thread
comments.iterPages(projectId, [opts], [opts.pageSize], [opts.documentId], [opts.entityType], [opts.entityId])

Async-iterate a project's comments page by page; yields each page's entries array.

ParameterTypeDescription
projectId string The project to read
opts optional object
opts.pageSize optional number Per-request page size
opts.documentId optional string Every comment anywhere in one document
opts.entityType optional string With entityId, one entity's thread
opts.entityId optional string With entityType, one entity's thread
comments.counts(projectId, [filters])

Comment counts per entity, as an {entityId: n} map, over the same scope and filters as list. One cheap request paints a comment indicator on every annotated item in a document without paging through the bodies.

The response is NOT key-transformed: its keys are entity ids, and camelCasing would mangle the hyphens in a UUID.

ParameterTypeDescription
projectId string The project to read
filters optional object Same filters as list()
comments.listInVocab(vocabId, [filters], [filters.entityId])

List the comments on a vocabulary's entries, oldest first. Requires read access to the vocabulary. Transparently follows pagination cursors and returns the full flat array.

ParameterTypeDescription
vocabId string The vocab layer to read
filters optional object
filters.entityId optional string One entry's thread
comments.listInVocabPage(vocabId, [opts], [opts.limit], [opts.cursor], [opts.entityId])

Fetch a single page of a vocabulary's comments.

ParameterTypeDescription
vocabId string The vocab layer to read
opts optional object
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
opts.entityId optional string One entry's thread
comments.iterInVocabPages(vocabId, [opts], [opts.entityId], [opts.pageSize])

Async-iterate a vocabulary's comments page by page, oldest first; yields each page's entries array.

ParameterTypeDescription
vocabId string The vocab layer to read
opts optional object
opts.entityId optional string One entry's thread
opts.pageSize optional number Per-request page size
comments.countsInVocab(vocabId, [filters], [filters.entityId])

Comment counts per entry of a vocabulary, as an {entityId: n} map. The response is NOT key-transformed: its keys are entry ids.

ParameterTypeDescription
vocabId string The vocab layer to read
filters optional object
filters.entityId optional string One entry only

Documents

documents.checkLock(documentId)

Check the lock status of a document.

ParameterTypeDescription
documentId string The document ID
documents.acquireLock(documentId, [auditMessage], [newLockId])

Acquire a document lock as a new holder.

The answer's lockId names the holder: renewLock and releaseLock take it. While the lock is held, a second acquire is refused with HTTP 423, whoever makes it, this user included.

newLockId names the holder from the client's side (a fresh UUID). An acquire whose answer never arrived can then be sent again, which answers 200 while that holder has the lock, or released. Without it the server mints the id, and a lost answer leaves a lock nobody can release until it expires.

outOfBand: the lock is a signal, not project data (see the note at the top of http.js). Queued on a batch it would be taken only at submit, after every write it was meant to guard, and until then answer success to a caller that does not hold it and cannot see the 423 saying somebody else does.

ParameterTypeDescription
documentId string The document ID
auditMessage optional string
newLockId optional string A holder id this client minted
documents.renewLock(documentId, lockId)

Renew the lock lockId holds while it is live. HTTP 423 if another holder has it, and also once it has expired or been dropped, even when nobody holds the document now: a renewal never takes a free document. outOfBand, for the same reason as acquireLock.

ParameterTypeDescription
documentId string The document ID
lockId string The lockId acquireLock answered with
documents.releaseLock(documentId, lockId)

Release the lock lockId holds. Idempotent: a lock that holder no longer has is left alone. outOfBand, for the same reason as acquireLock: queued, the lock would be held until the batch submits, and not released at all if it aborts.

ParameterTypeDescription
documentId string The document ID
lockId string The lockId acquireLock answered with
documents.locked(documentId, fn, [options])

Hold this document's server-enforced lock for the length of fn, releasing it on the way out (including on error). Resolves to what fn returned.

await client.documents.locked(docId, async () => {
  // delete + recreate tokens
});

Wrap any multi-step, server-side mutation of a document that must not interleave with a human editor or another service, e.g. a parser or tokenizer that deletes and recreates a document's tokens, spans and relations. A single atomic call does not need it. While the lock is held, writes to the document by ANOTHER user are refused with HTTP 423; the holder's own writes pass and renew it. If anyone already holds it, another block of this same user included, this rejects with a readable 423 and fn does not run.

The lock is renewed for as long as fn runs, so work that computes for minutes before it writes holds the lock the whole time rather than only for its first minute. If a renewal fails the lock is gone: every later write from this client throws DocumentLockLost, and a block that got to the end anyway ends with that error rather than reporting success. fn receives a lock handle and may read lock.lost (or call lock.raiseIfLost()) to give up sooner.

The lock is per HOLDER: each block is its own, named by lock.lockId, and only that id renews or releases it. NOT re-entrant: a nested locked() block on one document is a second holder and gets the 423. Lock at exactly one level per call path. The block mints its holder id and sends it with the acquire, so an acquire whose answer was lost is sent again (up to three tries) and, if none is answered, released rather than left to expire. A lost lock is recorded on the CLIENT, like strict mode, so it stops every write the client makes (on any batch of it too) and not only the ones this block makes.

ParameterTypeDescription
documentId string The document ID
fn (lock: DocumentLock) => any The work to run while holding it
options optional object { keepAlive }: renew on a timer (default true)
documents.getMedia(documentId)

Get the media file for a document. Media is not versioned, so there is no as-of form: the route refuses the parameter. Prefer the document's own mediaUrl, which carries the file's version for caching.

ParameterTypeDescription
documentId string The document ID
documents.uploadMedia(documentId, file, [auditMessage], [options])

Upload a media file for a document. Uses Apache Tika for content validation.

ParameterTypeDescription
documentId string The document ID
file File The file to upload
auditMessage optional string Custom audit-log message for this write
options optional object { onProgress }: called with { loaded, total } (bytes) as the file goes up. In a browser the upload then travels by XMLHttpRequest, and the request timeout only fires when the upload stalls, not on total time.
documents.setMetadata(documentId, documentId, body)

Delete media file for a document

ParameterTypeDescription
documentId string The document ID / // The upload above is multipart and cannot be batched, but a DELETE // carries no blob, so the batch transport takes it. It is a write // of the document's own data and queues like any other. Note that the // file removal happens outside the server's transaction, so a batch that // aborts after this op does not bring the file back. deleteMedia: (documentId, auditMessage) => this._request("DELETE", /api/v1/documents/${documentId}/media, { auditMessage, }), /** Replace all metadata for a document.
documentId string The document ID
body any The request body
documents.deleteMetadata(documentId)

Remove all metadata from a document.

ParameterTypeDescription
documentId string The document ID
documents.patchMetadata(documentId)

Edit metadata for a document with a list of ops applied in order, in one operation. {op: 'set', path, value} writes value at path, creating missing objects along it; {op: 'delete', path} removes the key at path (a no-op when absent). A path is a non-empty array of keys, the first a top-level key. A path through a non-object is refused (400). See metadataOps and applyMetadataOps.

ParameterTypeDescription
documentId string The document ID
documents.audit(documentId, [startTime], [endTime], [opTypes], [kinds])

Get audit log for a document. Transparently follows pagination cursors and returns the full flat array.

ParameterTypeDescription
documentId string The document ID
startTime optional string Start of time range
endTime optional string End of time range
opTypes optional string[]|string Only return operations of these types, spelled as in an entry's op/type (e.g. ['span-layer/create', 'span-layer/delete']). An entry appears when one of its operations matches, carrying only the ones that did.
kinds optional string[]|string Only the entries of operations of these kinds (e.g. ['review', 'guess-adoption']), each whole
documents.auditPage(documentId, [opts], [opts.order], [opts.limit], [opts.cursor])

One page of the same log, newest-first with order: "desc". Use this rather than audit() wherever the caller wants the recent end of a log that may be long: audit() walks every page before it resolves.

ParameterTypeDescription
documentId string The document ID
opts optional object
opts.order optional "asc"|"desc" "desc" pages newest-first
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
documents.restore(documentId, asOf, [options], [auditMessage])

Restore a document to its state at an earlier time, as one operation: what was deleted since then comes back under its original id, what was added since is removed, and what changed is set back, across every layer. A layer deleted since then, or a vocabulary entry that no longer exists, is skipped and reported under skipped. Resolves to a summary of the changes. Maintainers only.

ParameterTypeDescription
documentId string The document ID
asOf string The moment to go back to (ISO-8601 instant), typically a history entry's endTime
options optional object { dryRun }: with dryRun true nothing is written and the summary says what would change
auditMessage optional string Custom audit message for this operation
documents.get(documentId, [includeBody], [asOf], [layers])

Get a document. Set includeBody to true to include all data.

layers narrows a body read to the layers you name (ids of any kind: text, token, span, or relation). A layer comes back when it is named or is an ancestor of a named layer, and carries its own texts/tokens/spans/relations/vocabs only when it is itself named — so name the text layer too if you also want the text body. An id that is not a layer of this document's project is an error, not a quietly smaller response. Requires includeBody.

ParameterTypeDescription
documentId string The document ID
includeBody optional boolean Include document body data
asOf optional string Temporal query timestamp
layers optional string[]|string Layer ids to restrict a body read to
documents.delete(documentId)

Delete a document and all data contained.

ParameterTypeDescription
documentId string The document ID
documents.update(documentId, name)

Update a document's name.

ParameterTypeDescription
documentId string The document ID
name string The name
documents.create(projectId, name, [metadata])

Create a new document in a project.

ParameterTypeDescription
projectId string The project ID
name string The name
metadata optional any Metadata map. Omit to leave unset; pass null to send JSON null.
documents.copy(documentId, name, [options], [auditMessage])

Copy a document and everything in it into a new document of the same project, as one operation. The copy shares the source's layers and the vocabulary entries its links name, and holds the source's texts, tokens, spans, relations and vocab links under fresh ids, with their metadata. Comments do not travel. The media file does, unless includeMedia is false. Resolves to { id }, plus mediaError when the source had media the copy could not take with it.

ParameterTypeDescription
documentId string The document to copy
name string The new document's name
options optional object { includeMedia }: false leaves the media file behind
auditMessage optional string Custom audit message for this operation

Events

events.record(type, fields, fields.projectId, [fields.documentId], [fields.targetId], [fields.data])

Record one research-telemetry event (core manual, "Research telemetry"). Fire and forget: the event is buffered and sent with others every ten seconds, at fifty events, and when the page is hidden. A batch that fails is dropped, nothing is retried, and nothing is ever thrown. Sends nothing for a project whose switch (config.plaid.research.telemetry) is off, which it reads from the project itself. suggestion.shown is recorded once per target, field and value in a page session.

ParameterTypeDescription
type 'suggestion.shown'|'suggestion.adopted'|'suggestion.dismissed'|'plan.opened' The event type
fields object
fields.projectId string The project it happened in
fields.documentId optional string The document it happened in
fields.targetId optional string What it is about: a token, a plan
fields.data optional object Its details, keyed by single lowercase words (value, source, field, written, conversation)
events.flush()

Send what the recorder holds now, rather than at its next interval.

events.setEnabled(projectId, on)

Tell the recorder a project's switch at once, e.g. right after a maintainer changed it. Turning it off drops what is buffered.

ParameterTypeDescription
projectId string The project
on boolean Whether telemetry is on
events.create(projectId)

Record events directly, with no buffering. Requires write access, and the server refuses with a 403 while the project's switch is off. All or nothing: one bad event refuses the request with a 400 naming it.

ParameterTypeDescription
projectId string The project the events happened in
events.list(projectId, [filters], [filters.types], [filters.startTime], [filters.endTime])

A project's events in arrival order. Maintainer or admin only. Transparently follows pagination cursors and returns the full flat array.

ParameterTypeDescription
projectId string The project to read
filters optional object
filters.types optional string|string[] Only these types
filters.startTime optional string Only events the server stamped at or after this instant
filters.endTime optional string Only events the server stamped at or before this instant
events.listPage(projectId, [opts], [opts.limit], [opts.cursor], [opts.types], [opts.startTime], [opts.endTime])

One page of a project's events. Maintainer or admin only.

ParameterTypeDescription
projectId string The project to read
opts optional object
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
opts.types optional string|string[] Only these types
opts.startTime optional string Only events at or after this instant
opts.endTime optional string Only events at or before this instant
events.iterPages(projectId, [opts], [opts.pageSize], [opts.types], [opts.startTime], [opts.endTime])

Async-iterate a project's events page by page; yields each page's entries array.

ParameterTypeDescription
projectId string The project to read
opts optional object
opts.pageSize optional number Per-request page size
opts.types optional string|string[] Only these types
opts.startTime optional string Only events at or after this instant
opts.endTime optional string Only events at or before this instant

Guidelines

guidelines.create(projectId, title, [opts], [opts.body], [opts.pinned])

Create a guideline in a project. title is the handle an assistant asks for one by, and the only thing a person has to keep current. It is NOT required to be unique, so a title already in use is written like any other: warn about it, do not refuse it. A pinned guideline is one the assistant is given in full on every turn.

ParameterTypeDescription
projectId string The project the guideline belongs to
title string The handle an assistant asks for one by (1..100 characters)
opts optional object
opts.body optional string The Markdown text (up to 20000 characters; may be empty)
opts.pinned optional boolean Send this one to the assistant in full on every turn
guidelines.get(id)

Read one guideline, Markdown body included.

ParameterTypeDescription
id string The guideline id
guidelines.update(id, [changes], [changes.title], [changes.body], [changes.pinned], [changes.expectedUpdatedAt])

Update a guideline. Every field is optional and an omitted one is left alone, so an edit to the body need not restate the title.

Pass expectedUpdatedAt (the updatedAt you last read) when a person has been editing prose: the write then fails with 409 rather than overwriting somebody who saved in between. Leave it off for a pin toggle or a script, which have nothing of anyone's to lose.

ParameterTypeDescription
id string The guideline id
changes optional object
changes.title optional string The new handle
changes.body optional string The new Markdown text
changes.pinned optional boolean Whether the assistant always gets it in full
changes.expectedUpdatedAt optional string Write only if this is still the stored updatedAt
guidelines.delete(id)

Delete a guideline.

ParameterTypeDescription
id string The guideline id
guidelines.list(projectId, [opts], [opts.includeBodies])

List a project's guidelines, by title. Transparently follows pagination cursors and returns the full flat array.

Without includeBodies each entry carries bodyChars, the length of its body, so a caller can budget before fetching any. Pinned guidelines are NOT sorted first: pinned is on every entry and grouping is the caller's.

ParameterTypeDescription
projectId string The project to read
opts optional object
opts.includeBodies optional boolean Return each body instead of its length
guidelines.listPage(projectId, [opts], [opts.limit], [opts.cursor], [opts.includeBodies])

Fetch a single page of a project's guidelines.

ParameterTypeDescription
projectId string The project to read
opts optional object
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
opts.includeBodies optional boolean Return each body instead of its length
guidelines.iterPages(projectId, [opts], [opts.pageSize], [opts.includeBodies])

Async-iterate a project's guidelines page by page; yields each page's entries array.

ParameterTypeDescription
projectId string The project to read
opts optional object
opts.pageSize optional number Per-request page size
opts.includeBodies optional boolean Return each body instead of its length

Invites

invites.list([opts], [opts.projectId], [opts.all])

List invites you minted, oldest first. With projectId, lists that project's invites instead (including co-maintainers'), which requires maintainer or admin on it. Never includes invite codes — the code is returned once, by create(), and is not recoverable afterward. Transparently follows pagination cursors and returns the full flat array.

ParameterTypeDescription
opts optional object
opts.projectId optional string List this project's invites instead of your own
opts.all optional boolean List every invite on the server (admin only)
invites.listPage([opts], [opts.projectId], [opts.all], [opts.limit], [opts.cursor])

Fetch a single page of invites.

ParameterTypeDescription
opts optional object
opts.projectId optional string List this project's invites instead of your own
opts.all optional boolean List every invite on the server (admin only)
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
invites.iterPages([opts], [opts.projectId], [opts.all], [opts.pageSize])

Async-iterate invites page by page; yields each page's entries array.

ParameterTypeDescription
opts optional object
opts.projectId optional string List this project's invites instead of your own
opts.all optional boolean List every invite on the server (admin only)
opts.pageSize optional number Per-request page size
invites.create([opts], [opts.projectId], [opts.projectRole], [opts.grantAdmin], [opts.targetUserId], [opts.maxUses], [opts.ttlDays], [opts.note])

Mint an invite. The returned code is shown ONLY here — it is never stored and cannot be recovered, so build and hand off the link now. Use PlaidClient.inviteUrl() to turn it into one.

Admins may mint anything. A project maintainer may mint role grants on projects they maintain, and nothing else: no admin grant, no grantless invite, no password resets — so for a non-admin, projectId/projectRole are required in practice (403 without them).

EVERY option is optional; create() with no arguments mints a single-use signup link granting nothing but an account. Two pairing rules the server enforces with a 400: projectId and projectRole must be given TOGETHER, and targetUserId may not be combined with projectId, grantAdmin, or a maxUses above 1.

ParameterTypeDescription
opts optional object
opts.projectId optional string Project the redeemer joins (requires projectRole)
opts.projectRole optional string "reader" | "writer" | "maintainer" (requires projectId)
opts.grantAdmin optional boolean Make the new account a global admin (admin only)
opts.targetUserId optional string Password reset for that user instead of a signup; admin only, single-use, grants nothing
opts.maxUses optional number How many accounts this link may create (default 1)
opts.ttlDays optional number Days until it expires (default 14, max 365)
opts.note optional string Human label shown in your invite list
invites.revoke(id)

Revoke an invite, killing the link immediately. Idempotent. Allowed for the creator, an admin, or a maintainer of the invite's project.

ParameterTypeDescription
id string The invite ID

Messages

messages.listen(projectId, onEvent, [path])

Open a Server-Sent Events stream for a project.

ParameterTypeDescription
projectId string The UUID of the project to listen to
onEvent function Callback function that receives (eventType, data). If it returns true, listening will stop.
path optional string Stream path under baseUrl (defaults to the project /listen bus; service channels pass their own).
messages.sendMessage(projectId, data)

Send a message to project listeners.

data may be any JSON value and is sent VERBATIM (rawBody): a message payload is opaque application data, like metadata and config, so its keys must not be re-cased on the way out. Without this a key such as case-marker would reach listeners as caseMarker in JS and case_marker in Python. listen restores it verbatim on the way in.

A message is not saved and writes nothing to History, so it never joins an open operation (withOperation). Made on a batch it still queues, so a message queued after the writes goes out after them.

ParameterTypeDescription
projectId string The UUID of the project to send to
data any The message data to send
messages.discoverServices(projectId)

Discover the services seen on a project (synchronous GET). Currently connected services carry online: true; previously-seen offline ones carry online: false plus a lastSeenAt stamp.

ParameterTypeDescription
projectId string The UUID of the project to query
messages.discardService(projectId, serviceId)

Forget a previously-seen (offline) service. Maintainer-only; 409 if the service is currently connected.

ParameterTypeDescription
projectId string The UUID of the project
serviceId string The ID of the service to forget
messages.serve(projectId, serviceInfo, onServiceRequest, [extras], [onStatus])

Register as a service and handle incoming work requests.

The registration reopens its channel whenever it drops, so a server restart needs no service restart.

ParameterTypeDescription
projectId string The UUID of the project to serve
serviceInfo Object Service information {serviceId, serviceName, description}
onServiceRequest function Callback (data, responseHelper)
extras optional Object Optional additional service metadata
onStatus optional function Optional callback (event, projectId, detail) for connection transitions: 'registered', 'reconnected', 'disconnected', and 'stopped' when the server refuses the channel for good, which ends the registration
messages.requestService(projectId, serviceId, data, [timeout], [onProgress], [signal], [opts])

Request a service to perform work and await its result.

The request outlives this call: after a timeout, an abort, or a dropped connection the service goes on, and attachServiceRequest collects the result given the request id, which opts.onAccepted receives as soon as the server has taken the request. Pass opts.requestId (a UUID you mint) to know the id before submitting; submitting an id that names a request you already made rejoins it instead of starting another.

ParameterTypeDescription
projectId string The UUID of the project
serviceId string The ID of the service to request
data any The request data
timeout optional number =10000] - Timeout in ms
onProgress optional function Called with each progress payload {percent, message}
signal optional AbortSignal Abort to stop waiting; rejects with an AbortError
opts optional Object {requestId, onAccepted, projectIds, noOperation}
messages.attachServiceRequest(projectId, requestId, [timeout], [onProgress], [signal])

Rejoin a service request made earlier and await its result: the latest progress is replayed, then the result comes, or at once if the request already finished. Only the user who submitted it (or an admin). Rejects with an error whose status is 404 when the request is unknown or expired (a finished request's result is kept for a while, not forever).

ParameterTypeDescription
projectId string The UUID of the project
requestId string The request id
timeout optional number =10000] - Timeout in ms
onProgress optional function Called with each progress payload
signal optional AbortSignal Abort to stop waiting
messages.cancelServiceRequest(projectId, requestId)

Ask the service to stop a request made earlier. The request still ends with whatever the service then reports, on the stream of whoever is awaiting it. Rejects with 404 if unknown or expired, 409 once finished.

ParameterTypeDescription
projectId string The UUID of the project
requestId string The request id

Operation Groups

operationGroups.get(id)

Get a logical-operation group (its label + creator).

ParameterTypeDescription
id string The group id
operationGroups.update(id, message)

Relabel a logical-operation group after the fact. Owner or admin only.

ParameterTypeDescription
id string The group id
message string|null The new label

Projects

projects.addWriter(id, userId)

Set a user's access level to read and write for this project.

ParameterTypeDescription
id string The resource ID
userId string The user ID
projects.removeWriter(id, userId)

Remove a user's writer privileges for this project.

ParameterTypeDescription
id string The resource ID
userId string The user ID
projects.addReader(id, userId)

Set a user's access level to read-only for this project.

ParameterTypeDescription
id string The resource ID
userId string The user ID
projects.removeReader(id, userId)

Remove a user's reader privileges for this project.

ParameterTypeDescription
id string The resource ID
userId string The user ID
projects.setConfig(id, namespace, configKey, configValue, [auditMessage])

Set a configuration value for a project in an editor namespace.

ParameterTypeDescription
id string The resource ID
namespace string The config namespace
configKey string The config key
configValue any Configuration value to set
auditMessage optional string Audit message for this write
projects.deleteConfig(id, namespace, configKey, [auditMessage])

Remove a configuration value for a project.

ParameterTypeDescription
id string The resource ID
namespace string The config namespace
configKey string The config key
auditMessage optional string Audit message for this write
projects.addMaintainer(id, userId)

Assign a user as a maintainer for this project.

ParameterTypeDescription
id string The resource ID
userId string The user ID
projects.removeMaintainer(id, userId)

Remove a user's maintainer privileges for this project.

ParameterTypeDescription
id string The resource ID
userId string The user ID
projects.audit(projectId, [startTime], [endTime], [opTypes], [kinds])

Get audit log for a project. Transparently follows pagination cursors and returns the full flat array.

ParameterTypeDescription
projectId string The project ID
startTime optional string Start of time range
endTime optional string End of time range
opTypes optional string[]|string Only return operations of these types, spelled as in an entry's op/type (e.g. ['span-layer/create', 'span-layer/delete']). An entry appears when one of its operations matches, carrying only the ones that did.
kinds optional string[]|string Only the entries of operations of these kinds (e.g. ['review', 'guess-adoption']), each whole
projects.auditPage(projectId, [opts], [opts.order], [opts.limit], [opts.cursor])

One page of the same log, newest-first with order: "desc". Use this rather than audit() wherever the caller wants the recent end of a log that may be long: audit() walks every page before it resolves.

ParameterTypeDescription
projectId string The project ID
opts optional object
opts.order optional "asc"|"desc" "desc" pages newest-first
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
projects.myLastEdits(projectId)

When the calling user last wrote to each document in a project, as a {documentId: timestamp} map. Documents they have never written to are absent. One request covers a whole document list.

The response is NOT key-transformed: its keys are document ids, and camelCasing would mangle the hyphens in a UUID.

ParameterTypeDescription
projectId string The project ID
projects.linkVocab(id, vocabId)

Link a vocabulary to a project.

ParameterTypeDescription
id string The resource ID
vocabId string The vocab layer ID
projects.unlinkVocab(id, vocabId)

Unlink a vocabulary from a project.

ParameterTypeDescription
id string The resource ID
vocabId string The vocab layer ID
projects.get(id)

Get a project by ID. To fetch the project's documents, use listDocuments(id) — the include-documents flag has been removed.

ParameterTypeDescription
id string The resource ID
projects.listDocuments(id)

List all documents in a project. Transparently follows pagination cursors and returns the full flat array.

Note: this endpoint does not support temporal (as-of) queries; the server rejects ?as-of= on the documents-list route with a 400.

ParameterTypeDescription
id string The project ID
projects.listDocumentsPage(id, [opts], [opts.limit], [opts.cursor])

Fetch a single page of a project's documents.

Note: this endpoint does not support temporal (as-of) queries; the server rejects ?as-of= on the documents-list route with a 400.

ParameterTypeDescription
id string The project ID
opts optional object
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
projects.iterDocuments(id, [opts], [opts.pageSize])

Async-iterate a project's documents page by page; yields each page's entries array.

Note: this endpoint does not support temporal (as-of) queries; the server rejects ?as-of= on the documents-list route with a 400.

ParameterTypeDescription
id string The project ID
opts optional object
opts.pageSize optional number Per-request page size
projects.delete(id, [auditMessage], [options], [options.timeout])

Delete a project and everything in it. This is irrecoverable. The project is gone when this returns, and what it holds is removed on the server afterwards.

ParameterTypeDescription
id string The resource ID
auditMessage optional string Custom audit-log message
options optional object
options.timeout optional number Per-request timeout in ms, the client's own by default (0/null disables)
projects.update(id, name)

Update a project's name.

ParameterTypeDescription
id string The resource ID
name string The name
projects.list()

List all projects accessible to user. Transparently follows pagination cursors and returns the full flat array.

projects.listPage([opts], [opts.limit], [opts.cursor])

Fetch a single page of projects.

ParameterTypeDescription
opts optional object
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
projects.iterPages([opts], [opts.pageSize])

Async-iterate projects page by page; yields each page's entries array.

ParameterTypeDescription
opts optional object
opts.pageSize optional number Per-request page size
projects.create(name)

Create a new project. Note: this also registers the user as a maintainer.

ParameterTypeDescription
name string The name

Relation Layers

relationLayers.shift(relationLayerId, direction)

Shift a relation layer's display order.

ParameterTypeDescription
relationLayerId string The relation layer ID
direction string The direction ("up" or "down")
relationLayers.create(spanLayerId, name)

Create a new relation layer.

ParameterTypeDescription
spanLayerId string The span layer ID
name string The name
relationLayers.setConfig(relationLayerId, namespace, configKey, configValue, [auditMessage])

Set a configuration value for a layer in an editor namespace.

ParameterTypeDescription
relationLayerId string The relation layer ID
namespace string The config namespace
configKey string The config key
configValue any Configuration value to set
auditMessage optional string Audit message for this write
relationLayers.deleteConfig(relationLayerId, namespace, configKey, [auditMessage])

Remove a configuration value for a layer.

ParameterTypeDescription
relationLayerId string The relation layer ID
namespace string The config namespace
configKey string The config key
auditMessage optional string Audit message for this write
relationLayers.get(relationLayerId)

Get a relation layer by ID.

ParameterTypeDescription
relationLayerId string The relation layer ID
relationLayers.delete(relationLayerId)

Delete a relation layer.

ParameterTypeDescription
relationLayerId string The relation layer ID
relationLayers.update(relationLayerId, name)

Update a relation layer's name.

ParameterTypeDescription
relationLayerId string The relation layer ID
name string The name

Relations

relations.setMetadata(relationId, body)

Replace all metadata for a relation.

ParameterTypeDescription
relationId string The relation ID
body any The request body
relations.deleteMetadata(relationId)

Remove all metadata from a relation.

ParameterTypeDescription
relationId string The relation ID
relations.patchMetadata(relationId)

Edit metadata for a relation with a list of ops applied in order, in one operation. {op: 'set', path, value} writes value at path, creating missing objects along it; {op: 'delete', path} removes the key at path (a no-op when absent). A path is a non-empty array of keys, the first a top-level key. A path through a non-object is refused (400). See metadataOps and applyMetadataOps.

ParameterTypeDescription
relationId string The relation ID
relations.setTarget(relationId, spanId)

Update the target span of a relation.

ParameterTypeDescription
relationId string The relation ID
spanId string The span ID
relations.get(relationId)

Get a relation by ID.

ParameterTypeDescription
relationId string The relation ID
relations.delete(relationId)

Delete a relation.

ParameterTypeDescription
relationId string The relation ID
relations.update(relationId, value)

Update a relation's value.

ParameterTypeDescription
relationId string The relation ID
value any The value
relations.setSource(relationId, spanId)

Update the source span of a relation.

ParameterTypeDescription
relationId string The relation ID
spanId string The span ID
relations.create(layerId, sourceId, targetId, value, [metadata])

Create a new relation. A relation is a directed edge between two spans with a value, useful for expressing phenomena such as syntactic or semantic relations.

ParameterTypeDescription
layerId string The relation layer ID
sourceId string The source span ID
targetId string The target span ID
value any The value
metadata optional any Metadata map. Omit to leave unset; pass null to send JSON null.
relations.bulkCreate(body)

Create multiple relations in a single operation.

ParameterTypeDescription
body Array The request body
relations.bulkDelete(body)

Delete multiple relations in a single operation. Provide an array of IDs.

ParameterTypeDescription
body Array The request body
relations.bulkUpdate(body)

Update many relations in a single operation: set values and/or patch metadata.

ParameterTypeDescription
body Array Objects of the shape {id, value?, metadata?}. value is set only when the key is present (null sends JSON null); metadata is a list of metadata ops, as for patchMetadata. The relations may lie in several documents of one project; every document touched has its version bumped and every new version comes back in X-Document-Versions (past fifty documents, only their number, in X-Document-Versions-Omitted). A document-version precondition is accepted only when every entry lies in one document. An unknown id refuses the whole update.

Server

server.info()

This server's version and the limits it enforces, e.g. { limits: { mediaFileBytes, jsonBodyBytes, batchOperations, … } }. Sizes are in bytes. Unauthenticated.

server.health()

Liveness, version and database size. Unauthenticated, and served outside the REST router at /health, so it answers even while the API is refusing requests. Never cached — the point is that it is current.

Span Layers

spanLayers.setConfig(spanLayerId, namespace, configKey, configValue, [auditMessage])

Set a configuration value for a layer in an editor namespace.

ParameterTypeDescription
spanLayerId string The span layer ID
namespace string The config namespace
configKey string The config key
configValue any Configuration value to set
auditMessage optional string Audit message for this write
spanLayers.deleteConfig(spanLayerId, namespace, configKey, [auditMessage])

Remove a configuration value for a layer.

ParameterTypeDescription
spanLayerId string The span layer ID
namespace string The config namespace
configKey string The config key
auditMessage optional string Audit message for this write
spanLayers.get(spanLayerId)

Get a span layer by ID.

ParameterTypeDescription
spanLayerId string The span layer ID
spanLayers.delete(spanLayerId)

Delete a span layer.

ParameterTypeDescription
spanLayerId string The span layer ID
spanLayers.update(spanLayerId, name)

Update a span layer's name.

ParameterTypeDescription
spanLayerId string The span layer ID
name string The name
spanLayers.create(tokenLayerId, name)

Create a new span layer.

ParameterTypeDescription
tokenLayerId string The token layer ID
name string The name
spanLayers.shift(spanLayerId, direction)

Shift a span layer's display order.

ParameterTypeDescription
spanLayerId string The span layer ID
direction string The direction ("up" or "down")

Spans

spans.setTokens(spanId, tokens)

Replace tokens for a span.

ParameterTypeDescription
spanId string The span ID
tokens Array The tokens
spans.create(spanLayerId, tokens, value, [metadata])

Create a new span. A span holds a primary atomic value and optional metadata, and must at all times be associated with one or more tokens.

ParameterTypeDescription
spanLayerId string The span layer ID
tokens Array The tokens
value any The value
metadata optional any Metadata map. Omit to leave unset; pass null to send JSON null.
spans.get(spanId)

Get a span by ID.

ParameterTypeDescription
spanId string The span ID
spans.delete(spanId)

Delete a span.

ParameterTypeDescription
spanId string The span ID
spans.update(spanId, value)

Update a span's value.

ParameterTypeDescription
spanId string The span ID
value any The value
spans.bulkCreate(body)

Create multiple spans in a single operation.

ParameterTypeDescription
body Array The request body
spans.bulkDelete(body)

Delete multiple spans in a single operation. Provide an array of IDs.

ParameterTypeDescription
body Array The request body
spans.bulkUpdate(body)

Update many spans in a single operation: set values and/or patch metadata.

ParameterTypeDescription
body Array Objects of the shape {id, value?, metadata?}. value is set only when the key is present (null sends JSON null); metadata is a list of metadata ops, as for patchMetadata. The spans may lie in several documents of one project; every document touched has its version bumped and every new version comes back in X-Document-Versions (past fifty documents, only their number, in X-Document-Versions-Omitted). A document-version precondition is accepted only when every entry lies in one document. An unknown id refuses the whole update.
spans.setMetadata(spanId, body)

Replace all metadata for a span.

ParameterTypeDescription
spanId string The span ID
body any The request body
spans.deleteMetadata(spanId)

Remove all metadata from a span.

ParameterTypeDescription
spanId string The span ID
spans.patchMetadata(spanId)

Edit metadata for a span with a list of ops applied in order, in one operation. {op: 'set', path, value} writes value at path, creating missing objects along it; {op: 'delete', path} removes the key at path (a no-op when absent). A path is a non-empty array of keys, the first a top-level key. A path through a non-object is refused (400). See metadataOps and applyMetadataOps.

ParameterTypeDescription
spanId string The span ID

Text Layers

textLayers.setConfig(textLayerId, namespace, configKey, configValue, [auditMessage])

Set a configuration value for a layer in an editor namespace.

ParameterTypeDescription
textLayerId string The text layer ID
namespace string The config namespace
configKey string The config key
configValue any Configuration value to set
auditMessage optional string Audit message for this write
textLayers.deleteConfig(textLayerId, namespace, configKey, [auditMessage])

Remove a configuration value for a layer.

ParameterTypeDescription
textLayerId string The text layer ID
namespace string The config namespace
configKey string The config key
auditMessage optional string Audit message for this write
textLayers.get(textLayerId)

Get a text layer by ID.

ParameterTypeDescription
textLayerId string The text layer ID
textLayers.delete(textLayerId)

Delete a text layer.

ParameterTypeDescription
textLayerId string The text layer ID
textLayers.update(textLayerId, name)

Update a text layer's name.

ParameterTypeDescription
textLayerId string The text layer ID
name string The name
textLayers.shift(textLayerId, direction)

Shift a text layer's display order within the project.

ParameterTypeDescription
textLayerId string The text layer ID
direction string The direction ("up" or "down")
textLayers.create(projectId, name)

Create a new text layer for a project.

ParameterTypeDescription
projectId string The project ID
name string The name

Texts

texts.setMetadata(textId, body)

Replace all metadata for a text.

ParameterTypeDescription
textId string The text ID
body any The request body
texts.deleteMetadata(textId)

Remove all metadata from a text.

ParameterTypeDescription
textId string The text ID
texts.patchMetadata(textId)

Edit metadata for a text with a list of ops applied in order, in one operation. {op: 'set', path, value} writes value at path, creating missing objects along it; {op: 'delete', path} removes the key at path (a no-op when absent). A path is a non-empty array of keys, the first a top-level key. A path through a non-object is refused (400). See metadataOps and applyMetadataOps.

ParameterTypeDescription
textId string The text ID
texts.create(textLayerId, documentId, body, [metadata])

Create a new text in a document's text layer. A text is a container for one long string in body for a given layer.

ParameterTypeDescription
textLayerId string The text layer ID
documentId string The document ID
body string The request body
metadata optional any Metadata map. Omit to leave unset; pass null to send JSON null.
texts.get(textId)

Get a text.

ParameterTypeDescription
textId string The text ID
texts.delete(textId)

Delete a text and all dependent data.

ParameterTypeDescription
textId string The text ID
texts.update(textId, body, [auditMessage])

Update a text's body. A diff is computed and token indices are updated so that tokens remain intact. Alternatively, body can be a list of edit directives (code-point indices, applied in order): {type: 'delete', index, value: count} {type: 'insert', index, value: string} {type: 'replace', index, length, value: string} — unlike delete+insert, a token covering the whole range is resized to keep it (respell a word in place without losing its annotations). A list is applied exactly as sent. With base (the digest of the body the update was made on, as every read of a text gives it) the update applies only to that body, and is refused with 409 and text-changed otherwise. Strict mode then does not stamp it, unless versioned is true (a batch whose later writes are stamped needs its first write stamped too).

ParameterTypeDescription
textId string The text ID
body any The request body
auditMessage optional string
texts.edit(textId, edits, [auditMessage])

Change a text's body by the edits made at the caret: a list of edit directives as update takes them (code-point indices, applied in order, each index in the body the ones before it left). Only their net change counts. An insert or a delete stays where it was made, and a stretch deleted and typed over is read as a whole new body is. The answer is the text with its new digest and reshape (the tokens moved, the spans and vocab links trimmed, the rows deleted). With base, the digest of the body the edits were made on, the edit applies only to that body and is refused with 409 and text-changed otherwise, and strict mode does not stamp it unless versioned is true. See composeTextEdits and gapsToOps.

ParameterTypeDescription
textId string The text ID
edits Array The edit directives
auditMessage optional string

Token Layers

tokenLayers.shift(tokenLayerId, direction)

Shift a token layer's display order.

ParameterTypeDescription
tokenLayerId string The token layer ID
direction string The direction ("up" or "down")
tokenLayers.create(textLayerId, name, [overlapMode], [parentTokenLayerId])

Create a new token layer.

ParameterTypeDescription
textLayerId string The text layer ID
name string The name
overlapMode optional string Per-layer, immutable token invariant: "any" (default), "non-overlapping", or "partitioning". On partitioning layers, single token create/update/delete are rejected; use bulkCreate plus split/merge/shift.
parentTokenLayerId optional string Optional immutable parent token layer. Tokens in this layer must nest within a parent-layer token; the parent layer must be in the same text layer and be "non-overlapping" or "partitioning" (an "any" parent is rejected). A nested layer may be "any" or "non-overlapping" but not "partitioning" (partitioning is only for root layers), e.g. words (non-overlapping, parent=sentences) within sentences (partitioning).
tokenLayers.setConfig(tokenLayerId, namespace, configKey, configValue, [auditMessage])

Set a configuration value for a layer in an editor namespace.

ParameterTypeDescription
tokenLayerId string The token layer ID
namespace string The config namespace
configKey string The config key
configValue any Configuration value to set
auditMessage optional string Audit message for this write
tokenLayers.deleteConfig(tokenLayerId, namespace, configKey, [auditMessage])

Remove a configuration value for a layer.

ParameterTypeDescription
tokenLayerId string The token layer ID
namespace string The config namespace
configKey string The config key
auditMessage optional string Audit message for this write
tokenLayers.get(tokenLayerId)

Get a token layer by ID.

ParameterTypeDescription
tokenLayerId string The token layer ID
tokenLayers.delete(tokenLayerId)

Delete a token layer.

ParameterTypeDescription
tokenLayerId string The token layer ID
tokenLayers.update(tokenLayerId, name)

Update a token layer's name.

ParameterTypeDescription
tokenLayerId string The token layer ID
name string The name

Tokens

tokens.create(tokenLayerId, text, begin, end, [precedence], [metadata])

Create a new token in a token layer. Tokens define text substrings using begin and end offsets. Tokens may be zero-width and may overlap. For tokens sharing the same begin, precedence controls the linear ordering.

Offsets are 0-based indices in Unicode CODE POINTS (not UTF-16 code units): a supplementary-plane character (emoji, SMP script) is one position. JS strings are UTF-16, so do NOT use str.length / str.substring to compute offsets — count code points instead (e.g. [...str].length, or iterate with codePointAt).

ParameterTypeDescription
tokenLayerId string The token layer ID
text string The text ID
begin number Start offset, inclusive (Unicode code points)
end number End offset, exclusive (Unicode code points)
precedence optional number Ordering precedence
metadata optional any Metadata map. Omit to leave unset; pass null to send JSON null.
tokens.get(tokenId)

Get a token.

ParameterTypeDescription
tokenId string The token ID
tokens.delete(tokenId)

Delete a token and remove it from any spans. If this causes a span to have no remaining tokens, the span will also be deleted.

ParameterTypeDescription
tokenId string The token ID
tokens.update(tokenId, [begin], [end], [precedence])

Update a token.

ParameterTypeDescription
tokenId string The token ID
begin optional number New start offset, inclusive (Unicode code points)
end optional number New end offset, exclusive (Unicode code points)
precedence optional ?number Ordering precedence. Omit (undefined) to leave unchanged; pass a number to set; pass null explicitly to CLEAR it (revert to no explicit ordering). bodyOf keeps null but drops undefined, so the three cases map correctly to the server.
tokens.bulkCreate(body)

Create multiple tokens in a single operation.

ParameterTypeDescription
body Array The request body
tokens.bulkDelete(body)

Delete multiple tokens in a single operation. Provide an array of IDs.

ParameterTypeDescription
body Array The request body
tokens.bulkUpdate(body)

Update many tokens in a single operation: patch metadata.

ParameterTypeDescription
body Array Objects of the shape {id, metadata}. metadata is a list of metadata ops, as for patchMetadata. The tokens may lie in several documents of one project; every document touched has its version bumped and every new version comes back in X-Document-Versions (past fifty documents, only their number, in X-Document-Versions-Omitted). A document-version precondition is accepted only when every entry lies in one document. An unknown id refuses the whole update.
tokens.split(tokenId, position, [auditMessage])

Split a token at a Unicode code-point offset. The original token becomes the left half (keeps its ID, spans, vocab-links); the new right token's ID is returned.

ParameterTypeDescription
tokenId string The token ID
position number Code-point offset to split at (strictly between begin and end)
auditMessage optional string Audit message for this write
tokens.merge(tokenId, otherTokenId)

Merge two tokens. The left token (smaller begin) survives with the combined extent; the right is deleted and its spans/vocab-links are reparented to the left. On partitioning layers the tokens must be adjacent; on non-overlapping layers the merged extent must not engulf a third token.

ParameterTypeDescription
tokenId string The anchor token ID
otherTokenId string The other token to merge in
tokens.shift(tokenId, [begin], [end])

Shift a token's boundary. On partitioning layers the adjacent token is auto-adjusted to preserve the partition; on non-overlapping layers a shift that would create an overlap is rejected.

ParameterTypeDescription
tokenId string The token ID
begin optional number New start offset, inclusive (Unicode code points)
end optional number New end offset, exclusive (Unicode code points)
tokens.setMetadata(tokenId, body)

Replace all metadata for a token.

ParameterTypeDescription
tokenId string The token ID
body any The request body
tokens.deleteMetadata(tokenId)

Remove all metadata from a token.

ParameterTypeDescription
tokenId string The token ID
tokens.patchMetadata(tokenId)

Edit metadata for a token with a list of ops applied in order, in one operation. {op: 'set', path, value} writes value at path, creating missing objects along it; {op: 'delete', path} removes the key at path (a no-op when absent). A path is a non-empty array of keys, the first a top-level key. A path through a non-object is refused (400). See metadataOps and applyMetadataOps.

ParameterTypeDescription
tokenId string The token ID

User Data

userData.list(userId, [opts], [opts.prefix], [opts.pattern], [opts.includeValues], [opts.pageSize])

List a user's private data entries ({key, updatedAt}, plus value when includeValues), ordered by key. Owner or admin only. Transparently follows pagination cursors and returns the full flat array.

Narrow with prefix (the literal head of a key) and/or pattern, a GLOB over the whole key (* any run, ? one character) — the way to ask for a key convention identified by a segment in the middle, e.g. igt:assistant:*:meta:* for every conversation's sidebar entry across every project without dragging down the transcripts beside them.

pageSize is exposed here, and defaults lower than elsewhere, because one value runs to 1 MB: a page of them with includeValues is the largest response this API can be asked for. Raise it when the listing is keys, or the values are known to be small.

ParameterTypeDescription
userId string
opts optional object
opts.prefix optional string Only keys starting with this prefix
opts.pattern optional string Only keys matching this GLOB
opts.includeValues optional boolean Also return each entry's value
opts.pageSize optional number =100] - Entries per request (1..1000)
userData.listPage(userId, [opts], [opts.prefix], [opts.pattern], [opts.includeValues], [opts.limit], [opts.cursor])

One page of a user's private data entries, ordered by key.

ParameterTypeDescription
userId string
opts optional object
opts.prefix optional string Only keys starting with this prefix
opts.pattern optional string Only keys matching this GLOB
opts.includeValues optional boolean Also return each entry's value
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
userData.iterPages(userId, [opts], [opts.prefix], [opts.pattern], [opts.includeValues], [opts.pageSize])

Async generator over a user's private data entries, one page at a time.

ParameterTypeDescription
userId string
opts optional object
opts.prefix optional string Only keys starting with this prefix
opts.pattern optional string Only keys matching this GLOB
opts.includeValues optional boolean Also return each entry's value
opts.pageSize optional number =100] - Entries per request (1..1000)
userData.get(userId, key)

Read one private data entry ({key, updatedAt, value}); 404 if absent.

ParameterTypeDescription
userId string
key string
userData.put(userId, key, value)

Create or replace one private data entry. value is any JSON (up to 1 MB). Not audited, not batchable.

The server stores it verbatim, but this client recases object keys on the way out and back like any other body (myKey <-> my-key), so a value whose keys are camelCase round-trips unchanged while one keyed by arbitrary strings does not. Put such a map under a metadata key, which both clients pass through untouched.

ParameterTypeDescription
userId string
key string
value *
userData.delete(userId, key)

Delete one private data entry; 404 if absent.

ParameterTypeDescription
userId string
key string

Users

users.list([opts], [opts.q])

List (or search) users. Transparently follows pagination cursors and returns the full flat array. Admin-or-maintainer only.

ParameterTypeDescription
opts optional object
opts.q optional string Filter to users whose display name or email contains this text (case-insensitive)
users.listPage([opts], [opts.q], [opts.limit], [opts.cursor])

Fetch a single page of users (optionally filtered by q).

ParameterTypeDescription
opts optional object
opts.q optional string Filter to users whose display name or email contains this text (case-insensitive)
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
users.iterPages([opts], [opts.q], [opts.pageSize])

Async-iterate users page by page; yields each page's entries array.

ParameterTypeDescription
opts optional object
opts.q optional string Filter to users whose display name or email contains this text (case-insensitive)
opts.pageSize optional number Per-request page size
users.create(email, password, isAdmin, [displayName])

Create a new user.

ParameterTypeDescription
email string The account's email address. It becomes the user's id and is what they log in with; it can never be changed.
password string The password
isAdmin boolean Whether the user is an admin
displayName optional string How the user is shown in the UI. Defaults to the local part of the email.
users.audit(userId, [startTime], [endTime], [opTypes], [kinds])

Get audit log for a user's actions. Transparently follows pagination cursors and returns the full flat array.

ParameterTypeDescription
userId string The user ID
startTime optional string Start of time range
endTime optional string End of time range
opTypes optional string[]|string Only return operations of these types, spelled as in an entry's op/type (e.g. ['span-layer/create', 'span-layer/delete']). An entry appears when one of its operations matches, carrying only the ones that did.
kinds optional string[]|string Only the entries of operations of these kinds (e.g. ['review', 'guess-adoption']), each whole
users.auditPage(userId, [opts], [opts.order], [opts.limit], [opts.cursor])

One page of the same log, newest-first with order: "desc". Use this rather than audit() wherever the caller wants the recent end of a log that may be long: audit() walks every page before it resolves.

ParameterTypeDescription
userId string The user ID
opts optional object
opts.order optional "asc"|"desc" "desc" pages newest-first
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
users.get(id)

Get a user by ID

ParameterTypeDescription
id string The resource ID
users.delete(id)

Deactivate a user. Users are never hard-deleted: deactivation rejects their logins and tokens, strips their project memberships and vocab maintainerships, and revokes their API tokens. The user stays visible in listings with a deactivated-at timestamp. Reversible via activate(), which restores login only.

ParameterTypeDescription
id string The resource ID
users.activate(id)

Reactivate a deactivated user, restoring their ability to log in. Project memberships, vocab maintainerships, and API tokens removed at deactivation are NOT restored — re-grant them deliberately.

ParameterTypeDescription
id string The resource ID
users.update(id, [password], [displayName], [isAdmin])

Modify a user. Admins may change the display name, password, and admin status of any user. All other users may only modify their own display name or password.

A user's id is their email address and is fixed for the life of the account — it is what they log in with, so nothing can change it.

ParameterTypeDescription
id string The resource ID (the user's email address)
password optional string New password
displayName optional string New display name
isAdmin optional boolean New admin status
users.avatarUrl(id, [avatarHash])

Build a URL for a user's profile picture, suitable for use directly as an <img> src. An image element cannot send an Authorization header, so the session token rides in the query string, the same way document media does.

Pass the user record's avatarHash as the second argument whenever you have it: the URL then addresses that exact picture, so the browser can cache it indefinitely and still pick up a replacement the moment the user changes it. Returns null when the user has no picture, so callers can fall back to initials without a wasted request.

ParameterTypeDescription
id string The user ID
avatarHash optional string The user record's avatarHash
users.getAvatar(id)

Fetch a user's profile picture as raw bytes. Most callers want avatarUrl() instead. This one is for non-browser consumers.

ParameterTypeDescription
id string The user ID
users.setAvatar(id, file)

Upload a profile picture. Your own, or anyone's if you are an admin. The server center-crops to a square, scales to the configured edge length, and re-encodes, so no client-side resizing is needed. Accepts PNG, JPEG, WebP, and GIF. Resolves to the updated user record.

ParameterTypeDescription
id string The user ID
file File The image to upload

Vocab Items

vocabItems.setMetadata(id, body)

Replace all metadata for a vocab item.

ParameterTypeDescription
id string The resource ID
body any The request body
vocabItems.deleteMetadata(id)

Remove all metadata from a vocab item.

ParameterTypeDescription
id string The resource ID
vocabItems.patchMetadata(id)

Edit metadata for a vocab item with a list of ops applied in order, in one operation. {op: 'set', path, value} writes value at path, creating missing objects along it; {op: 'delete', path} removes the key at path (a no-op when absent). A path is a non-empty array of keys, the first a top-level key. A path through a non-object is refused (400). See metadataOps and applyMetadataOps.

ParameterTypeDescription
id string The resource ID
vocabItems.create(vocabLayerId, form, [metadata])

Create a new vocab item

ParameterTypeDescription
vocabLayerId string The vocab layer ID
form string The vocab item form
metadata optional any Metadata map. Omit to leave unset; pass null to send JSON null.
vocabItems.bulkCreate()

Create multiple vocab items in a single operation. Entries may target different vocab layers; the user must have write access to each.

vocabItems.bulkUpdate()

Update many vocab items in a single operation: set forms and/or patch metadata.

vocabItems.bulkDelete(body)

Delete multiple vocab items in a single operation. Each item's descendant vocab links are deleted too. Provide an array of IDs.

Every document holding one of those links has its version bumped, and a strict-mode client picks up their new versions from the response.

ParameterTypeDescription
body string[] The vocab item IDs to delete
vocabItems.get(id)

Get a vocab item by ID

ParameterTypeDescription
id string The resource ID
vocabItems.delete(id, [auditMessage])

Delete a vocab item, and every link to it. Every document holding one of those links has its version bumped, and a strict-mode client picks up their new versions from the response.

ParameterTypeDescription
id string The resource ID
auditMessage optional string Audit message for this write
vocabItems.merge(survivorId, loserIds)

Merge entries into this one, in one operation. Every link to a loser moves to the survivor (keeping its id and metadata), except a link on words the survivor is already linked to, which is deleted, and then the losers are deleted. Links are read when the merge runs, so one made after the caller looked moves too. Every loser must be in the survivor's vocabulary, and a loser that is already gone is skipped, so a repeated merge changes nothing. References to a loser in other entries' metadata are the caller's to rewrite, in the same batch. Needs maintainer rights on the vocabulary.

ParameterTypeDescription
survivorId string The entry that stays
loserIds string[] The entries merged into it
vocabItems.update(id, form)

Update a vocab item's form. A document read carries the entry's form on every link to it, so a rename restates those documents: each has its version bumped, and a strict-mode client picks up their new versions from the response.

ParameterTypeDescription
id string The resource ID
form string The vocab item form

Vocab Layers

vocabLayers.get(id, [includeItems], [asOf])

Get a vocab layer by ID. With asOf, the vocabulary as it was at that instant, read from its history: the same shape as the live read, its entries with includeItems. A vocabulary that did not exist then is a 404, a malformed or pruned time a 400.

ParameterTypeDescription
id string The resource ID
includeItems optional boolean Include vocab items
asOf optional string The moment to read at (ISO-8601 instant)
vocabLayers.getItemAt(id, itemId, asOf)

One entry of the vocabulary as it was at asOf, also when it has been deleted since. The same shape as vocabItems.get. A 404 when the entry was not in this vocabulary at that time.

ParameterTypeDescription
id string The vocabulary ID
itemId string The entry ID
asOf string The moment to read at (ISO-8601 instant)
vocabLayers.audit(id, [startTime], [endTime], [opTypes], [itemId], [kinds])

Get the audit log of a vocabulary: every change to it or to its entries, folded into entries as the document log is. Links are not listed, they belong to the document they annotate. Transparently follows pagination cursors and returns the full flat array.

ParameterTypeDescription
id string The vocabulary ID
startTime optional string Start of time range
endTime optional string End of time range
opTypes optional string[]|string Only return operations of these types, spelled as in an entry's op/type (e.g. ['vocab-item/delete', 'vocab-item/restore'])
itemId optional string Only the changes that wrote this one entry, each with only its operations that did
kinds optional string[]|string Only the entries of operations of these kinds (e.g. ['review', 'guess-adoption']), each whole
vocabLayers.auditPage(id, [opts], [opts.order], [opts.limit], [opts.cursor], [opts.itemId])

One page of the same log, newest-first with order: "desc". Use this rather than audit() wherever the caller wants the recent end of a log that may be long: audit() walks every page before it resolves.

ParameterTypeDescription
id string The vocabulary ID
opts optional object
opts.order optional "asc"|"desc" "desc" pages newest-first
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
opts.itemId optional string Only the changes that wrote this one entry, each with only its operations that did
vocabLayers.restoreItem(id, itemId, asOf, [options], [auditMessage])

Put one entry of the vocabulary back as it was at asOf, as one operation. A deleted entry comes back under its original id with its form and fields, and a living one has its form and fields set back. Links are not part of an entry: a deleted entry's links come back through each document's own documents.restore. Resolves to {inserted, form, metadata, total}, total 0 when nothing changes. A form set back bumps every linking document, and the new versions come back in X-Document-Versions (or, past fifty documents, X-Document-Versions-Omitted), which the client takes up as on any write. A time when the entry did not exist is a 400. Maintainers of the vocabulary only.

ParameterTypeDescription
id string The vocabulary ID
itemId string The entry ID
asOf string The moment to go back to (ISO-8601 instant), typically a history entry's endTime
options optional object { dryRun }: with dryRun true nothing is written and the summary says what would change
auditMessage optional string Custom audit message for this operation
vocabLayers.delete(id)

Delete a vocab layer.

ParameterTypeDescription
id string The resource ID
vocabLayers.update(id, name)

Update a vocab layer's name.

ParameterTypeDescription
id string The resource ID
name string The name
vocabLayers.setConfig(id, namespace, configKey, configValue, [auditMessage])

Set a configuration value for a layer in an editor namespace.

ParameterTypeDescription
id string The resource ID
namespace string The config namespace
configKey string The config key
configValue any Configuration value to set
auditMessage optional string Audit message for this write
vocabLayers.deleteConfig(id, namespace, configKey, [auditMessage])

Remove a configuration value for a layer.

ParameterTypeDescription
id string The resource ID
namespace string The config namespace
configKey string The config key
auditMessage optional string Audit message for this write
vocabLayers.list()

List all vocab layers accessible to user. Transparently follows pagination cursors and returns the full flat array.

vocabLayers.listPage([opts], [opts.limit], [opts.cursor])

Fetch a single page of vocab layers.

ParameterTypeDescription
opts optional object
opts.limit optional number Page size (1..1000; server default 100)
opts.cursor optional string Opaque cursor from a previous page
vocabLayers.iterPages([opts], [opts.pageSize])

Async-iterate vocab layers page by page; yields each page's entries array.

ParameterTypeDescription
opts optional object
opts.pageSize optional number Per-request page size
vocabLayers.create(name)

Create a new vocab layer. Note: this also registers the user as a maintainer.

ParameterTypeDescription
name string The name
vocabLayers.addMaintainer(id, userId)

Assign a user as a maintainer for this vocab layer.

ParameterTypeDescription
id string The resource ID
userId string The user ID
vocabLayers.removeMaintainer(id, userId)

Remove a user's maintainer privileges for this vocab layer.

ParameterTypeDescription
id string The resource ID
userId string The user ID