Skip to Content
GuidesCollections

Collections

Use collections to group documents and templates by client, project, or matter. You can leave a resource unassigned or add it to several collections. You keep the same resource when you add or remove a membership.

Collections belong to your organization and are separate in live and test mode. API requests use the key’s mode. Dashboard requests can select sandbox=true; omitting it selects live mode. Collections grant no additional access and are not visible to signers.

Find collections in the dashboard

Open Documents → Collections to organize related documents and templates. Select prepared documents and choose Send for signing to prepare a request. Use Documents → Signing requests to track individual and grouped requests. A collection shows its documents, templates, and related signing requests. Use its actions menu to edit, archive, or restore it.

The All collections control above the Documents and Templates tables filters by collection or shows unassigned work. Select All collections inside the control to clear the filter.

On a document or template, open Details and use Edit in the Collections panel to change its memberships. Removing a membership keeps the resource. During creation, choose collections alongside the name after selecting a file.

Create or retrieve a collection

Use an external reference to reconcile a retried creation request. Choose a case-sensitive external ID and preserve its whitespace. You cannot change it after creation or reuse it within the same organization and mode, even after archiving the collection. A duplicate creation returns 409 Conflict; retrieve and inspect the existing record rather than overwriting it.

import { KoralaClient, KoralaError, DocumentStatus } from '@korala/api-client'; const client = new KoralaClient({ apiKeyId: process.env.KORALA_API_KEY_ID!, apiSecret: process.env.KORALA_API_SECRET!, }); const externalId = 'crm:client:acme'; const collection = await client.collections.create({ name: 'Acme onboarding', externalId, metadata: { project: 'onboarding' }, }).catch(async error => { if (error instanceof KoralaError && error.status === 409) { return client.collections.byExternalId(externalId); } throw error; });

The equivalent API operations are POST /api/v1/collections and GET /api/v1/collections/by-external-id?externalId=crm%3Aclient%3Aacme. Korala trims surrounding whitespace from names and requires 1–255 characters. Descriptions allow up to 2,000 characters; external IDs allow 1–255. Metadata must be a JSON object of at most 16 KiB when encoded as UTF-8 JSON. Updating metadata replaces the object.

Put new work in a collection

Supply collectionIds when requesting a document or template upload URL, or when creating a document from a template. Resource creation and assignment commit together. An invalid or archived destination fails creation.

const upload = await client.documents.createUploadUrl({ filename: 'agreement.pdf', contentType: 'application/pdf', collectionIds: [collection.id], }); // PUT the PDF bytes to upload.uploadUrl, then confirm the upload. await client.documents.confirmUpload(upload.documentId); const document = await client.templates.createDocument(templateId, { name: 'Acme offer', signers: { Employee: { name: 'Alex', email: '[email protected]' } }, collectionIds: [collection.id], });

Choose destinations for each generated document; template memberships do not carry over. Omitting collectionIds or supplying [] creates an unassigned resource. A reused template can have a different mode from the generated document; destinations must match the document’s mode.

In the dashboard, creation flows started from a collection preselect it. Clear or change the selection before submitting to choose another destination.

Organize and find existing resources

await client.collections.addDocuments(collection.id, [document.id]); await client.collections.addTemplates(collection.id, [templateId]); const page = await client.documents.listPage({ collectionId: collection.id, status: DocumentStatus.Pending, search: 'offer', includeCollections: true, page: 1, limit: 20, }); const unassigned = await client.templates.list({ unassigned: true }); await client.collections.removeDocuments(collection.id, [document.id]);

Membership operations accept 1–100 distinct resource IDs. Repeated add/remove requests have the same result; an invalid resource rejects the whole request. Creation accepts up to 100 distinct destination collection IDs. These are request limits, not lifetime membership limits.

Collection lists default to active records. Use archiveStatus=active|archived|all, search, page, and limit. Collection and member endpoints default to 20 rows and cap pages at 100. Search is a literal, case-insensitive substring match; filters run before counting and pagination. Document and template lists support collectionId, collectionIds, or unassigned=true; these filters cannot be combined. collectionIds accepts 1–100 distinct UUIDs and matches membership in any selected collection. Each resource appears once, including in pagination totals. All collection IDs must belong to the authenticated organization and mode; an invalid or inaccessible collection rejects the request. Archived memberships are included.

const page = await client.documents.listPage({ collectionIds: [clientCollection.id, projectCollection.id], search: 'offer', status: DocumentStatus.Pending, });

HTTP clients can send ?collectionIds=UUID1,UUID2 or repeated collectionIds=UUID1&collectionIds=UUID2 parameters. Search, status, and other filters still apply to the resulting documents. The SDK serializes arrays for you.

Use client.documents.listPage({ collectionIds: [...] }) or client.templates.listPage({ collectionIds: [...] }) to search several collections. client.collections.listDocuments(id, query) and listTemplates(id, query) search the one collection named by id; their query accepts resource filters such as search and status/activity, but no collection assignment filters.

Authenticated detail responses include collectionIds. List responses include it when includeCollections=true; an empty array means unassigned. Member lists use /collections/:id/documents and /collections/:id/templates.

Create a signing packet

Prepare and send individual documents for signing before selecting them for a packet. Collection templates must first generate documents with signer records.

const eligible = await client.signingPackets.listEligibleDocuments({ collectionId: collection.id, recipientEmail: '[email protected]', }); // Review the documents and resolve the exact signer record for each one. const reviewedItems = eligible.data.map(document => ({ documentId: document.id, signerId: document.signers[0].id, })); const packet = await client.signingPackets.create({ name: 'Acme onboarding signatures', sourceCollectionId: collection.id, recipient: { name: 'Alex', email: '[email protected]' }, items: reviewedItems, }); const history = await client.signingPackets.list({ sourceCollectionId: collection.id, });

Review the final selection before creating the packet. Existing packet rules apply, including mode, recipient, eligibility, and the 50-document limit. The server revalidates membership at creation. Changes require another review; the server does not silently remove selected documents. Send the packet through the existing packet workflow.

Use sourceCollectionId to trace a packet to its collection. Later membership, archive, or name changes leave the packet’s selected items unchanged. Source revisions still freeze at send. Only authenticated management responses expose the origin link.

Archive and restore

await client.collections.archive(collection.id); await client.collections.restore(collection.id);

Archiving preserves members and packet history, and existing signing continues. You can read and edit archived collections and remove their members. Restore before adding members or creating a new packet. Permanent collection deletion is not available.

A template’s mode cannot change while it has any collection memberships, including archived ones. Remove memberships first or duplicate the template into the other mode.

Last updated on