Add document resource to n8n node and MCP sendSigningNotifications tool

Add a complete document resource to the n8n node with 21 operations
covering documents, versions, and signatures — matching the MCP
specification. Also add the sendSigningNotifications tool to the MCP
API for triggering pending signature reminders.

n8n operations: create, get, getAll, update, delete, archive,
unarchive, getVersion, getAllVersions, createDraftVersion,
updateVersion, deleteDraftVersion, publishMajorVersion,
publishMinorVersion, requestApproval, voidApproval, getSignature,
getAllSignatures, requestSignature, cancelSignature,
sendSigningNotifications.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2026-04-13 17:27:11 +02:00
parent 06c0972551
commit d40b114f0f
26 changed files with 2161 additions and 0 deletions

View File

@@ -96,6 +96,11 @@ export class Probo implements INodeType {
value: 'datum',
description: 'Manage data',
},
{
name: 'Document',
value: 'document',
description: 'Manage documents, versions, and signatures',
},
{
name: 'Execute',
value: 'execute',

View File

@@ -0,0 +1,64 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document ID',
name: 'documentId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['archive'],
},
},
default: '',
description: 'The ID of the document to archive',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentId = this.getNodeParameter('documentId', itemIndex) as string;
const query = `
mutation ArchiveDocument($input: ArchiveDocumentInput!) {
archiveDocument(input: $input) {
document {
id
status
trustCenterVisibility
currentPublishedMajor
currentPublishedMinor
archivedAt
createdAt
updatedAt
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, { input: { documentId } });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,57 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Signature ID',
name: 'signatureId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['cancelSignature'],
},
},
default: '',
description: 'The ID of the document version signature to cancel',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const signatureId = this.getNodeParameter('signatureId', itemIndex) as string;
const query = `
mutation CancelSignatureRequest($input: CancelSignatureRequestInput!) {
cancelSignatureRequest(input: $input) {
deletedDocumentVersionSignatureId
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { documentVersionSignatureId: signatureId },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,211 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Organization ID',
name: 'organizationId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['create'],
},
},
default: '',
description: 'The ID of the organization',
required: true,
},
{
displayName: 'Title',
name: 'title',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['create'],
},
},
default: '',
description: 'The title of the document',
required: true,
},
{
displayName: 'Document Type',
name: 'documentType',
type: 'options',
displayOptions: {
show: {
resource: ['document'],
operation: ['create'],
},
},
options: [
{ name: 'Governance', value: 'GOVERNANCE' },
{ name: 'Other', value: 'OTHER' },
{ name: 'Plan', value: 'PLAN' },
{ name: 'Policy', value: 'POLICY' },
{ name: 'Procedure', value: 'PROCEDURE' },
{ name: 'Record', value: 'RECORD' },
{ name: 'Register', value: 'REGISTER' },
{ name: 'Report', value: 'REPORT' },
{ name: 'Template', value: 'TEMPLATE' },
],
default: 'POLICY',
description: 'The type of the document',
required: true,
},
{
displayName: 'Classification',
name: 'classification',
type: 'options',
displayOptions: {
show: {
resource: ['document'],
operation: ['create'],
},
},
options: [
{ name: 'Confidential', value: 'CONFIDENTIAL' },
{ name: 'Internal', value: 'INTERNAL' },
{ name: 'Public', value: 'PUBLIC' },
{ name: 'Secret', value: 'SECRET' },
],
default: 'INTERNAL',
description: 'The classification of the document',
required: true,
},
{
displayName: 'Content',
name: 'content',
type: 'string',
typeOptions: {
rows: 6,
},
displayOptions: {
show: {
resource: ['document'],
operation: ['create'],
},
},
default: '',
description: 'The content of the document in markdown format',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['document'],
operation: ['create'],
},
},
options: [
{
displayName: 'Trust Center Visibility',
name: 'trustCenterVisibility',
type: 'options',
options: [
{ name: 'None', value: 'NONE' },
{ name: 'Private', value: 'PRIVATE' },
{ name: 'Public', value: 'PUBLIC' },
],
default: 'NONE',
description: 'The trust center visibility of the document',
},
{
displayName: 'Default Approver IDs',
name: 'defaultApproverIds',
type: 'string',
default: '',
description: 'Comma-separated list of default approver profile IDs',
},
],
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const organizationId = this.getNodeParameter('organizationId', itemIndex) as string;
const title = this.getNodeParameter('title', itemIndex) as string;
const documentType = this.getNodeParameter('documentType', itemIndex) as string;
const classification = this.getNodeParameter('classification', itemIndex) as string;
const content = this.getNodeParameter('content', itemIndex, '') as string;
const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {}) as {
trustCenterVisibility?: string;
defaultApproverIds?: string;
};
const query = `
mutation CreateDocument($input: CreateDocumentInput!) {
createDocument(input: $input) {
documentEdge {
node {
id
status
trustCenterVisibility
currentPublishedMajor
currentPublishedMinor
archivedAt
createdAt
updatedAt
}
}
documentVersionEdge {
node {
id
title
major
minor
status
content
changelog
classification
documentType
publishedAt
createdAt
updatedAt
}
}
}
}
`;
const input: Record<string, unknown> = {
organizationId,
title,
documentType,
classification,
};
if (content) input.content = content;
if (additionalFields.trustCenterVisibility) input.trustCenterVisibility = additionalFields.trustCenterVisibility;
if (additionalFields.defaultApproverIds) {
input.defaultApproverIds = additionalFields.defaultApproverIds.split(',').map(id => id.trim()).filter(Boolean);
}
const responseData = await proboApiRequest.call(this, query, { input });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,70 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document ID',
name: 'documentId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['createDraftVersion'],
},
},
default: '',
description: 'The ID of the document',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentId = this.getNodeParameter('documentId', itemIndex) as string;
const query = `
mutation CreateDraftDocumentVersion($input: CreateDraftDocumentVersionInput!) {
createDraftDocumentVersion(input: $input) {
documentVersionEdge {
node {
id
title
major
minor
status
content
changelog
classification
documentType
publishedAt
createdAt
updatedAt
}
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, { input: { documentID: documentId } });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,55 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document ID',
name: 'documentId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['delete'],
},
},
default: '',
description: 'The ID of the document to delete',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentId = this.getNodeParameter('documentId', itemIndex) as string;
const query = `
mutation DeleteDocument($input: DeleteDocumentInput!) {
deleteDocument(input: $input) {
deletedDocumentId
}
}
`;
const responseData = await proboApiRequest.call(this, query, { input: { documentId } });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,55 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document Version ID',
name: 'documentVersionId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['deleteDraftVersion'],
},
},
default: '',
description: 'The ID of the draft document version to delete',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentVersionId = this.getNodeParameter('documentVersionId', itemIndex) as string;
const query = `
mutation DeleteDraftDocumentVersion($input: DeleteDraftDocumentVersionInput!) {
deleteDraftDocumentVersion(input: $input) {
deletedDocumentVersionId
}
}
`;
const responseData = await proboApiRequest.call(this, query, { input: { documentVersionId } });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,64 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document ID',
name: 'documentId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['get'],
},
},
default: '',
description: 'The ID of the document',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentId = this.getNodeParameter('documentId', itemIndex) as string;
const query = `
query GetDocument($documentId: ID!) {
node(id: $documentId) {
... on Document {
id
status
trustCenterVisibility
currentPublishedMajor
currentPublishedMinor
archivedAt
createdAt
updatedAt
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, { documentId });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,117 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData, IDataObject } from 'n8n-workflow';
import { proboApiRequestAllItems } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Organization ID',
name: 'organizationId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['getAll'],
},
},
default: '',
description: 'The ID of the organization',
required: true,
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
resource: ['document'],
operation: ['getAll'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
resource: ['document'],
operation: ['getAll'],
returnAll: [false],
},
},
typeOptions: {
minValue: 1,
},
default: 50,
description: 'Max number of results to return',
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const organizationId = this.getNodeParameter('organizationId', itemIndex) as string;
const returnAll = this.getNodeParameter('returnAll', itemIndex) as boolean;
const limit = this.getNodeParameter('limit', itemIndex, 50) as number;
const query = `
query GetDocuments($organizationId: ID!, $first: Int, $after: CursorKey) {
node(id: $organizationId) {
... on Organization {
documents(first: $first, after: $after) {
edges {
node {
id
status
trustCenterVisibility
currentPublishedMajor
currentPublishedMinor
archivedAt
createdAt
updatedAt
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}
`;
const documents = await proboApiRequestAllItems.call(
this,
query,
{ organizationId },
(response) => {
const data = response?.data as IDataObject | undefined;
const node = data?.node as IDataObject | undefined;
return node?.documents as IDataObject | undefined;
},
returnAll,
limit,
);
return {
json: { documents },
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,120 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData, IDataObject } from 'n8n-workflow';
import { proboApiRequestAllItems } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document Version ID',
name: 'documentVersionId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['getAllSignatures'],
},
},
default: '',
description: 'The ID of the document version',
required: true,
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
resource: ['document'],
operation: ['getAllSignatures'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
resource: ['document'],
operation: ['getAllSignatures'],
returnAll: [false],
},
},
typeOptions: {
minValue: 1,
},
default: 50,
description: 'Max number of results to return',
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentVersionId = this.getNodeParameter('documentVersionId', itemIndex) as string;
const returnAll = this.getNodeParameter('returnAll', itemIndex) as boolean;
const limit = this.getNodeParameter('limit', itemIndex, 50) as number;
const query = `
query GetDocumentVersionSignatures($documentVersionId: ID!, $first: Int, $after: CursorKey) {
node(id: $documentVersionId) {
... on DocumentVersion {
signatures(first: $first, after: $after) {
edges {
node {
id
state
signedAt
requestedAt
createdAt
updatedAt
signedBy {
id
fullName
primaryEmailAddress
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}
`;
const signatures = await proboApiRequestAllItems.call(
this,
query,
{ documentVersionId },
(response) => {
const data = response?.data as IDataObject | undefined;
const node = data?.node as IDataObject | undefined;
return node?.signatures as IDataObject | undefined;
},
returnAll,
limit,
);
return {
json: { signatures },
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,121 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData, IDataObject } from 'n8n-workflow';
import { proboApiRequestAllItems } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document ID',
name: 'documentId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['getAllVersions'],
},
},
default: '',
description: 'The ID of the document',
required: true,
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
resource: ['document'],
operation: ['getAllVersions'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
resource: ['document'],
operation: ['getAllVersions'],
returnAll: [false],
},
},
typeOptions: {
minValue: 1,
},
default: 50,
description: 'Max number of results to return',
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentId = this.getNodeParameter('documentId', itemIndex) as string;
const returnAll = this.getNodeParameter('returnAll', itemIndex) as boolean;
const limit = this.getNodeParameter('limit', itemIndex, 50) as number;
const query = `
query GetDocumentVersions($documentId: ID!, $first: Int, $after: CursorKey) {
node(id: $documentId) {
... on Document {
versions(first: $first, after: $after) {
edges {
node {
id
title
major
minor
status
content
changelog
classification
documentType
publishedAt
createdAt
updatedAt
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}
`;
const versions = await proboApiRequestAllItems.call(
this,
query,
{ documentId },
(response) => {
const data = response?.data as IDataObject | undefined;
const node = data?.node as IDataObject | undefined;
return node?.versions as IDataObject | undefined;
},
returnAll,
limit,
);
return {
json: { versions },
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,67 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Signature ID',
name: 'signatureId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['getSignature'],
},
},
default: '',
description: 'The ID of the document version signature',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const signatureId = this.getNodeParameter('signatureId', itemIndex) as string;
const query = `
query GetDocumentVersionSignature($signatureId: ID!) {
node(id: $signatureId) {
... on DocumentVersionSignature {
id
state
signedAt
requestedAt
createdAt
updatedAt
signedBy {
id
fullName
primaryEmailAddress
}
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, { signatureId });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,68 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document Version ID',
name: 'documentVersionId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['getVersion'],
},
},
default: '',
description: 'The ID of the document version',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentVersionId = this.getNodeParameter('documentVersionId', itemIndex) as string;
const query = `
query GetDocumentVersion($documentVersionId: ID!) {
node(id: $documentVersionId) {
... on DocumentVersion {
id
title
major
minor
status
content
changelog
classification
documentType
publishedAt
createdAt
updatedAt
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, { documentVersionId });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,224 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties } from 'n8n-workflow';
import * as createOp from './create.operation';
import * as getOp from './get.operation';
import * as getAllOp from './getAll.operation';
import * as updateOp from './update.operation';
import * as deleteOp from './delete.operation';
import * as archiveOp from './archive.operation';
import * as unarchiveOp from './unarchive.operation';
import * as getVersionOp from './getVersion.operation';
import * as getAllVersionsOp from './getAllVersions.operation';
import * as createDraftVersionOp from './createDraftVersion.operation';
import * as updateVersionOp from './updateVersion.operation';
import * as deleteDraftVersionOp from './deleteDraftVersion.operation';
import * as publishMajorVersionOp from './publishMajorVersion.operation';
import * as publishMinorVersionOp from './publishMinorVersion.operation';
import * as requestApprovalOp from './requestApproval.operation';
import * as voidApprovalOp from './voidApproval.operation';
import * as getSignatureOp from './getSignature.operation';
import * as getAllSignaturesOp from './getAllSignatures.operation';
import * as requestSignatureOp from './requestSignature.operation';
import * as cancelSignatureOp from './cancelSignature.operation';
import * as sendSigningNotificationsOp from './sendSigningNotifications.operation';
export const description: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['document'],
},
},
options: [
{
name: 'Archive',
value: 'archive',
description: 'Archive a document',
action: 'Archive a document',
},
{
name: 'Cancel Signature',
value: 'cancelSignature',
description: 'Cancel a signature request',
action: 'Cancel a document signature request',
},
{
name: 'Create',
value: 'create',
description: 'Create a new document',
action: 'Create a document',
},
{
name: 'Create Draft Version',
value: 'createDraftVersion',
description: 'Create a new draft version from the latest published version',
action: 'Create a draft document version',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a document',
action: 'Delete a document',
},
{
name: 'Delete Draft Version',
value: 'deleteDraftVersion',
description: 'Delete a draft document version',
action: 'Delete a draft document version',
},
{
name: 'Get',
value: 'get',
description: 'Get a document',
action: 'Get a document',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Get many documents',
action: 'Get many documents',
},
{
name: 'Get Many Signatures',
value: 'getAllSignatures',
description: 'Get many signatures for a document version',
action: 'Get many document version signatures',
},
{
name: 'Get Many Versions',
value: 'getAllVersions',
description: 'Get many versions of a document',
action: 'Get many document versions',
},
{
name: 'Get Signature',
value: 'getSignature',
description: 'Get a document version signature',
action: 'Get a document version signature',
},
{
name: 'Get Version',
value: 'getVersion',
description: 'Get a document version',
action: 'Get a document version',
},
{
name: 'Publish Major Version',
value: 'publishMajorVersion',
description: 'Publish a draft as a new major version',
action: 'Publish a major document version',
},
{
name: 'Publish Minor Version',
value: 'publishMinorVersion',
description: 'Publish a draft as a minor version',
action: 'Publish a minor document version',
},
{
name: 'Request Approval',
value: 'requestApproval',
description: 'Request approval for a document version',
action: 'Request document version approval',
},
{
name: 'Request Signature',
value: 'requestSignature',
description: 'Request a signature for a document version',
action: 'Request a document version signature',
},
{
name: 'Send Signing Notifications',
value: 'sendSigningNotifications',
description: 'Send signing notifications to all pending signatories',
action: 'Send signing notifications',
},
{
name: 'Unarchive',
value: 'unarchive',
description: 'Unarchive a document',
action: 'Unarchive a document',
},
{
name: 'Update',
value: 'update',
description: 'Update an existing document',
action: 'Update a document',
},
{
name: 'Update Version',
value: 'updateVersion',
description: 'Update a draft document version',
action: 'Update a document version',
},
{
name: 'Void Approval',
value: 'voidApproval',
description: 'Void a pending approval request',
action: 'Void a document version approval',
},
],
default: 'create',
},
...createOp.description,
...getOp.description,
...getAllOp.description,
...updateOp.description,
...deleteOp.description,
...archiveOp.description,
...unarchiveOp.description,
...getVersionOp.description,
...getAllVersionsOp.description,
...createDraftVersionOp.description,
...updateVersionOp.description,
...deleteDraftVersionOp.description,
...publishMajorVersionOp.description,
...publishMinorVersionOp.description,
...requestApprovalOp.description,
...voidApprovalOp.description,
...getSignatureOp.description,
...getAllSignaturesOp.description,
...requestSignatureOp.description,
...cancelSignatureOp.description,
...sendSigningNotificationsOp.description,
];
export {
createOp as create,
getOp as get,
getAllOp as getAll,
updateOp as update,
deleteOp as delete,
archiveOp as archive,
unarchiveOp as unarchive,
getVersionOp as getVersion,
getAllVersionsOp as getAllVersions,
createDraftVersionOp as createDraftVersion,
updateVersionOp as updateVersion,
deleteDraftVersionOp as deleteDraftVersion,
publishMajorVersionOp as publishMajorVersion,
publishMinorVersionOp as publishMinorVersion,
requestApprovalOp as requestApproval,
voidApprovalOp as voidApproval,
getSignatureOp as getSignature,
getAllSignaturesOp as getAllSignatures,
requestSignatureOp as requestSignature,
cancelSignatureOp as cancelSignature,
sendSigningNotificationsOp as sendSigningNotifications,
};

View File

@@ -0,0 +1,97 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document ID',
name: 'documentId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['publishMajorVersion'],
},
},
default: '',
description: 'The ID of the document',
required: true,
},
{
displayName: 'Changelog',
name: 'changelog',
type: 'string',
typeOptions: {
rows: 4,
},
displayOptions: {
show: {
resource: ['document'],
operation: ['publishMajorVersion'],
},
},
default: '',
description: 'The changelog for this version',
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentId = this.getNodeParameter('documentId', itemIndex) as string;
const changelog = this.getNodeParameter('changelog', itemIndex, '') as string;
const query = `
mutation PublishMajorDocumentVersion($input: PublishMajorDocumentVersionInput!) {
publishMajorDocumentVersion(input: $input) {
document {
id
status
trustCenterVisibility
currentPublishedMajor
currentPublishedMinor
createdAt
updatedAt
}
documentVersion {
id
title
major
minor
status
content
changelog
classification
documentType
publishedAt
createdAt
updatedAt
}
}
}
`;
const input: Record<string, unknown> = { documentId };
if (changelog) input.changelog = changelog;
const responseData = await proboApiRequest.call(this, query, { input });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,97 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document ID',
name: 'documentId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['publishMinorVersion'],
},
},
default: '',
description: 'The ID of the document',
required: true,
},
{
displayName: 'Changelog',
name: 'changelog',
type: 'string',
typeOptions: {
rows: 4,
},
displayOptions: {
show: {
resource: ['document'],
operation: ['publishMinorVersion'],
},
},
default: '',
description: 'The changelog for this version',
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentId = this.getNodeParameter('documentId', itemIndex) as string;
const changelog = this.getNodeParameter('changelog', itemIndex, '') as string;
const query = `
mutation PublishMinorDocumentVersion($input: PublishMinorDocumentVersionInput!) {
publishMinorDocumentVersion(input: $input) {
document {
id
status
trustCenterVisibility
currentPublishedMajor
currentPublishedMinor
createdAt
updatedAt
}
documentVersion {
id
title
major
minor
status
content
changelog
classification
documentType
publishedAt
createdAt
updatedAt
}
}
}
`;
const input: Record<string, unknown> = { documentId };
if (changelog) input.changelog = changelog;
const responseData = await proboApiRequest.call(this, query, { input });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,97 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document ID',
name: 'documentId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['requestApproval'],
},
},
default: '',
description: 'The ID of the document',
required: true,
},
{
displayName: 'Approver IDs',
name: 'approverIds',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['requestApproval'],
},
},
default: '',
description: 'Comma-separated list of approver profile IDs',
required: true,
},
{
displayName: 'Changelog',
name: 'changelog',
type: 'string',
typeOptions: {
rows: 4,
},
displayOptions: {
show: {
resource: ['document'],
operation: ['requestApproval'],
},
},
default: '',
description: 'The changelog for this version',
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentId = this.getNodeParameter('documentId', itemIndex) as string;
const approverIds = this.getNodeParameter('approverIds', itemIndex) as string;
const changelog = this.getNodeParameter('changelog', itemIndex, '') as string;
const query = `
mutation RequestDocumentVersionApproval($input: RequestDocumentVersionApprovalInput!) {
requestDocumentVersionApproval(input: $input) {
approvalQuorum {
id
createdAt
updatedAt
}
}
}
`;
const input: Record<string, unknown> = {
documentId,
approverIds: approverIds.split(',').map(id => id.trim()).filter(Boolean),
};
if (changelog) input.changelog = changelog;
const responseData = await proboApiRequest.call(this, query, { input });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,86 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document Version ID',
name: 'documentVersionId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['requestSignature'],
},
},
default: '',
description: 'The ID of the document version',
required: true,
},
{
displayName: 'Signatory ID',
name: 'signatoryId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['requestSignature'],
},
},
default: '',
description: 'The profile ID of the signatory',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentVersionId = this.getNodeParameter('documentVersionId', itemIndex) as string;
const signatoryId = this.getNodeParameter('signatoryId', itemIndex) as string;
const query = `
mutation RequestSignature($input: RequestSignatureInput!) {
requestSignature(input: $input) {
documentVersionSignatureEdge {
node {
id
state
signedAt
requestedAt
createdAt
updatedAt
signedBy {
id
fullName
primaryEmailAddress
}
}
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { documentVersionId, signatoryId },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,55 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Organization ID',
name: 'organizationId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['sendSigningNotifications'],
},
},
default: '',
description: 'The ID of the organization',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const organizationId = this.getNodeParameter('organizationId', itemIndex) as string;
const query = `
mutation SendSigningNotifications($input: SendSigningNotificationsInput!) {
sendSigningNotifications(input: $input) {
success
}
}
`;
const responseData = await proboApiRequest.call(this, query, { input: { organizationId } });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,64 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document ID',
name: 'documentId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['unarchive'],
},
},
default: '',
description: 'The ID of the document to unarchive',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentId = this.getNodeParameter('documentId', itemIndex) as string;
const query = `
mutation UnarchiveDocument($input: UnarchiveDocumentInput!) {
unarchiveDocument(input: $input) {
document {
id
status
trustCenterVisibility
currentPublishedMajor
currentPublishedMinor
archivedAt
createdAt
updatedAt
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, { input: { documentId } });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,108 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document ID',
name: 'documentId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['update'],
},
},
default: '',
description: 'The ID of the document to update',
required: true,
},
{
displayName: 'Update Fields',
name: 'updateFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['document'],
operation: ['update'],
},
},
options: [
{
displayName: 'Trust Center Visibility',
name: 'trustCenterVisibility',
type: 'options',
options: [
{ name: 'None', value: 'NONE' },
{ name: 'Private', value: 'PRIVATE' },
{ name: 'Public', value: 'PUBLIC' },
],
default: 'NONE',
description: 'The trust center visibility of the document',
},
{
displayName: 'Default Approver IDs',
name: 'defaultApproverIds',
type: 'string',
default: '',
description: 'Comma-separated list of default approver profile IDs',
},
],
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentId = this.getNodeParameter('documentId', itemIndex) as string;
const updateFields = this.getNodeParameter('updateFields', itemIndex, {}) as {
trustCenterVisibility?: string;
defaultApproverIds?: string;
};
const query = `
mutation UpdateDocument($input: UpdateDocumentInput!) {
updateDocument(input: $input) {
document {
id
status
trustCenterVisibility
currentPublishedMajor
currentPublishedMinor
archivedAt
createdAt
updatedAt
}
}
}
`;
const input: Record<string, unknown> = { id: documentId };
if (updateFields.trustCenterVisibility !== undefined) input.trustCenterVisibility = updateFields.trustCenterVisibility;
if (updateFields.defaultApproverIds !== undefined && updateFields.defaultApproverIds !== '') {
input.defaultApproverIds = updateFields.defaultApproverIds.split(',').map(id => id.trim()).filter(Boolean);
}
const responseData = await proboApiRequest.call(this, query, { input });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,143 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document Version ID',
name: 'documentVersionId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['updateVersion'],
},
},
default: '',
description: 'The ID of the document version to update',
required: true,
},
{
displayName: 'Update Fields',
name: 'updateFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['document'],
operation: ['updateVersion'],
},
},
options: [
{
displayName: 'Title',
name: 'title',
type: 'string',
default: '',
description: 'The title of the document version',
},
{
displayName: 'Content',
name: 'content',
type: 'string',
typeOptions: {
rows: 6,
},
default: '',
description: 'The content of the document in markdown format',
},
{
displayName: 'Classification',
name: 'classification',
type: 'options',
options: [
{ name: 'Confidential', value: 'CONFIDENTIAL' },
{ name: 'Internal', value: 'INTERNAL' },
{ name: 'Public', value: 'PUBLIC' },
{ name: 'Secret', value: 'SECRET' },
],
default: 'INTERNAL',
description: 'The classification of the document',
},
{
displayName: 'Document Type',
name: 'documentType',
type: 'options',
options: [
{ name: 'Governance', value: 'GOVERNANCE' },
{ name: 'Other', value: 'OTHER' },
{ name: 'Plan', value: 'PLAN' },
{ name: 'Policy', value: 'POLICY' },
{ name: 'Procedure', value: 'PROCEDURE' },
{ name: 'Record', value: 'RECORD' },
{ name: 'Register', value: 'REGISTER' },
{ name: 'Report', value: 'REPORT' },
{ name: 'Template', value: 'TEMPLATE' },
],
default: 'POLICY',
description: 'The type of the document',
},
],
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentVersionId = this.getNodeParameter('documentVersionId', itemIndex) as string;
const updateFields = this.getNodeParameter('updateFields', itemIndex, {}) as {
title?: string;
content?: string;
classification?: string;
documentType?: string;
};
const query = `
mutation UpdateDocumentVersion($input: UpdateDocumentVersionInput!) {
updateDocumentVersion(input: $input) {
documentVersion {
id
title
major
minor
status
content
changelog
classification
documentType
publishedAt
createdAt
updatedAt
}
}
}
`;
const input: Record<string, unknown> = { documentVersionId };
if (updateFields.title !== undefined) input.title = updateFields.title;
if (updateFields.content !== undefined) input.content = updateFields.content;
if (updateFields.classification !== undefined) input.classification = updateFields.classification;
if (updateFields.documentType !== undefined) input.documentType = updateFields.documentType;
const responseData = await proboApiRequest.call(this, query, { input });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,73 @@
// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Document Version ID',
name: 'documentVersionId',
type: 'string',
displayOptions: {
show: {
resource: ['document'],
operation: ['voidApproval'],
},
},
default: '',
description: 'The ID of the document version',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const documentVersionId = this.getNodeParameter('documentVersionId', itemIndex) as string;
const query = `
mutation VoidDocumentVersionApproval($input: VoidDocumentVersionApprovalInput!) {
voidDocumentVersionApproval(input: $input) {
approvalQuorum {
id
createdAt
updatedAt
}
documentVersion {
id
title
major
minor
status
content
changelog
classification
documentType
publishedAt
createdAt
updatedAt
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, { input: { documentVersionId } });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -17,6 +17,7 @@ import * as asset from './asset';
import * as audit from './audit';
import * as control from './control';
import * as datum from './datum';
import * as document from './document';
import * as execute from './execute';
import * as framework from './framework';
import * as measure from './measure';
@@ -41,6 +42,7 @@ export const resources: Record<string, ResourceModule> = {
audit: audit as ResourceModule,
control: control as ResourceModule,
datum: datum as ResourceModule,
document: document as ResourceModule,
execute: execute as ResourceModule,
framework: framework as ResourceModule,
measure: measure as ResourceModule,

View File

@@ -3956,3 +3956,18 @@ func (r *Resolver) VoidDocumentVersionApprovalTool(ctx context.Context, req *mcp
DocumentVersion: types.NewDocumentVersion(documentVersion),
}, nil
}
func (r *Resolver) SendSigningNotificationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.SendSigningNotificationsInput) (*mcp.CallToolResult, types.SendSigningNotificationsOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDocumentSendSigningNotifications)
svc := r.ProboService(ctx, input.OrganizationID)
err := svc.Documents.SendSigningNotifications(ctx, input.OrganizationID)
if err != nil {
panic(fmt.Errorf("cannot send signing notifications: %w", err))
}
return nil, types.SendSigningNotificationsOutput{
Success: true,
}, nil
}

View File

@@ -5883,6 +5883,24 @@ components:
document_version:
$ref: "#/components/schemas/DocumentVersion"
SendSigningNotificationsInput:
type: object
required:
- organization_id
properties:
organization_id:
$ref: "#/components/schemas/GID"
description: Organization ID
SendSigningNotificationsOutput:
type: object
required:
- success
properties:
success:
type: boolean
description: Whether the notifications were sent successfully
MeetingOrderField:
type: string
enum:
@@ -8515,6 +8533,14 @@ tools:
$ref: "#/components/schemas/VoidDocumentVersionApprovalInput"
outputSchema:
$ref: "#/components/schemas/VoidDocumentVersionApprovalOutput"
- name: sendSigningNotifications
description: Send signing notifications to all signatories with pending signature requests in the organization
hints:
readonly: false
inputSchema:
$ref: "#/components/schemas/SendSigningNotificationsInput"
outputSchema:
$ref: "#/components/schemas/SendSigningNotificationsOutput"
- name: listMeetings
description: List all meetings for the organization
hints: