diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7ba91bdb..628adb41 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -34,12 +34,11 @@ jobs: GTM_CONTAINER_ID: ${{ secrets.GTM_CONTAINER_ID }} - name: Deploy to Cloudflare Pages - uses: cloudflare/pages-action@v1 + uses: cloudflare/wrangler-action@v4 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - projectName: turbodocx-docs - directory: build + command: pages deploy build --project-name=turbodocx-docs gitHubToken: ${{ secrets.GITHUB_TOKEN }} - name: Submit URLs to IndexNow diff --git a/docs/API/create-image-variable-folder.api.mdx b/docs/API/create-image-variable-folder.api.mdx index 1d5c767d..986c1004 100644 --- a/docs/API/create-image-variable-folder.api.mdx +++ b/docs/API/create-image-variable-folder.api.mdx @@ -1,7 +1,7 @@ --- id: create-image-variable-folder title: "Create Image Variable (Folder)" -description: "Create Image Variable (Folder)" +description: "Create a reusable image, text, or HTML variable in a template folder or your knowledge base. Includes example request, response, and error handling." sidebar_label: "Create Image Variable (Folder)" hide_title: true hide_table_of_contents: true @@ -16,9 +16,73 @@ custom_edit_url: null # Create Image Variable (Folder) - - Create Image Variable (Folder) - + +This endpoint creates a reusable variable scoped to a template folder or to your organization's global knowledge base, independent of any single template. Despite the name, it is not limited to images: `mimeType` also accepts `text` and `html`, and the same endpoint is used for [Read Variables (Folder)](/docs/API/read-variables-folder) to later list. + +## When to use it + +Use this endpoint to build a shared library of content, such as a company logo, a standard address block, or boilerplate legal language, that multiple templates can reference by placeholder without duplicating the content in each one. + +## Example request + +```bash +curl -X POST "https://api.turbodocx.com/Variable" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Company Logo", + "placeholder": "{CompanyLogo}", + "mimeType": "image", + "text": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB...", + "templateFolderId": "9d2b1c63-0f77-4a9c-b1d0-2c5e6f7a8b90", + "allowRichTextInjection": true + }' +``` + +Optionally send `templateFolderId` (scopes the variable to that folder) or `isGlobal: true` (adds it to your org-wide knowledge base); at most one may be set, and sending both is rejected. `text` must be a base64 `data:` URI when `mimeType` is `"image"`, or plain text/HTML otherwise. `placeholder` must be unique within its folder or knowledge base and, if set, must be wrapped in curly braces, for example `{CompanyLogo}`. + +## Example response + +On success the endpoint returns the created variable: + +```json +{ + "data": { + "results": { + "variable": { + "id": "e4f5a6b7-8c9d-4e0f-a1b2-3c4d5e6f7a8b", + "name": "Company Logo", + "placeholder": "{CompanyLogo}", + "mimeType": "image", + "isGlobal": false, + "templateFolderId": "9d2b1c63-0f77-4a9c-b1d0-2c5e6f7a8b90", + "allowRichTextInjection": true, + "orgId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", + "createdBy": "f5e6d7c8-9a0b-4c1d-2e3f-4a5b6c7d8e9f", + "createdOn": "2026-05-01T14:22:10.000Z" + } + } + } +} +``` + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator, contributor, or user | Empty (status only) | +| 403 | `isGlobal: true` and the key's role is `user` (creating a knowledge-base variable requires administrator or contributor) | Empty (status only) | +| 400 | `mimeType` or `text` is missing, or both `isGlobal` and `templateFolderId` are set | `{ "message", "type": "ValidationError", "data": { "errors": [...] } }` | +| 400 | `placeholder` is not wrapped in `{ }`, or already exists in that folder or knowledge base | `{ "message", "type": "TemplateError", "data": [{ "message", "type", "data": { "explanation", "context" } }] }` | + +## Related endpoints + +- [Read Variables (Folder)](/docs/API/read-variables-folder) to list variables you have created +- [Update Variable by ID](/docs/API/update-variable-by-id) to edit a variable after creating it +- [Delete Variables (by IDs)](/docs/API/delete-variables-by-i-ds) to remove variables in bulk + diff --git a/docs/API/create-tag.api.mdx b/docs/API/create-tag.api.mdx index 5bc01bc4..0a7c590d 100644 --- a/docs/API/create-tag.api.mdx +++ b/docs/API/create-tag.api.mdx @@ -1,7 +1,7 @@ --- id: create-tag title: "Create Tag" -description: "Create Tag" +description: "Create a reusable tag in your organization to attach to templates and variables. Includes example request, response, and error handling." sidebar_label: "Create Tag" hide_title: true hide_table_of_contents: true @@ -16,9 +16,55 @@ custom_edit_url: null # Create Tag - - Create Tag - + +The Create Tag endpoint adds a new tag to your organization. Tags are a flat, organization-wide label set; once created, a tag can be attached to templates (with [Edit Template Metadata](/docs/API/edit-template-metadata)) or variables to make them easier to filter and organize. + +## When to use it + +Use this endpoint to build a tag picker that lets users create new tags on the fly, or to seed a starting set of tags when provisioning an organization. + +## Example request + +```bash +curl -X POST "https://api.turbodocx.com/Tag" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Content-Type: application/json" \ + -d '{"label": "legal"}' +``` + +## Example response + +```json +{ + "data": { + "results": { + "id": "7c1a0b52-9e88-4f0d-b3a2-1d4c6f8e2a90", + "label": "legal", + "isActive": true, + "orgId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", + "createdBy": "f5e6d7c8-9a0b-4c1d-2e3f-4a5b6c7d8e9f", + "createdOn": "2026-05-01T14:22:10.000Z", + "updatedOn": "2026-05-01T14:22:10.000Z" + } + } +} +``` + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator, contributor, or user | Empty (status only) | +| 400 | `label` is missing or not between 1 and 255 characters | `{ "message", "type": "ValidationError", "data": { "errors": [...] } }` | + +## Related endpoints + +- [Read Tag](/docs/API/read-tag) to list existing tags before creating a duplicate +- [Update Tag](/docs/API/update-tag) to rename a tag +- [Delete Tags (by IDs)](/docs/API/delete-tags-by-i-ds) to remove tags you no longer need + diff --git a/docs/API/create-webhook.api.mdx b/docs/API/create-webhook.api.mdx index 0dcec8f7..0ebb963c 100644 --- a/docs/API/create-webhook.api.mdx +++ b/docs/API/create-webhook.api.mdx @@ -1,7 +1,7 @@ --- id: create-webhook title: "Create Webhook" -description: "Register a new signature webhook for the org. The `name` field is hardcoded to `signature` by the SDK. The returned `secret` is shown **once** — store it on receipt. It cannot be retrieved later; use Regenerate Webhook Secret if lost." +description: "Register a new signature webhook for your org. The SDK always sends name=\"signature\". The returned secret is shown once; store it immediately." sidebar_label: "Create Webhook" hide_title: true hide_table_of_contents: true @@ -16,9 +16,69 @@ custom_edit_url: null # Create Webhook - - Create Webhook - + +The Create Webhook endpoint registers a webhook that TurboDocx calls when TurboSign events happen in your organization, such as a document being signed or completed. Each webhook needs a unique `name` among your org's active webhooks; every TurboDocx SDK sends `"signature"`. A second create call with that name conflicts (409) only while an active webhook already has it; if you paused a webhook via [Update Webhook](/docs/API/update-webhook)'s `isActive: false` instead of deleting it, creating a new one with the same name succeeds and leaves two rows sharing that name, and by-name lookups on the other endpoints may then hit either one. Delete the old webhook (see [Delete Webhook](/docs/API/delete-webhook)) before reusing its name, rather than just pausing it. + +## When to use it + +Use this endpoint once, during integration setup, to start receiving signature lifecycle events instead of polling the API. To change the URLs or subscribed events later, use [Update Webhook](/docs/API/update-webhook) rather than creating a new one. + +## Example request + +```bash +curl -X POST "https://api.turbodocx.com/api/webhooks" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "signature", + "urls": ["https://example.com/webhooks/turbodocx"], + "events": ["signature.document.completed", "signature.document.voided"] + }' +``` + +`urls` accepts up to 10 HTTPS endpoints (plain HTTP is rejected); `events` must be one or more of the values listed in [Get Webhook](/docs/API/get-webhook)'s `availableEvents`. Requires an API key with the administrator role. + +## Example response + +On success the endpoint returns `201 Created`: + +```json +{ + "data": { + "id": "b7e2c4a1-3f9d-4e6a-8c1b-5d0f7a2e9c34", + "orgId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", + "name": "signature", + "urls": ["https://example.com/webhooks/turbodocx"], + "events": ["signature.document.completed", "signature.document.voided"], + "secret": "whsec_REPLACE_WITH_YOUR_WEBHOOK_SECRET", + "isActive": true, + "createdBy": "f5e6d7c8-9a0b-4c1d-2e3f-4a5b6c7d8e9f", + "createdOn": "2026-05-01T14:22:10.000Z", + "updatedOn": "2026-05-01T14:22:10.000Z", + "secretExists": true + }, + "message": "Webhook created successfully. Save the secret - it won't be shown again." +} +``` + +`secret` is only ever returned in full on create and on [Regenerate Webhook Secret](/docs/API/regenerate-webhook-secret); every other endpoint returns a masked `maskedSecret` instead. Use `secret` to verify the `X-TurboDocx-Signature` header on incoming webhook calls. + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator | Empty (status only) | +| 400 | `name`, `urls`, or `events` is missing or invalid, or any URL is not HTTPS | `{ "message", "type": "ValidationError", "data": { "errors": [...] } }` | +| 409 | A webhook named `signature` already exists in your organization | `{ "message", "error": "WebhookNameTaken", "data": { "constraint", "orgId", "name" } }` | + +## Related endpoints + +- [Get Webhook](/docs/API/get-webhook) to view the webhook you created, its delivery stats, and available event types +- [Update Webhook](/docs/API/update-webhook) to change its URLs, events, or active state +- [Test Webhook](/docs/API/test-webhook) to send a sample event before going live + diff --git a/docs/API/delete-tags-by-i-ds.api.mdx b/docs/API/delete-tags-by-i-ds.api.mdx index 43bd89a9..fb608a4c 100644 --- a/docs/API/delete-tags-by-i-ds.api.mdx +++ b/docs/API/delete-tags-by-i-ds.api.mdx @@ -1,7 +1,7 @@ --- id: delete-tags-by-i-ds title: "Delete Tags (by IDs)" -description: "Delete Tags (by IDs)" +description: "Delete one or more tags from your organization in a single call, by ID. Includes example request, response, and error handling." sidebar_label: "Delete Tags (by IDs)" hide_title: true hide_table_of_contents: true @@ -16,9 +16,49 @@ custom_edit_url: null # Delete Tags (by IDs) - - Delete Tags (by IDs) - + +The Delete Tags (by IDs) endpoint deactivates one or more tags in a single call. It is a soft delete: matching tags are marked inactive rather than removed from the database, so they immediately stop appearing in [Read Tag](/docs/API/read-tag) and tag pickers. + +## When to use it + +Use this endpoint to let users bulk-remove tags they no longer need, instead of calling a single-tag delete endpoint in a loop. + +## Example request + +```bash +curl -X DELETE "https://api.turbodocx.com/Tag/Bulk/Action" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Content-Type: application/json" \ + -d '{"ids": ["7c1a0b52-9e88-4f0d-b3a2-1d4c6f8e2a90", "9d2b1c63-0f77-4a9c-b1d0-2c5e6f7a8b90"]}' +``` + +## Example response + +On success the endpoint returns `200 OK` with an empty data object: + +```json +{ + "data": {} +} +``` + +Deletion is idempotent: IDs that do not exist, or belong to another organization, are silently skipped rather than causing an error. + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator, contributor, or user | Empty (status only) | +| 400 | `ids` is missing or not an array | `{ "message", "type": "ValidationError", "data": { "errors": [...] } }` | + +## Related endpoints + +- [Read Tag](/docs/API/read-tag) to find the tag IDs to delete +- [Create Tag](/docs/API/create-tag) to add a new tag +- [Update Tag](/docs/API/update-tag) to rename a tag instead of deleting it + diff --git a/docs/API/delete-variables-by-i-ds.api.mdx b/docs/API/delete-variables-by-i-ds.api.mdx index a091066a..80a5b567 100644 --- a/docs/API/delete-variables-by-i-ds.api.mdx +++ b/docs/API/delete-variables-by-i-ds.api.mdx @@ -1,7 +1,7 @@ --- id: delete-variables-by-i-ds title: "Delete Variables (by IDs)" -description: "Delete Variables (by IDs)" +description: "Delete one or more knowledge-base or folder variables in a single call, by variableMapId. Includes example request, response, and errors." sidebar_label: "Delete Variables (by IDs)" hide_title: true hide_table_of_contents: true @@ -16,9 +16,48 @@ custom_edit_url: null # Delete Variables (by IDs) - - Delete Variables (by IDs) - + +The Delete Variables (by IDs) endpoint removes one or more variables from your knowledge base or a template folder in a single call, along with their versions, tags, and (for image variables) their stored files. + +## When to use it + +Use this endpoint to let users bulk-clean their variable library, instead of calling a single-variable delete endpoint in a loop. + +## Example request + +```bash +curl -X DELETE "https://api.turbodocx.com/Variable/Bulk/Action" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Content-Type: application/json" \ + -d '{"ids": ["e4f5a6b7-8c9d-4e0f-a1b2-3c4d5e6f7a8b"]}' +``` + +Each entry in `ids` is a `variableMapId`, the same `id` returned by [Read Variables (Folder)](/docs/API/read-variables-folder). + +## Example response + +On success the endpoint returns `200 OK` with an empty data object: + +```json +{ + "data": {} +} +``` + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator, contributor, or user | Empty (status only) | +| 400 | `ids` is missing or not an array | `{ "message", "type": "ValidationError", "data": { "errors": [...] } }` | + +## Related endpoints + +- [Read Variables (Folder)](/docs/API/read-variables-folder) to find the variable IDs to delete +- [Update Variable by ID](/docs/API/update-variable-by-id) to edit a variable instead of deleting it + diff --git a/docs/API/delete-webhook.api.mdx b/docs/API/delete-webhook.api.mdx index e65e2bec..eaa7d932 100644 --- a/docs/API/delete-webhook.api.mdx +++ b/docs/API/delete-webhook.api.mdx @@ -1,7 +1,7 @@ --- id: delete-webhook title: "Delete Webhook" -description: "Soft-delete the org's signature webhook and its delivery history." +description: "Permanently delete the org's signature webhook and its delivery history. This is a hard delete and cannot be undone." sidebar_label: "Delete Webhook" hide_title: true hide_table_of_contents: true @@ -16,9 +16,46 @@ custom_edit_url: null # Delete Webhook - - Delete Webhook - + +The Delete Webhook endpoint permanently removes a webhook and all of its delivery history. Unlike [Delete Template](/docs/API/delete-template), this is a hard delete: the webhook row and its delivery records are removed from the database, not deactivated. There is no un-delete. + +## When to use it + +Use this endpoint when you are decommissioning an integration and no longer want TurboDocx to call your endpoint. If you only want to pause delivery temporarily, use [Update Webhook](/docs/API/update-webhook) with `isActive: false` instead, so you keep the secret and delivery history. + +## Example request + +```bash +curl -X DELETE "https://api.turbodocx.com/api/webhooks/signature" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Accept: application/json" +``` + +## Example response + +On success the endpoint returns `200 OK`: + +```json +{ + "message": "Webhook deleted successfully" +} +``` + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator | Empty (status only) | +| 404 | No webhook with that name exists in your organization | `{ "error": "Webhook not found" }` | + +## Related endpoints + +- [Get Webhook](/docs/API/get-webhook) to confirm the webhook's configuration before deleting it +- [Update Webhook](/docs/API/update-webhook) to pause delivery instead of deleting +- [Create Webhook](/docs/API/create-webhook) to register a new webhook afterward + diff --git a/docs/API/edit-template-metadata.api.mdx b/docs/API/edit-template-metadata.api.mdx index 8cc73633..7bc21a55 100644 --- a/docs/API/edit-template-metadata.api.mdx +++ b/docs/API/edit-template-metadata.api.mdx @@ -1,7 +1,7 @@ --- id: edit-template-metadata title: "Edit Template Metadata" -description: "Edit Template Metadata" +description: "Rename a template, change its description or folder, or replace its tags with a single PATCH call. Includes an example request, response, and error handling." sidebar_label: "Edit Template Metadata" hide_title: true hide_table_of_contents: true @@ -16,9 +16,48 @@ custom_edit_url: null # Edit Template Metadata - - Edit Template Metadata - + +The Edit Template Metadata endpoint updates a template's name, description, folder, or tags without touching its file or variables. Send only the fields you want to change; fields you omit are left as-is. + +## When to use it + +Use this endpoint to rename a template, move it into a different folder (`templateFolderId`), or replace its tags after you have already uploaded it. To change the file itself, delete the template and upload a new one with [Upload Template with Optional Default Values](/docs/API/upload-template-with-optional-default-values). + +## Example request + +```bash +curl -X PATCH "https://api.turbodocx.com/template/2b8f1c9e-4d3a-4a7c-9f21-6b0d5e9a1c34" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "SOW Template (v2)", + "description": "Standard statement of work, updated for 2026 pricing", + "tags": [{"id": "7c1a0b52-9e88-4f0d-b3a2-1d4c6f8e2a90"}] + }' +``` + +Sending `tags` replaces the template's entire tag list: existing tags not included in the array are removed. Each entry only needs the tag's `id`, from [Create Tag](/docs/API/create-tag) or [Read Tag](/docs/API/read-tag). + +## Example response + +On success the endpoint returns `200 OK` with no response body. + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator, contributor, or user | Empty (status only) | +| 423 | The template is locked | `{ "error": "Resource is locked", "message", "data": { "locked": true, "lockedBy", "lockedOn" } }` | +| 400 | A field fails validation (for example `name` under 3 characters) | `{ "message", "type": "ValidationError", "data": { "errors": [...] } }` | + +## Related endpoints + +- [Get Template by ID](/docs/API/get-template-by-id) to see the current metadata before editing +- [Delete Template](/docs/API/delete-template) to remove a template instead of editing it +- [Get Templates and Folders](/docs/API/get-templates-and-folders) to find the `TemplateId` to edit + diff --git a/docs/API/extract-template-placeholders-and-generate-preview.api.mdx b/docs/API/extract-template-placeholders-and-generate-preview.api.mdx index a294ce21..572c7d64 100644 --- a/docs/API/extract-template-placeholders-and-generate-preview.api.mdx +++ b/docs/API/extract-template-placeholders-and-generate-preview.api.mdx @@ -1,7 +1,7 @@ --- id: extract-template-placeholders-and-generate-preview title: "Extract Template Placeholders and Generate Preview" -description: "Extract Template Placeholders and Generate Preview" +description: "Upload a DOCX or PPTX file to extract its {placeholder} variables and fonts, and optionally render a PDF preview, before creating the template." sidebar_label: "Extract Template Placeholders and Generate Preview" hide_title: true hide_table_of_contents: true @@ -16,9 +16,65 @@ custom_edit_url: null # Extract Template Placeholders and Generate Preview - - Extract Template Placeholders and Generate Preview - + +The Extract Template Placeholders and Generate Preview endpoint parses an uploaded DOCX or PPTX file and returns every `{placeholder}` variable and font it found, without creating a template. By default it also renders a PDF preview of the file and returns it inline. This lets you show a user exactly what variables a file contains, and what it looks like, before they commit to uploading it as a template. + +## When to use it + +Use this endpoint to build an "upload and preview" step ahead of [Upload Template with Optional Default Values](/docs/API/upload-template-with-optional-default-values): show the detected placeholders so the user can confirm or rename them, and show the rendered PDF so they can confirm it's the right file. Pass `skipFile=true` if you only need the extracted variables and fonts and want to skip the (slower) PDF render. + +## Example request + +```bash +curl -X POST "https://api.turbodocx.com/template/file?skipFile=true" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -F "file=@./sow-template.docx" +``` + +## Example response + +With `skipFile=true`: + +```json +{ + "data": { + "results": { + "filetype": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "vars": [ + { + "placeholder": "{CustomerName}", + "name": "CustomerName", + "mimeType": "text", + "order": 0, + "count": 1, + "allowRichTextInjection": false + } + ], + "fonts": [{ "name": "Calibri" }] + } + } +} +``` + +Without `skipFile`, the response also includes `templatePdf`, the rendered PDF of the uploaded file. It is a JSON-serialized Node.js Buffer, not a base64 string: an object of the form `{"type": "Buffer", "data": [37, 80, 68, 70, ...]}`, where `data` is an array of the PDF's raw bytes. To use it, reconstruct the binary from the byte array, for example `Buffer.from(templatePdf.data)` in Node.js or `new Uint8Array(templatePdf.data)` in the browser. Pass the `vars` array as the `variables` field (JSON-stringified) when you subsequently call [Upload Template with Optional Default Values](/docs/API/upload-template-with-optional-default-values). + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator, contributor, or user | Empty (status only) | +| 400 | No file was attached, or the file could not be uploaded ("Improper File Upload") | `{ "message", "error", "data": { "explanation", "context" } }` | +| 400 | The file type is not supported (not DOCX, PPTX, or HTML) | `{ "message": "Unsupported File Type", "error", "data": { "explanation", "context" } }` | +| 400 | Your plan's template or storage limit is reached | `{ "message", "type", "data": { "explanation", "context" } }` | +| 503 | The storage service is temporarily unavailable | `{ "message", "error", "data": { "explanation", "context" } }` | + +## Related endpoints + +- [Upload Template with Optional Default Values](/docs/API/upload-template-with-optional-default-values) to create the template from the same file +- [Get Templates and Folders](/docs/API/get-templates-and-folders) to browse existing templates + diff --git a/docs/API/get-template-by-id.api.mdx b/docs/API/get-template-by-id.api.mdx index 726c2b16..2c7871c0 100644 --- a/docs/API/get-template-by-id.api.mdx +++ b/docs/API/get-template-by-id.api.mdx @@ -1,7 +1,7 @@ --- id: get-template-by-id title: "Get Template by ID" -description: "Get Template by ID" +description: "Fetch a single template by ID: its metadata, tags, and merged variables (template, folder, and global). Includes example request, response, and error handling." sidebar_label: "Get Template by ID" hide_title: true hide_table_of_contents: true @@ -16,9 +16,78 @@ custom_edit_url: null # Get Template by ID - - Get Template by ID - + +The Get Template by ID endpoint returns a single template's full details: its metadata, creator, and the variables available to it. The variables array merges the template's own variables with any inherited from its folder and from your organization's global (knowledge base) variables, so it reflects everything the template can fill in at generation time. + +## When to use it + +Use this endpoint to load a template's details and variable list before generating a document, to check whether a template is TurboDocx-provided (and therefore read-only), or to confirm a metadata change made with [Edit Template Metadata](/docs/API/edit-template-metadata). + +## Example request + +```bash +curl "https://api.turbodocx.com/template/2b8f1c9e-4d3a-4a7c-9f21-6b0d5e9a1c34?showTags=true" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Accept: application/json" +``` + +Pass `showTags=true` to include the template's `tags` array in the response; it is omitted by default. + +## Example response + +```json +{ + "data": { + "results": { + "id": "2b8f1c9e-4d3a-4a7c-9f21-6b0d5e9a1c34", + "name": "SOW Template", + "description": "Standard statement of work", + "isActive": true, + "createdOn": "2026-05-01T14:22:10.000Z", + "updatedOn": "2026-05-01T14:22:10.000Z", + "createdBy": "f5e6d7c8-9a0b-4c1d-2e3f-4a5b6c7d8e9f", + "firstName": "Jane", + "lastName": "Doe", + "email": "jane@example.com", + "orgId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", + "templateFolderId": null, + "defaultFont": "Calibri", + "fonts": [{ "name": "Calibri" }], + "metadata": {}, + "templateFileType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "isTurboDocxProvided": false, + "deliverableCount": 12, + "variables": [ + { + "placeholder": "{CustomerName}", + "name": "CustomerName", + "mimeType": "text", + "order": 0, + "count": 1 + } + ] + } + } +} +``` + +`isTurboDocxProvided` is `true` for templates from the built-in TurboDocx library; those cannot be edited in place and must be downloaded and re-uploaded to customize. Each entry in `variables` mirrors the variable fields returned by generation, with `isTemplateFolder` set on variables inherited from the template's folder. + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 404 | No active template with that ID exists in your organization | Empty (status only) | +| 400 | The `TemplateID` path parameter is not a valid UUID | `{ "message", "type": "ValidationError", "data": { "errors": [...] } }` | + +## Related endpoints + +- [Get Templates and Folders](/docs/API/get-templates-and-folders) to list templates and find a `TemplateId` +- [Edit Template Metadata](/docs/API/edit-template-metadata) to rename, retag, or move this template +- [Delete Template](/docs/API/delete-template) to remove this template + diff --git a/docs/API/get-webhook-stats.api.mdx b/docs/API/get-webhook-stats.api.mdx index 0190dfae..3f8fd4d0 100644 --- a/docs/API/get-webhook-stats.api.mdx +++ b/docs/API/get-webhook-stats.api.mdx @@ -1,7 +1,7 @@ --- id: get-webhook-stats title: "Get Webhook Stats" -description: "Retrieve aggregate delivery statistics for the org's signature webhook over a sliding time window. Returns per-event breakdown, success rates, average response times, and last delivery timestamps." +description: "Aggregate delivery statistics for the org's signature webhook over a custom time window: per-event breakdown, success rate, response time." sidebar_label: "Get Webhook Stats" hide_title: true hide_table_of_contents: true @@ -16,9 +16,74 @@ custom_edit_url: null # Get Webhook Stats - - Get Webhook Stats - + +The Get Webhook Stats endpoint returns delivery statistics for this specific webhook over a time window you choose, broken down by event type. Unlike the `deliveryStats` on [Get Webhook](/docs/API/get-webhook) (which cover your whole organization's last 30 days), this endpoint is scoped to one webhook and lets you pick the window. + +## When to use it + +Use this endpoint to build a delivery health dashboard for a single webhook: overall success rate, average response time, and which event types are failing most, over a period you control. + +## Example request + +```bash +curl "https://api.turbodocx.com/api/webhooks/signature/stats?days=7" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Accept: application/json" +``` + +`days` defaults to `30` and accepts 1 to 365. + +## Example response + +```json +{ + "data": { + "webhook": { + "id": "b7e2c4a1-3f9d-4e6a-8c1b-5d0f7a2e9c34", + "name": "signature", + "isActive": true, + "events": ["signature.document.completed", "signature.document.voided"], + "urls": ["https://example.com/webhooks/turbodocx"] + }, + "period": { "days": 7, "from": "2026-04-25T00:00:00.000Z", "to": "2026-05-02T00:00:00.000Z" }, + "summary": { + "totalDeliveries": 42, + "successfulDeliveries": 40, + "failedDeliveries": 1, + "pendingRetries": 1, + "successRate": 95.24, + "avgResponseTime": 184, + "lastSuccessfulDelivery": "2026-05-01T22:10:05.000Z", + "lastFailedDelivery": "2026-04-29T11:02:41.000Z" + }, + "eventBreakdown": [ + { + "eventType": "signature.document.completed", + "total": 30, + "successful": 29, + "failed": 1, + "successRate": 96.67 + } + ] + } +} +``` + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator | Empty (status only) | +| 404 | No webhook with that name exists in your organization | `{ "error": "Webhook not found" }` | +| 400 | `days` is outside 1 to 365 | Validation error from the query schema | + +## Related endpoints + +- [Get Webhook](/docs/API/get-webhook) for the webhook's current configuration +- [List Webhook Deliveries](/docs/API/list-webhook-deliveries) to inspect individual delivery attempts behind these numbers + diff --git a/docs/API/get-webhook.api.mdx b/docs/API/get-webhook.api.mdx index f763efa2..b5bef807 100644 --- a/docs/API/get-webhook.api.mdx +++ b/docs/API/get-webhook.api.mdx @@ -16,9 +16,75 @@ custom_edit_url: null # Get Webhook - - Get Webhook - + +The Get Webhook endpoint returns a webhook's current configuration (URLs, subscribed events, active state), its secret status, delivery statistics for your organization, and the full list of event types you can subscribe to. + +## When to use it + +Use this endpoint to display a webhook's settings in your own dashboard, to check whether it is active before troubleshooting missing events, or to read `availableEvents` so you can build an event-picker UI without hardcoding the list. + +## Example request + +```bash +curl "https://api.turbodocx.com/api/webhooks/signature" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Accept: application/json" +``` + +`signature` is the webhook's `name`, not its `id`; every TurboDocx SDK-created webhook uses that name. + +## Example response + +```json +{ + "data": { + "id": "b7e2c4a1-3f9d-4e6a-8c1b-5d0f7a2e9c34", + "orgId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", + "name": "signature", + "urls": ["https://example.com/webhooks/turbodocx"], + "events": ["signature.document.completed", "signature.document.voided"], + "isActive": true, + "createdBy": "f5e6d7c8-9a0b-4c1d-2e3f-4a5b6c7d8e9f", + "createdOn": "2026-05-01T14:22:10.000Z", + "updatedOn": "2026-05-01T14:22:10.000Z", + "secretExists": true, + "maskedSecret": "whs***7f8", + "deliveryStats": { + "totalDeliveries": 214, + "successfulDeliveries": 209, + "failedDeliveries": 3, + "pendingRetries": 2 + }, + "availableEvents": [ + "signature.document.sent", + "signature.document.viewed", + "signature.document.signed", + "signature.document.recipient_signed", + "signature.document.completed", + "signature.document.finalization_failed", + "signature.document.voided" + ] + } +} +``` + +`deliveryStats` covers all webhook deliveries across your organization over the last 30 days, not only this webhook's. For per-delivery detail, or stats scoped to a custom time window, use [Get Webhook Stats](/docs/API/get-webhook-stats). + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator | Empty (status only) | +| 404 | No webhook with that name exists in your organization | `{ "error": "Webhook not found" }` | + +## Related endpoints + +- [Update Webhook](/docs/API/update-webhook) to change its URLs, events, or active state +- [Get Webhook Stats](/docs/API/get-webhook-stats) for delivery stats scoped to this webhook over a custom period +- [List Webhook Deliveries](/docs/API/list-webhook-deliveries) to inspect individual delivery attempts + diff --git a/docs/API/list-webhook-deliveries.api.mdx b/docs/API/list-webhook-deliveries.api.mdx index b4f583b7..92e44b8f 100644 --- a/docs/API/list-webhook-deliveries.api.mdx +++ b/docs/API/list-webhook-deliveries.api.mdx @@ -16,9 +16,72 @@ custom_edit_url: null # List Webhook Deliveries - - List Webhook Deliveries - + +The List Webhook Deliveries endpoint returns the individual delivery attempts made to your signature webhook's URLs, newest first, with each attempt's status, HTTP response code, and retry count. + +## When to use it + +Use this endpoint to build a delivery log for debugging: find which attempts failed, filter to a specific event type, or locate a delivery's `id` to pass to [Replay Webhook Delivery](/docs/API/replay-webhook-delivery). + +## Example request + +```bash +curl "https://api.turbodocx.com/api/webhooks/signature/deliveries?limit=20&offset=0&isDelivered=false" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Accept: application/json" +``` + +Supported filters: `eventType`, `isDelivered` (`true`/`false`), and `httpStatus` (an exact status code). `limit` defaults to `20`, `offset` to `0`. + +> **Known limitation:** `isDelivered=true` and `httpStatus` do not currently filter results correctly due to a backend issue: `isDelivered=true` returns the same (undelivered-only) results as `isDelivered=false`, and `httpStatus` is ignored entirely regardless of value. Only `isDelivered=false` behaves as documented today. + +## Example response + +```json +{ + "data": { + "results": [ + { + "id": "d3a1c2b4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", + "eventType": "signature.document.completed", + "url": "https://example.com/webhooks/turbodocx", + "httpStatus": 502, + "responseBody": "Bad Gateway", + "attemptCount": 2, + "maxAttempts": 3, + "isDelivered": false, + "deliveredAt": null, + "nextRetryAt": "2026-05-02T09:15:00.000Z", + "errorMessage": "Request failed with status code 502", + "status": "retrying", + "createdOn": "2026-05-02T09:05:00.000Z", + "updatedOn": "2026-05-02T09:10:00.000Z" + } + ], + "totalRecords": 1, + "limit": 20, + "offset": 0 + } +} +``` + +`status` summarizes the row as `"delivered"`, `"failed"` (all `maxAttempts` attempts exhausted), `"retrying"`, or `"pending"`. Failed deliveries retry automatically with backoff (immediate, then +1 minute, then +5 minutes) for up to `maxAttempts` (3) attempts total before landing in the dead-letter state. + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator | Empty (status only) | +| 404 | No webhook with that name exists in your organization | `{ "error": "Webhook not found" }` | + +## Related endpoints + +- [Replay Webhook Delivery](/docs/API/replay-webhook-delivery) to manually retry a delivery from this list +- [Get Webhook Stats](/docs/API/get-webhook-stats) for aggregate numbers instead of individual deliveries +- [Test Webhook](/docs/API/test-webhook) to generate a fresh delivery on demand + diff --git a/docs/API/notify-webhook.api.mdx b/docs/API/notify-webhook.api.mdx index d9c9a8ce..aa8988f3 100644 --- a/docs/API/notify-webhook.api.mdx +++ b/docs/API/notify-webhook.api.mdx @@ -1,7 +1,7 @@ --- id: notify-webhook title: "Notify Webhook" -description: "Send a manual notification to all URLs configured on the org's signature webhook. Routes through the same backend handler as Test Webhook; use Test Webhook in new code. Both are exposed for API surface symmetry." +description: "Send a manual notification to all URLs on the org's signature webhook. Same backend handler as Test Webhook; kept for API surface symmetry." sidebar_label: "Notify Webhook" hide_title: true hide_table_of_contents: true @@ -16,9 +16,66 @@ custom_edit_url: null # Notify Webhook - - Notify Webhook - + +The Notify Webhook endpoint sends a one-off event delivery to every URL configured on your signature webhook. It calls the exact same backend logic as [Test Webhook](/docs/API/test-webhook): both accept the same body and return the same response shape. This endpoint exists for API surface symmetry with the "notify" naming some integrations expect; new integrations should call Test Webhook instead. + +## When to use it + +Use this endpoint (or Test Webhook) to confirm your receiving endpoint handles a TurboSign event correctly, without waiting for a real document to reach that state. + +## Example request + +```bash +curl -X POST "https://api.turbodocx.com/api/webhooks/signature/notify" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Content-Type: application/json" \ + -d '{ + "eventType": "signature.document.completed", + "payload": {"documentId": "doc_abc123", "status": "completed"} + }' +``` + +Both `eventType` and `payload` are optional; omit them to send a default sample payload for a default event type. + +## Example response + +```json +{ + "data": { + "deliveries": [ + { + "id": "d3a1c2b4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", + "eventType": "signature.document.completed", + "url": "https://example.com/webhooks/turbodocx", + "httpStatus": 200, + "attemptCount": 1, + "maxAttempts": 3, + "isDelivered": true, + "status": "delivered" + } + ], + "summary": { "total": 1, "successful": 1, "failed": 0, "errors": [] } + }, + "message": "Manual notification sent successfully to all URLs" +} +``` + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator | Empty (status only) | +| 404 | No webhook with that name exists in your organization | `{ "error": "Webhook not found" }` | +| 400 | The webhook exists but `isActive` is `false` | `{ "error": "Cannot send notification to inactive webhook" }` | + +## Related endpoints + +- [Test Webhook](/docs/API/test-webhook) for the same behavior under TurboDocx's documented name +- [List Webhook Deliveries](/docs/API/list-webhook-deliveries) to review past delivery attempts +- [Get Webhook](/docs/API/get-webhook) to check the webhook's configuration first + diff --git a/docs/API/read-tag.api.mdx b/docs/API/read-tag.api.mdx index b03b62cc..4c487758 100644 --- a/docs/API/read-tag.api.mdx +++ b/docs/API/read-tag.api.mdx @@ -1,7 +1,7 @@ --- id: read-tag title: "Read Tag" -description: "Read Tag" +description: "List the tags in your organization, with search and sorting. Includes example request, response, and error handling." sidebar_label: "Read Tag" hide_title: true hide_table_of_contents: true @@ -16,9 +16,59 @@ custom_edit_url: null # Read Tag - - Read Tag - + +The Read Tag endpoint lists the active tags in your organization, sorted alphabetically by `label` by default. Despite the singular name, it returns a paginated array, not a single tag. To fetch one tag by its ID, use `GET /Tag/:id`, which returns a single tag object under `data.results` (404 if not found). + +## When to use it + +Use this endpoint to populate a tag picker or filter dropdown, or to search for an existing tag by name before deciding whether to create a new one with [Create Tag](/docs/API/create-tag). + +## Example request + +```bash +curl "https://api.turbodocx.com/Tag?limit=25&offset=0&query=legal" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Accept: application/json" +``` + +`limit` defaults to `6`, `offset` to `0`. `query` filters by a case-insensitive match on `label`. Sort with `column0` (`label`, `createdOn`, or `updatedOn`) and `order0` (`asc` or `desc`). + +## Example response + +```json +{ + "data": { + "results": [ + { + "id": "7c1a0b52-9e88-4f0d-b3a2-1d4c6f8e2a90", + "label": "legal", + "isActive": true, + "orgId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", + "createdBy": "f5e6d7c8-9a0b-4c1d-2e3f-4a5b6c7d8e9f", + "createdOn": "2026-05-01T14:22:10.000Z", + "updatedOn": "2026-05-01T14:22:10.000Z" + } + ], + "totalRecords": 1 + } +} +``` + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 400 | A query parameter fails validation | `{ "message", "type": "ValidationError", "data": { "errors": [...] } }` | + +## Related endpoints + +- [Create Tag](/docs/API/create-tag) to add a new tag +- [Update Tag](/docs/API/update-tag) to rename an existing tag +- [Delete Tags (by IDs)](/docs/API/delete-tags-by-i-ds) to remove tags in bulk +- `GET /Tag/:id` to fetch a single tag by ID + diff --git a/docs/API/read-variables-folder.api.mdx b/docs/API/read-variables-folder.api.mdx index 93cb9e35..2429601b 100644 --- a/docs/API/read-variables-folder.api.mdx +++ b/docs/API/read-variables-folder.api.mdx @@ -1,7 +1,7 @@ --- id: read-variables-folder title: "Read Variables (Folder)" -description: "Read Variables (Folder)" +description: "List the variables in your knowledge base or a template folder, with search, tags, and pagination. Includes example request and response." sidebar_label: "Read Variables (Folder)" hide_title: true hide_table_of_contents: true @@ -16,9 +16,65 @@ custom_edit_url: null # Read Variables (Folder) - - Read Variables (Folder) - + +The Read Variables (Folder) endpoint lists reusable variables scoped to your organization's global knowledge base or to a specific template folder. These are standalone variables you manage independently of any one template, for reuse across many templates (for example a company address or a standard clause). + +## When to use it + +Use this endpoint to build a variable library browser, or to look up a variable's `id` before updating it with [Update Variable by ID](/docs/API/update-variable-by-id) or deleting it with [Delete Variables (by IDs)](/docs/API/delete-variables-by-i-ds). + +## Example request + +```bash +curl "https://api.turbodocx.com/Variable?isGlobal=true&limit=25&offset=0&showTags=true" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Accept: application/json" +``` + +Optionally pass `isGlobal=true` (your org-wide knowledge base) or `templateFolderId=` (a specific folder) to scope the list; at most one may be set, and passing both is rejected. Omit both to list across your accessible scope. `limit` defaults to `6`, `offset` to `0`, and `query` filters by name. + +## Example response + +```json +{ + "data": { + "results": [ + { + "id": "e4f5a6b7-8c9d-4e0f-a1b2-3c4d5e6f7a8b", + "variableMapId": "e4f5a6b7-8c9d-4e0f-a1b2-3c4d5e6f7a8b", + "name": "Company Address", + "placeholder": "{CompanyAddress}", + "description": "Standard mailing address block", + "mimeType": "text", + "text": "123 Main St, Suite 400, Austin, TX 78701", + "isGlobal": true, + "templateFolderId": null, + "allowRichTextInjection": false, + "createdBy": "f5e6d7c8-9a0b-4c1d-2e3f-4a5b6c7d8e9f", + "updatedOn": "2026-05-01T14:22:10.000Z" + } + ], + "totalRecords": 1 + } +} +``` + +An image variable's `text` holds a `data:` URI rather than plain text. + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 400 | Both `isGlobal` and `templateFolderId` are set, or a query parameter fails validation | `{ "message", "type": "ValidationError", "data": { "errors": [...] } }` | + +## Related endpoints + +- [Update Variable by ID](/docs/API/update-variable-by-id) to change a variable found here +- [Delete Variables (by IDs)](/docs/API/delete-variables-by-i-ds) to remove variables in bulk +- [Get Template by ID](/docs/API/get-template-by-id) to see how folder and global variables merge into a template + diff --git a/docs/API/regenerate-webhook-secret.api.mdx b/docs/API/regenerate-webhook-secret.api.mdx index ada4d07e..8e448c0c 100644 --- a/docs/API/regenerate-webhook-secret.api.mdx +++ b/docs/API/regenerate-webhook-secret.api.mdx @@ -1,7 +1,7 @@ --- id: regenerate-webhook-secret title: "Regenerate Webhook Secret" -description: "Rotate the org's signature webhook HMAC secret. The new secret is returned **once** — store it immediately. Old HMAC signatures will fail as soon as this call succeeds." +description: "Rotate the org's signature webhook HMAC secret. The new secret is returned once; store it immediately, since old signatures stop working right away." sidebar_label: "Regenerate Webhook Secret" hide_title: true hide_table_of_contents: true @@ -16,9 +16,51 @@ custom_edit_url: null # Regenerate Webhook Secret - - Regenerate Webhook Secret - + +The Regenerate Webhook Secret endpoint issues a new HMAC secret for your signature webhook and immediately replaces the old one. Use the returned secret to verify the `X-TurboDocx-Signature` header on incoming webhook calls. + +## When to use it + +Use this endpoint if the current secret may have leaked, or as part of a routine credential rotation. Because the change takes effect immediately, update your webhook receiver's stored secret before or right after calling this endpoint; deliveries signed with the old secret will fail verification on your side as soon as it rotates. + +## Example request + +```bash +curl -X POST "https://api.turbodocx.com/api/webhooks/signature/regenerate" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Accept: application/json" +``` + +## Example response + +```json +{ + "data": { + "id": "b7e2c4a1-3f9d-4e6a-8c1b-5d0f7a2e9c34", + "secret": "whsec_REPLACE_WITH_YOUR_WEBHOOK_SECRET", + "regeneratedAt": "2026-05-02T09:20:00.000Z" + }, + "message": "Webhook secret regenerated successfully. Save the new secret - it won't be shown again." +} +``` + +The full `secret` is only returned here and on [Create Webhook](/docs/API/create-webhook); [Get Webhook](/docs/API/get-webhook) only ever returns a masked `maskedSecret`. + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator | Empty (status only) | +| 404 | No webhook with that name exists in your organization | `{ "error": "Webhook not found" }` | + +## Related endpoints + +- [Get Webhook](/docs/API/get-webhook) to confirm the secret was rotated (`maskedSecret` changes) +- [Update Webhook](/docs/API/update-webhook) to change URLs or events without rotating the secret +- [Test Webhook](/docs/API/test-webhook) to confirm your receiver validates the new secret correctly + diff --git a/docs/API/replay-webhook-delivery.api.mdx b/docs/API/replay-webhook-delivery.api.mdx index c847a789..174fb9cb 100644 --- a/docs/API/replay-webhook-delivery.api.mdx +++ b/docs/API/replay-webhook-delivery.api.mdx @@ -1,7 +1,7 @@ --- id: replay-webhook-delivery title: "Replay Webhook Delivery" -description: "Manually retry a specific past delivery by its ID. Creates a new delivery row and immediately attempts re-delivery to all configured URLs. Returns the full delivery object for the new attempt." +description: "Manually retry one past delivery by its ID. Creates a new delivery row and immediately re-sends the event to the URL the original delivery targeted." sidebar_label: "Replay Webhook Delivery" hide_title: true hide_table_of_contents: true @@ -16,9 +16,63 @@ custom_edit_url: null # Replay Webhook Delivery - - Replay Webhook Delivery - + +The Replay Webhook Delivery endpoint manually retries a specific past delivery, identified by its `deliveryId`. It creates a brand-new delivery row for the attempt (the original row is left as-is) and immediately re-sends the event to the URL the original delivery was made to (not every URL configured on the webhook, if it has more than one). + +## When to use it + +Use this endpoint to retry a delivery that permanently failed (exhausted its automatic retries) after you have fixed whatever was wrong with your receiving endpoint, instead of waiting for the same event to occur again. + +## Example request + +```bash +curl -X POST "https://api.turbodocx.com/api/webhooks/signature/replay" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Content-Type: application/json" \ + -d '{"deliveryId": "d3a1c2b4-5e6f-4a7b-8c9d-0e1f2a3b4c5d"}' +``` + +Get `deliveryId` from [List Webhook Deliveries](/docs/API/list-webhook-deliveries). + +## Example response + +On success the endpoint returns `200 OK` with the new delivery: + +```json +{ + "data": { + "id": "f2e1d0c9-8b7a-4695-a3b2-1c0d9e8f7a6b", + "eventType": "signature.document.completed", + "url": "https://example.com/webhooks/turbodocx", + "attemptCount": 0, + "maxAttempts": 3, + "isDelivered": false, + "status": "pending", + "createdOn": "2026-05-02T09:30:00.000Z", + "updatedOn": "2026-05-02T09:30:00.000Z" + }, + "message": "Webhook delivery replayed successfully - new delivery attempt created" +} +``` + +Check the new delivery's status afterward with [List Webhook Deliveries](/docs/API/list-webhook-deliveries). + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator | Empty (status only) | +| 404 | No webhook with that name exists, or `deliveryId` does not belong to it | `{ "error": "Webhook or delivery not found" }` | +| 400 | `deliveryId` is missing or not a valid UUID | Validation error from the body schema | + +## Related endpoints + +- [List Webhook Deliveries](/docs/API/list-webhook-deliveries) to find failed deliveries to replay +- [Test Webhook](/docs/API/test-webhook) to send a fresh sample event instead of replaying a past one +- [Get Webhook Stats](/docs/API/get-webhook-stats) to see whether replays are improving your success rate + diff --git a/docs/API/test-webhook.api.mdx b/docs/API/test-webhook.api.mdx index 004ab813..33f2d197 100644 --- a/docs/API/test-webhook.api.mdx +++ b/docs/API/test-webhook.api.mdx @@ -16,9 +16,68 @@ custom_edit_url: null # Test Webhook - - Test Webhook - + +The Test Webhook endpoint sends a sample event delivery to every URL configured on your signature webhook and returns a per-URL summary of the result. It creates a real delivery record, identical to a delivery triggered by an actual TurboSign event, so it also shows up in [List Webhook Deliveries](/docs/API/list-webhook-deliveries). + +## When to use it + +Use this endpoint right after creating or updating a webhook to confirm your receiving endpoint is reachable and returns a 2xx response, before relying on it for real signature events. + +## Example request + +```bash +curl -X POST "https://api.turbodocx.com/api/webhooks/signature/test" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Content-Type: application/json" \ + -d '{ + "eventType": "signature.document.completed", + "payload": {"documentId": "doc_abc123", "status": "completed"} + }' +``` + +Both `eventType` and `payload` are optional; omit them to send a default sample payload for a default event type. + +## Example response + +```json +{ + "data": { + "deliveries": [ + { + "id": "d3a1c2b4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", + "eventType": "signature.document.completed", + "url": "https://example.com/webhooks/turbodocx", + "httpStatus": 200, + "attemptCount": 1, + "maxAttempts": 3, + "isDelivered": true, + "status": "delivered" + } + ], + "summary": { "total": 1, "successful": 1, "failed": 0, "errors": [] } + }, + "message": "Test webhook sent successfully to all URLs" +} +``` + +If a URL returns a non-2xx status or times out, its entry has `isDelivered: false` and `status: "retrying"` (while attempts remain) or `"failed"` (once all attempts are exhausted), with details in `errorMessage`. `summary.failed`/`summary.errors` do not currently reflect HTTP-level failures; they only count a database error while creating the delivery record, so a URL that returns 4xx/5xx or times out through all attempts still increments `summary.successful` and leaves `summary.errors` empty. Inspect each `deliveries[]` entry's `isDelivered`, `status`, and `errorMessage` to detect a failing receiver rather than relying on `summary.failed`. + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator | Empty (status only) | +| 404 | No webhook with that name exists in your organization | `{ "error": "Webhook not found" }` | +| 400 | The webhook exists but `isActive` is `false` | `{ "error": "Cannot test inactive webhook" }` | + +## Related endpoints + +- [Get Webhook](/docs/API/get-webhook) to confirm the webhook's URLs and events before testing +- [List Webhook Deliveries](/docs/API/list-webhook-deliveries) to review this and past delivery attempts +- [Replay Webhook Delivery](/docs/API/replay-webhook-delivery) to retry a specific failed delivery + diff --git a/docs/API/update-tag.api.mdx b/docs/API/update-tag.api.mdx index 2ef7f7bb..68295186 100644 --- a/docs/API/update-tag.api.mdx +++ b/docs/API/update-tag.api.mdx @@ -1,7 +1,7 @@ --- id: update-tag title: "Update Tag" -description: "Update Tag" +description: "Rename an existing tag by ID. Includes example request, response, and error handling." sidebar_label: "Update Tag" hide_title: true hide_table_of_contents: true @@ -16,9 +16,53 @@ custom_edit_url: null # Update Tag - - Update Tag - + +The Update Tag endpoint changes a tag's `label`. It is a `PUT`, but in practice `label` is the only field you should send. `orgId` is not an accepted body field and returns a validation error if sent. `id` is different: it isn't rejected by validation, and it isn't ignored either; the endpoint applies whatever body you send, so an `id` that differs from the `TagId` in the URL will overwrite the tag's actual `id` instead of being discarded. Omit `id` from the body and let the URL path segment identify the tag to update. + +## When to use it + +Use this endpoint to rename a tag across your organization; every template or variable already tagged with it keeps the same tag `id`, so the rename applies everywhere the tag is used. + +## Example request + +```bash +curl -X PUT "https://api.turbodocx.com/Tag/7c1a0b52-9e88-4f0d-b3a2-1d4c6f8e2a90" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Content-Type: application/json" \ + -d '{"label": "legal-2026"}' +``` + +## Example response + +On success the endpoint returns `200 OK` with the updated tag object directly (not wrapped in a `data` envelope, unlike most other TurboDocx endpoints): + +```json +{ + "id": "7c1a0b52-9e88-4f0d-b3a2-1d4c6f8e2a90", + "label": "legal-2026", + "isActive": true, + "orgId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", + "createdBy": "f5e6d7c8-9a0b-4c1d-2e3f-4a5b6c7d8e9f", + "createdOn": "2026-05-01T14:22:10.000Z", + "updatedOn": "2026-05-02T09:00:00.000Z" +} +``` + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator, contributor, or user | Empty (status only) | +| 400 | `TagId` is not a valid UUID, or `label` fails validation | `{ "message", "type": "ValidationError", "data": { "errors": [...] } }` | + +## Related endpoints + +- [Read Tag](/docs/API/read-tag) to find the `TagId` to update +- [Create Tag](/docs/API/create-tag) to add a new tag instead +- [Delete Tags (by IDs)](/docs/API/delete-tags-by-i-ds) to remove tags in bulk + diff --git a/docs/API/update-variable-by-id.api.mdx b/docs/API/update-variable-by-id.api.mdx index 217e2f9e..5b786f98 100644 --- a/docs/API/update-variable-by-id.api.mdx +++ b/docs/API/update-variable-by-id.api.mdx @@ -1,7 +1,7 @@ --- id: update-variable-by-id title: "Update Variable (by ID)" -description: "Update Variable (by ID)" +description: "Update a knowledge-base or folder variable's name, content, or tags by ID. Includes example request, response, and error handling." sidebar_label: "Update Variable (by ID)" hide_title: true hide_table_of_contents: true @@ -16,9 +16,66 @@ custom_edit_url: null # Update Variable (by ID) - - Update Variable (by ID) - + +The Update Variable (by ID) endpoint replaces a knowledge-base or template-folder variable's content and metadata. Unlike [Edit Template Metadata](/docs/API/edit-template-metadata), this is a full replace, not a partial patch: `mimeType` and `text` are required on every call. `isGlobal` and `templateFolderId` are both optional; at most one may be set. + +## When to use it + +Use this endpoint to edit a reusable variable you found with [Read Variables (Folder)](/docs/API/read-variables-folder), for example correcting its text, changing its name, or replacing its tag list. + +## Example request + +```bash +curl -X PUT "https://api.turbodocx.com/Variable/e4f5a6b7-8c9d-4e0f-a1b2-3c4d5e6f7a8b" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Company Address", + "placeholder": "{CompanyAddress}", + "mimeType": "text", + "text": "123 Main St, Suite 400, Austin, TX 78701", + "allowRichTextInjection": true, + "isGlobal": true, + "tags": [] + }' +``` + +`{VariableId}` in the path is the `variableMapId` returned by [Read Variables (Folder)](/docs/API/read-variables-folder), not the underlying `Variable.id`. Optionally send `isGlobal: true` or `templateFolderId`, but not both; sending both is rejected. For an image variable, set `mimeType` to `"image"` and `text` to a base64 data string. + +## Example response + +On success the endpoint returns `200 OK` with the updated variable wrapped in a `variable` key (not the `data` envelope most other TurboDocx endpoints use): + +```json +{ + "variable": { + "id": "e4f5a6b7-8c9d-4e0f-a1b2-3c4d5e6f7a8b", + "name": "Company Address", + "placeholder": "{CompanyAddress}", + "mimeType": "text", + "text": "123 Main St, Suite 400, Austin, TX 78701", + "isGlobal": true, + "templateFolderId": null, + "updatedOn": "2026-05-02T09:00:00.000Z" + } +} +``` + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator, contributor, or user. For `isGlobal: true` updates (as in the example above), only administrator and contributor are allowed; the `user` role is also rejected with `403`. | Empty (status only) | +| 400 | `mimeType` or `text` is missing, or both `isGlobal` and `templateFolderId` are set | `{ "message", "type": "ValidationError", "data": { "errors": [...] } }` | +| 409 | The variable was deleted or modified by someone else before this update landed | `{ "error", "data": { "explanation" } }` | + +## Related endpoints + +- [Read Variables (Folder)](/docs/API/read-variables-folder) to find the `variableMapId` to update +- [Delete Variables (by IDs)](/docs/API/delete-variables-by-i-ds) to remove variables instead of editing them + diff --git a/docs/API/update-webhook.api.mdx b/docs/API/update-webhook.api.mdx index 6577d596..69b9731b 100644 --- a/docs/API/update-webhook.api.mdx +++ b/docs/API/update-webhook.api.mdx @@ -1,7 +1,7 @@ --- id: update-webhook title: "Update Webhook" -description: "Patch one or more fields on the org's signature webhook. All fields are optional — supply only what you want to change." +description: "Patch one or more fields on the org's signature webhook, changing only what you send: name, URLs, events, or active state." sidebar_label: "Update Webhook" hide_title: true hide_table_of_contents: true @@ -16,9 +16,68 @@ custom_edit_url: null # Update Webhook - - Update Webhook - + +The Update Webhook endpoint changes a webhook's URLs, subscribed events, name, or active state. Every field is optional; send only what you want to change, and the rest is left untouched. + +## When to use it + +Use this endpoint to rotate delivery URLs, add or remove subscribed event types, or temporarily pause delivery by setting `isActive` to `false` without deleting the webhook and losing its secret and delivery history. + +## Example request + +```bash +curl -X PATCH "https://api.turbodocx.com/api/webhooks/signature" \ + -H "Authorization: Bearer $TURBODOCX_API_KEY" \ + -H "x-rapiddocx-org-id: $TURBODOCX_ORG_ID" \ + -H "Content-Type: application/json" \ + -d '{ + "urls": ["https://example.com/webhooks/turbodocx"], + "events": ["signature.document.completed"], + "isActive": true + }' +``` + +`urls` and `events` each replace the webhook's full list, they do not merge with the existing values. If you include `name`, it must still be unique among your organization's active webhooks. + +## Example response + +On success the endpoint returns `200 OK` with the updated webhook, in the same shape as [Get Webhook](/docs/API/get-webhook) (without `deliveryStats` or `availableEvents`): + +```json +{ + "data": { + "id": "b7e2c4a1-3f9d-4e6a-8c1b-5d0f7a2e9c34", + "orgId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", + "name": "signature", + "urls": ["https://example.com/webhooks/turbodocx"], + "events": ["signature.document.completed"], + "isActive": true, + "createdBy": "f5e6d7c8-9a0b-4c1d-2e3f-4a5b6c7d8e9f", + "createdOn": "2026-05-01T14:22:10.000Z", + "updatedOn": "2026-05-02T09:10:00.000Z", + "secretExists": true, + "maskedSecret": "whs***7f8" + }, + "message": "Webhook updated successfully" +} +``` + +## Common errors + +| Status | When | Response body | +| ------ | ---- | ------------- | +| 401 | Missing or invalid API key/token, or the organization cannot be resolved | Empty (status only) | +| 403 | The key's role is not administrator | Empty (status only) | +| 404 | No webhook with that name exists in your organization | `{ "error": "Webhook not found" }` | +| 400 | A field fails validation, or a URL in `urls` is not HTTPS | `{ "message", "type": "ValidationError", "data": { "errors": [...] } }` | +| 409 | Renaming to a name another active webhook already uses | `{ "message", "error": "WebhookNameTaken", "data": { "constraint", "orgId", "name" } }` | + +## Related endpoints + +- [Get Webhook](/docs/API/get-webhook) to view the current configuration before editing +- [Regenerate Webhook Secret](/docs/API/regenerate-webhook-secret) to rotate the signing secret without changing anything else +- [Delete Webhook](/docs/API/delete-webhook) to remove the webhook entirely + diff --git a/docs/Integrations/ConnectWise PSA.md b/docs/Integrations/ConnectWise PSA.md index 0b0d429f..75fbc37d 100644 --- a/docs/Integrations/ConnectWise PSA.md +++ b/docs/Integrations/ConnectWise PSA.md @@ -2,7 +2,7 @@ title: ConnectWise PSA Integration sidebar\_position: 6 -description: Automatically generate proposals, contracts, service reports, and presentations from ConnectWise PSA data. Turn companies, contacts, and opportunities into professional documents with AI-powered automation. +description: Generate proposals, contracts, and service reports from ConnectWise PSA. Automate documents from companies, contacts, and opportunities. keywords: - connectwise psa document automation diff --git a/docs/Integrations/Fireflies.md b/docs/Integrations/Fireflies.md index 046ad4a8..ba54e312 100644 --- a/docs/Integrations/Fireflies.md +++ b/docs/Integrations/Fireflies.md @@ -1,7 +1,7 @@ --- title: Fireflies AI Integration sidebar_position: 7 -description: Transform Fireflies AI meeting transcripts into professional documents and presentations. Coming soon - AI-powered meeting documentation and automated workflow integration. +description: Transform Fireflies AI meeting transcripts into professional documents and presentations with AI-powered automation and workflow integration. keywords: - fireflies ai integration - fireflies meeting documentation diff --git a/docs/Integrations/Hubspot.md b/docs/Integrations/Hubspot.md index f2281200..ed93dbb9 100644 --- a/docs/Integrations/Hubspot.md +++ b/docs/Integrations/Hubspot.md @@ -1,7 +1,7 @@ --- title: HubSpot Integration sidebar_position: 4 -description: Transform your HubSpot data into professional documents, proposals, and presentations with TurboDocx. Create personalized deliverables using your real customer data — powered by AI. +description: Transform HubSpot data into professional documents, proposals, and presentations. Create personalized deliverables powered by AI. keywords: - hubspot integration - crm documents diff --git a/docs/Integrations/OneDrive and SharePoint.md b/docs/Integrations/OneDrive and SharePoint.md index fcd5aa1f..3039cf30 100644 --- a/docs/Integrations/OneDrive and SharePoint.md +++ b/docs/Integrations/OneDrive and SharePoint.md @@ -1,7 +1,7 @@ --- title: OneDrive and SharePoint Integration sidebar_position: 3 -description: Import templates and export documents seamlessly with OneDrive and SharePoint. Configure Azure AD integration for secure document management and cloud storage automation. +description: Import templates and export documents with OneDrive and SharePoint. Configure Azure AD integration for secure document management and automation. keywords: - sharepoint integration - onedrive integration diff --git a/docs/Integrations/SalesForce.md b/docs/Integrations/SalesForce.md index 1ad17058..327dc648 100644 --- a/docs/Integrations/SalesForce.md +++ b/docs/Integrations/SalesForce.md @@ -1,7 +1,7 @@ --- title: Salesforce Integration sidebar_position: 2 -description: Transform your Salesforce data into professional documents, proposals, and presentations with TurboDocx. Create personalized deliverables using your real CRM data — powered by AI. +description: Transform Salesforce data into professional documents, proposals, and presentations. Create personalized deliverables powered by AI. keywords: - salesforce integration - crm documents diff --git a/docs/Integrations/Teams.md b/docs/Integrations/Teams.md index 11159c8d..dd5763b6 100644 --- a/docs/Integrations/Teams.md +++ b/docs/Integrations/Teams.md @@ -1,7 +1,7 @@ --- title: Microsoft Teams Integration sidebar_position: 6 -description: Transform Teams meetings into professional documents and presentations. Coming soon - Microsoft Teams integration for automated meeting documentation and collaboration workflows. +description: Coming soon. Transform Teams meetings into professional documents and presentations with automated meeting documentation and collaboration workflows. keywords: - microsoft teams integration - teams meeting documentation diff --git a/docs/Integrations/Wrike/convert-to-pdf.md b/docs/Integrations/Wrike/convert-to-pdf.md index a73f9aa3..40e74f72 100644 --- a/docs/Integrations/Wrike/convert-to-pdf.md +++ b/docs/Integrations/Wrike/convert-to-pdf.md @@ -1,7 +1,7 @@ --- title: How to Convert Wrike Documents to PDF sidebar_position: 11 -description: Configure a Wrike automation that converts the first attachment to PDF and attaches it back when a task, project, or folder changes status, with automatic in-place versioning on re-runs. +description: Configure Wrike automation to convert first attachment to PDF when task, project, or folder status changes. Auto-versioning on re-runs. keywords: - wrike convert to pdf - wrike pdf conversion diff --git a/docs/Integrations/Wrike/document-packages.md b/docs/Integrations/Wrike/document-packages.md index 2cd3700e..2a0ee400 100644 --- a/docs/Integrations/Wrike/document-packages.md +++ b/docs/Integrations/Wrike/document-packages.md @@ -1,7 +1,7 @@ --- title: How to Combine Documents in Wrike sidebar_position: 10 -description: Configure a Wrike automation that merges every attachment on a task or project into a single combined PDF (a Document Package) and attaches it back to Wrike when a status changes. +description: Configure Wrike automation to merge all attachments on a task or project into a single combined PDF and attach back on status change. keywords: - wrike document package - wrike combined pdf diff --git a/docs/Integrations/Wrike/index.md b/docs/Integrations/Wrike/index.md index e88ecd8c..956fcb99 100644 --- a/docs/Integrations/Wrike/index.md +++ b/docs/Integrations/Wrike/index.md @@ -1,7 +1,7 @@ --- title: Wrike Integration sidebar_position: 1 -description: Automate document generation from Wrike projects with TurboDocx. Generate SOWs, proposals, and reports directly from your Wrike tasks and folders using AI-powered automation. +description: Automate document generation from Wrike projects. Generate SOWs, proposals, and reports from tasks and folders with AI-powered automation. keywords: - wrike integration - wrike document automation diff --git a/docs/Integrations/Wrike/signature-workflow.md b/docs/Integrations/Wrike/signature-workflow.md index 9851d607..1b77ad96 100644 --- a/docs/Integrations/Wrike/signature-workflow.md +++ b/docs/Integrations/Wrike/signature-workflow.md @@ -1,7 +1,7 @@ --- title: "Wrike Example: Generate & Sign a Proposal" sidebar_position: 2 -description: Watch the full Wrike workflow in action — trigger document generation from a task status change, review an AI-powered proposal, and send it for e-signature, all without leaving Wrike. +description: Trigger document generation from task status change, review AI-powered proposal, and send for e-signature in Wrike without leaving the app. keywords: - wrike end to end example - wrike document generation example diff --git a/docs/Integrations/Zapier.md b/docs/Integrations/Zapier.md index d29505bc..64a4f7bf 100644 --- a/docs/Integrations/Zapier.md +++ b/docs/Integrations/Zapier.md @@ -1,7 +1,7 @@ --- title: Zapier Integration sidebar_position: 5 -description: Export TurboDocx documents to 5,000+ apps with Zapier automation. Connect your document generation to any CRM, project management, or cloud storage platform automatically. +description: Export TurboDocx documents to 5,000+ apps with Zapier. Connect document generation to any CRM, project management, or cloud storage platform. keywords: - zapier document automation - zapier integration turbodocx diff --git a/docs/Integrations/Zoom.md b/docs/Integrations/Zoom.md index 47b3b336..e8adaedd 100644 --- a/docs/Integrations/Zoom.md +++ b/docs/Integrations/Zoom.md @@ -1,7 +1,7 @@ --- title: Zoom Integration sidebar_position: 4 -description: Automatically turn Zoom transcripts into documents, proposals, and slide decks with TurboDocx. Speed up follow-ups, sales cycles, and client onboarding — powered by AI. +description: Turn Zoom transcripts into documents, proposals, and slide decks. Speed up follow-ups, sales cycles, and client onboarding with AI. keywords: - zoom meeting documents - zoom call transcripts diff --git a/docs/Pipelines/Cloud Connectors.md b/docs/Pipelines/Cloud Connectors.md index 2edda733..325a991d 100644 --- a/docs/Pipelines/Cloud Connectors.md +++ b/docs/Pipelines/Cloud Connectors.md @@ -1,7 +1,7 @@ --- title: Cloud Connectors (Enterprise) sidebar_position: 6 -description: Resolve signer details from systems behind your firewall. A Cloud connector runs inside your network, makes only outbound HTTPS calls to TurboDocx, and keeps your data in place. No inbound firewall access required. +description: Cloud connectors resolve signer details from systems behind your firewall without inbound access. Secure lookup from databases and internal APIs. keywords: - cloud connectors - signer resolution diff --git a/docs/Pipelines/Creating an E-Signature Pipeline.md b/docs/Pipelines/Creating an E-Signature Pipeline.md index 696e2f87..8374cfa4 100644 --- a/docs/Pipelines/Creating an E-Signature Pipeline.md +++ b/docs/Pipelines/Creating an E-Signature Pipeline.md @@ -1,7 +1,7 @@ --- title: Creating an E-Signature Pipeline sidebar_position: 2 -description: Step-by-step walkthrough of the pipeline wizard. Connect a source library, define field extraction and routing, choose signers, and pick a destination for signed documents. +description: Walkthrough of the pipeline wizard. Connect source library, define field extraction and routing, choose signers, and pick destination. keywords: - create e-signature pipeline - pipeline wizard diff --git a/docs/Pipelines/Field Extraction.md b/docs/Pipelines/Field Extraction.md index 05debc74..1e41d7a0 100644 --- a/docs/Pipelines/Field Extraction.md +++ b/docs/Pipelines/Field Extraction.md @@ -1,7 +1,7 @@ --- title: Field Extraction sidebar_position: 4 -description: Pull values out of every PDF using text patterns. Capture invoice codes, dates, emails, and amounts to drive filenames, signer lookup, and routing in your pipeline. +description: Extract values from PDFs using text patterns. Capture codes, dates, emails, and amounts for routing and signer lookup in pipelines. keywords: - field extraction - pdf data extraction diff --git a/docs/Pipelines/Field Placement.md b/docs/Pipelines/Field Placement.md index f0447f00..98268fd2 100644 --- a/docs/Pipelines/Field Placement.md +++ b/docs/Pipelines/Field Placement.md @@ -1,7 +1,7 @@ --- title: Field Placement sidebar_position: 5 -description: Place signature and form fields on your sample PDF once, and the pipeline reprojects them onto every live document. Full TurboSign field-type parity, positioned per page and assigned to recipients. +description: Place signature and form fields on sample PDF once; pipeline reprojects them onto all live documents. Full field-type parity per page. keywords: - field placement - signature field placement diff --git a/docs/Pipelines/TurboDocx Pipelines.md b/docs/Pipelines/TurboDocx Pipelines.md index 25e4d626..e414a630 100644 --- a/docs/Pipelines/TurboDocx Pipelines.md +++ b/docs/Pipelines/TurboDocx Pipelines.md @@ -1,7 +1,7 @@ --- title: TurboDocx Pipelines sidebar_position: 1 -description: Automate document intake, data extraction, signature placement, and e-signature delivery end-to-end. Drop a PDF in a watched folder and TurboDocx Pipelines handles the rest, fully unattended. +description: Automate document intake, extraction, signature placement, and delivery end-to-end. Drop PDFs in a watched folder for unattended processing. keywords: - turbodocx pipelines - document automation diff --git a/docs/SDKs/agent-skills.md b/docs/SDKs/agent-skills.md index d09b37c1..8b844f15 100644 --- a/docs/SDKs/agent-skills.md +++ b/docs/SDKs/agent-skills.md @@ -2,7 +2,7 @@ title: Install with AI Agents (Agent Skills) sidebar_position: 0 sidebar_label: Install with AI Agents -description: Install the TurboDocx SDK and @turbodocx/html-to-docx into any project in one prompt using the TurboDocx Agent Skill — works with Claude Code, GitHub Copilot, Cursor, OpenCode, OpenAI Codex CLI, and Gemini CLI. +description: "TurboDocx Agent Skill: install the SDK and html-to-docx in one prompt via Claude Code, Copilot, Cursor, or Codex CLI." keywords: - agent skills - ai agent diff --git a/docs/SDKs/deliverable-go.md b/docs/SDKs/deliverable-go.md index 13f61d36..ea99a086 100644 --- a/docs/SDKs/deliverable-go.md +++ b/docs/SDKs/deliverable-go.md @@ -70,7 +70,7 @@ func main() { ``` :::tip No SenderEmail Required -Use `NewDeliverableClientOnly()` when you only need document generation — it skips the `SenderEmail` validation required by TurboSign. +Use `NewDeliverableClientOnly()` when you only need document generation: it skips the `SenderEmail` validation required by TurboSign. ::: ### Environment Variables @@ -422,20 +422,7 @@ if err != nil { ## Error Handling -The SDK provides typed errors for different error scenarios: - -### Error Types - -| Error Type | Status Code | Description | -| --------------------- | ----------- | ---------------------------------- | -| `TurboDocxError` | varies | Base error type for all API errors | -| `AuthenticationError` | 401 | Invalid or missing API key | -| `AuthorizationError` | 403 | Authenticated but lacks required permissions | -| `ValidationError` | 400 | Invalid request parameters | -| `NotFoundError` | 404 | Deliverable or template not found | -| `ConflictError` | 409 | Request conflicts with current resource state | -| `RateLimitError` | 429 | Too many requests | -| `NetworkError` | - | Network connectivity issues | +`GenerateDeliverable` returns `NotFoundError` when `TemplateID` doesn't match a template in the org, and `ValidationError` for invalid request parameters, most commonly a `DeliverableVariable` missing `Text` (required unless it sets `VariableStack` or `IsDisabled: true`) or specifying an unsupported `MimeType`. Match on the concrete type with `errors.As`, same as every other Go SDK call: ### Handling Errors @@ -479,13 +466,7 @@ if err != nil { } ``` -### Error Properties - -| Property | Type | Description | -| ------------ | -------- | ---------------------------- | -| `Message` | `string` | Human-readable error message | -| `StatusCode` | `int` | HTTP status code | -| `Code` | `string` | Error code (if available) | +The full typed-error table (`AuthenticationError`, `AuthorizationError`, `ConflictError`, `RateLimitError`, `NetworkError`, HTTP status mapping) and the `Message`/`StatusCode`/`Code` fields on every error are documented once in the [Go SDK's Error Handling reference](./go.md#error-handling). --- diff --git a/docs/SDKs/deliverable-java.md b/docs/SDKs/deliverable-java.md index 9df5d277..9a0bbf3a 100644 --- a/docs/SDKs/deliverable-java.md +++ b/docs/SDKs/deliverable-java.md @@ -32,7 +32,7 @@ The official TurboDocx Deliverable SDK for Java applications. Generate documents com.turbodocx turbodocx-sdk - 0.5.0 + 0.7.0 ``` @@ -40,14 +40,14 @@ The official TurboDocx Deliverable SDK for Java applications. Generate documents ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.5.0") +implementation("com.turbodocx:turbodocx-sdk:0.7.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.5.0' +implementation 'com.turbodocx:turbodocx-sdk:0.7.0' ``` @@ -87,7 +87,7 @@ public class Main { ``` :::tip No senderEmail Required -Use `buildDeliverableClient()` when you only need document generation — it skips the `senderEmail` validation required by TurboSign. +Use `buildDeliverableClient()` when you only need document generation: it skips the `senderEmail` validation required by TurboSign. ::: ### Environment Variables @@ -285,9 +285,9 @@ The builder authenticates with either `apiKey(...)` or `accessToken(...)` (a bea | Builder method | Returns | Use for | | -------------------------- | ------------------- | --------------------------------------------------- | -| `build()` | `TurboDocxClient` | Full client — `turboSign()` and `deliverable()` | +| `build()` | `TurboDocxClient` | Full client, `turboSign()` and `deliverable()` | | `buildDeliverableClient()` | `DeliverableClient` | Document generation only (no `senderEmail` needed) | -| `buildWebhooksClient()` | `TurboWebhooks` | Signature webhook subscriptions — see [TurboWebhooks Java SDK](/docs/SDKs/webhooks-java) | +| `buildWebhooksClient()` | `TurboWebhooks` | Signature webhook subscriptions, see [TurboWebhooks Java SDK](/docs/SDKs/webhooks-java) | ```java // Authenticate with a bearer access token instead of an API key @@ -400,20 +400,7 @@ Files.write(Paths.get("report.pdf"), pdfData); ## Error Handling -The SDK provides typed exceptions for different error scenarios: - -### Error Types - -| Error Type | Status Code | Description | -| -------------------------------------------- | ----------- | ---------------------------------- | -| `TurboDocxException` | varies | Base exception for all API errors | -| `TurboDocxException.AuthenticationException` | 401 | Invalid or missing API credentials | -| `TurboDocxException.AuthorizationException` | 403 | Insufficient permissions | -| `TurboDocxException.ValidationException` | 400 | Invalid request parameters | -| `TurboDocxException.NotFoundException` | 404 | Deliverable or template not found | -| `TurboDocxException.ConflictException` | 409 | Resource conflict | -| `TurboDocxException.RateLimitException` | 429 | Too many requests | -| `TurboDocxException.NetworkException` | - | Network connectivity issues | +`deliverable.generateDeliverable()` throws `TurboDocxException.NotFoundException` when `templateId` doesn't match a template in the org, and `TurboDocxException.ValidationException` when a variable in the request is missing a required field: ### Handling Errors @@ -443,13 +430,7 @@ try { } ``` -### Error Properties - -| Property | Type | Description | -| ----------------- | -------- | ---------------------------- | -| `getMessage()` | `String` | Human-readable error message | -| `getStatusCode()` | `int` | HTTP status code | -| `getCode()` | `String` | Error code (if available) | +The full typed-exception table (`AuthenticationException`, `AuthorizationException`, `ConflictException`, `RateLimitException`, `NetworkException`, HTTP status mapping) and the `getMessage()`/`getStatusCode()`/`getCode()` methods shared by every exception are documented once in the [Java SDK's Error Handling reference](./java.md#error-handling). --- diff --git a/docs/SDKs/deliverable-javascript.md b/docs/SDKs/deliverable-javascript.md index 0f856281..11a8b5d3 100644 --- a/docs/SDKs/deliverable-javascript.md +++ b/docs/SDKs/deliverable-javascript.md @@ -99,14 +99,14 @@ Deliverable.configure({ | Property | Type | Required | Description | | ------------- | -------- | -------- | ------------------------------------------------------ | | `apiKey` | `string` | Yes\* | Your TurboDocx API key | -| `accessToken` | `string` | Yes\* | OAuth access token — alternative to `apiKey` | +| `accessToken` | `string` | Yes\* | OAuth access token, alternative to `apiKey` | | `orgId` | `string` | Yes | Your organization ID | | `baseUrl` | `string` | No | API base URL (defaults to `https://api.turbodocx.com`) | \*Supply either `apiKey` or `accessToken`. When both are set, `accessToken` wins. :::tip No Sender Email Required -Unlike TurboSign, the Deliverable module only requires a credential and `orgId` — no sender email or name is needed. +Unlike TurboSign, the Deliverable module only requires a credential and `orgId`: no sender email or name is needed. ::: ### Environment Variables @@ -602,20 +602,7 @@ writeFileSync("report.pdf", Buffer.from(buffer)); ## Error Handling -The SDK provides typed error classes for different failure scenarios. All errors extend the base `TurboDocxError` class. - -### Error Classes - -| Error Class | Status Code | Code | Description | -| --------------------- | ----------- | ---------------------- | ---------------------------------------- | -| `TurboDocxError` | varies | varies | Base error class for all SDK errors | -| `AuthenticationError` | 401 | `AUTHENTICATION_ERROR` | Invalid or missing API credentials | -| `AuthorizationError` | 403 | `AUTHORIZATION_ERROR` | Forbidden: API key lacks required permissions | -| `ValidationError` | 400 | `VALIDATION_ERROR` | Invalid request parameters | -| `NotFoundError` | 404 | `NOT_FOUND` | Deliverable or template not found | -| `ConflictError` | 409 | `CONFLICT` | Resource conflict | -| `RateLimitError` | 429 | `RATE_LIMIT_EXCEEDED` | Too many requests | -| `NetworkError` | - | `NETWORK_ERROR` | Network connectivity issues | +`Deliverable.generateDeliverable()` rejects with `NotFoundError` when `templateId` doesn't match a template in the org, and `ValidationError` when an entry in `variables` is missing a required field. Both extend the base `TurboDocxError` class: ### Handling Errors @@ -710,15 +697,7 @@ try { -### Error Properties - -All errors include these properties: - -| Property | Type | Description | -| ------------ | --------------------- | -------------------------------- | -| `message` | `string` | Human-readable error description | -| `statusCode` | `number \| undefined` | HTTP status code (if applicable) | -| `code` | `string \| undefined` | Machine-readable error code | +The full typed-error table (`AuthenticationError`, `AuthorizationError`, `ConflictError`, `RateLimitError`, `NetworkError`, HTTP status and code mapping) and the `message`/`statusCode`/`code` properties shared by every error are documented once in the [JavaScript / TypeScript SDK's Error Handling reference](./javascript.md#error-handling). --- diff --git a/docs/SDKs/deliverable-php.md b/docs/SDKs/deliverable-php.md index d93524bc..9fa8eb7b 100644 --- a/docs/SDKs/deliverable-php.md +++ b/docs/SDKs/deliverable-php.md @@ -81,7 +81,7 @@ Deliverable::configure(DeliverableConfig::fromEnvironment()); :::tip No senderEmail Required -Unlike TurboSign, the Deliverable module only requires `apiKey` and `orgId` — no sender email or name is needed. +Unlike TurboSign, the Deliverable module only requires `apiKey` and `orgId`: no sender email or name is needed. ::: ### Environment Variables @@ -361,20 +361,7 @@ echo $pdfFile; ## Error Handling -The SDK provides typed exceptions for different error scenarios. - -### Error Classes - -| Error Class | Status Code | Description | -| ------------------------- | ----------- | ---------------------------------- | -| `TurboDocxException` | varies | Base exception for all SDK errors | -| `AuthenticationException` | 401 | Invalid or missing API credentials | -| `AuthorizationException` | 403 | API key lacks required permissions | -| `ValidationException` | 400 | Invalid request parameters | -| `NotFoundException` | 404 | Deliverable or template not found | -| `ConflictException` | 409 | Resource conflict | -| `RateLimitException` | 429 | Too many requests | -| `NetworkException` | - | Network connectivity issues | +`Deliverable::generateDeliverable()` throws `NotFoundException` when `templateId` doesn't match a template in the org, and `ValidationException` when a variable in the `variables` array is missing a required field: ### Handling Errors @@ -423,13 +410,7 @@ try { } ``` -### Error Properties - -All exceptions extend `TurboDocxException` and include: - -- `getMessage()` - Human-readable error message -- `statusCode` - HTTP status code (if applicable) -- `errorCode` - Error code string (e.g., 'AUTHENTICATION_ERROR') +The full typed-exception table (`AuthenticationException`, `AuthorizationException`, `ConflictException`, `RateLimitException`, `NetworkException`, HTTP status mapping) and the `getMessage()`/`statusCode`/`errorCode` properties shared by every exception are documented once in the [PHP SDK's Error Handling reference](./php.md#error-handling). --- diff --git a/docs/SDKs/deliverable-python.md b/docs/SDKs/deliverable-python.md index 9b916d1a..e21c4139 100644 --- a/docs/SDKs/deliverable-python.md +++ b/docs/SDKs/deliverable-python.md @@ -70,7 +70,7 @@ Deliverable.configure( ``` :::tip No Sender Email Required -Unlike TurboSign, the Deliverable module only requires `api_key` and `org_id` — no sender email or name is needed. +Unlike TurboSign, the Deliverable module only requires `api_key` and `org_id`: no sender email or name is needed. ::: ### Environment Variables @@ -349,20 +349,7 @@ with open("report.pdf", "wb") as f: ## Error Handling -The SDK provides typed error classes for different failure scenarios. All errors extend the base `TurboDocxError` class. - -### Error Classes - -| Error Class | Status Code | Description | -| --------------------- | ----------- | ----------------------------------- | -| `TurboDocxError` | varies | Base error class for all SDK errors | -| `AuthenticationError` | 401 | Invalid or missing API credentials | -| `AuthorizationError` | 403 | Authenticated but lacks required permissions | -| `ValidationError` | 400 | Invalid request parameters | -| `NotFoundError` | 404 | Deliverable or template not found | -| `ConflictError` | 409 | Request conflicts with current resource state | -| `RateLimitError` | 429 | Too many requests | -| `NetworkError` | - | Network connectivity issues | +`Deliverable.generate_deliverable()` raises `NotFoundError` when `template_id` doesn't match a template in the org, and `ValidationError` for invalid request parameters, most commonly a variable dict missing `text` (required unless it sets `variableStack` or `isDisabled: True`) or specifying an unsupported `mimeType`. Both extend the base `TurboDocxError`: ### Handling Errors @@ -416,15 +403,7 @@ async def main(): asyncio.run(main()) ``` -### Error Properties - -All errors include these properties: - -| Property | Type | Description | -| ------------- | ------------- | --------------------------------------------------- | -| `message` | `str` | Human-readable error description (via `str(error)`) | -| `status_code` | `int \| None` | HTTP status code (if applicable) | -| `code` | `str \| None` | Machine-readable error code | +The full typed-error table (`AuthenticationError`, `AuthorizationError`, `ConflictError`, `RateLimitError`, `NetworkError`, HTTP status mapping) and the `message`/`status_code`/`code` attributes shared by every error are documented once in the [Python SDK's Error Handling reference](./python.md#error-handling). --- diff --git a/docs/SDKs/go.md b/docs/SDKs/go.md index 760124ed..82e06fe8 100644 --- a/docs/SDKs/go.md +++ b/docs/SDKs/go.md @@ -324,7 +324,7 @@ result, err := client.TurboSign.SendSignature(ctx, &turbodocx.SendSignatureReque ### Schedule reminders and expiration -`SendSignature` accepts an optional `SignatureSchedule` that turns on automatic reminder emails and a signing deadline. Every field is a pointer, and **both features are off by default** — omit the schedule entirely to preserve the original send behavior. The resolved schedule is **frozen onto the document at send time**, so later changes to your org defaults never touch a document already out for signature. +`SendSignature` accepts an optional `SignatureSchedule` that turns on automatic reminder emails and a signing deadline. Every field is a pointer, and **both features are off by default**: omit the schedule entirely to preserve the original send behavior. The resolved schedule is **frozen onto the document at send time**, so later changes to your org defaults never touch a document already out for signature. ```go result, err := client.TurboSign.SendSignature(ctx, &turbodocx.SendSignatureRequest{ @@ -346,7 +346,7 @@ result, err := client.TurboSign.SendSignature(ctx, &turbodocx.SendSignatureReque | `RemindersEnabled` | `*bool` | Master switch for automatic reminders. Default off. | | `ReminderDelay` | `*Duration` | Time to the **first** reminder, measured from that signer's invitation. | | `ReminderInterval` | `*Duration` | Gap between **subsequent** reminders. | -| `MaxReminders` | `*int` | Automatic reminders per signer. Valid range **-1..50** — `-1` unlimited, `0` none, default `5`. | +| `MaxReminders` | `*int` | Automatic reminders per signer. Valid range **-1..50**: `-1` unlimited, `0` none, default `5`. | | `ExpirationEnabled` | `*bool` | Master switch for the signing deadline. Default off. | | `ExpireAfter` | `*Duration` | How long the document stays signable, counted from sending. | | `ExpirationWarning` | `*Duration` | How far **before** expiry warnings start. `0` = never warn. | @@ -356,7 +356,7 @@ A `Duration` is a `{Value, Unit}` pair; `Unit` is `"hours"` or `"days"`. `Value` ### Get status -Check the status of a document. The response includes `ExpiresAt` — the signing-window deadline as an ISO 8601 string, or `""` when expiration is off — and a `Status` that can reach the terminal value `expired` once the deadline passes. For per-signer detail, use [Get recipients](#get-recipients). +Check the status of a document. The response includes `ExpiresAt` (the signing-window deadline as an ISO 8601 string, or `""` when expiration is off) and a `Status` that can reach the terminal value `expired` once the deadline passes. For per-signer detail, use [Get recipients](#get-recipients). ```go status, err := client.TurboSign.GetStatus(ctx, "document-uuid") @@ -392,7 +392,7 @@ for _, r := range progress.Recipients { :::tip Two status fields, and they differ on purpose `status` is the raw database value and is only ever `pending`, `viewed` or `completed`. -`effectiveStatus` layers the document's outcome on top, adding `voided` and `expired` — that +`effectiveStatus` layers the document's outcome on top, adding `voided` and `expired`: that is the one to display. On a voided or expired document an unsigned signer still reads `pending` in `status`, so @@ -405,14 +405,14 @@ the document is terminal. ::: -Each recipient also carries a `delivery` block — `firstSentOn`, `lastSentOn`, `totalSent`, +Each recipient also carries a `delivery` block: `firstSentOn`, `lastSentOn`, `totalSent`, `reminderCount`, `lastRemindedAt`, `warningCount`, `lastWarningAt`. It counts the signature request, resends, reminders, expiry warnings and terminal notices; CC notifications are excluded, since a CC address is not a signer. :::warning `reminderCount` and `lastRemindedAt` do not mean what their names suggest -`reminderCount` counts **automatic (scheduled) reminders only** — the counter `maxReminders` +`reminderCount` counts **automatic (scheduled) reminders only**: the counter `maxReminders` caps. A manual "remind now" is a standalone nudge that must not consume the cap budget, so it does **not** increment this, even though the email it sends *does* appear in `totalSent`. @@ -421,7 +421,7 @@ signature-request send, each scheduled reminder, each manual "remind now" and ea warning all stamp it. Only scheduled reminders bump `reminderCount`. So a freshly-sent document returns a non-null `lastRemindedAt` equal to the invitation -timestamp alongside `reminderCount: 0` — nobody has been reminded. To answer "have we actually +timestamp alongside `reminderCount: 0`: nobody has been reminded. To answer "have we actually chased this person", read `totalSent`, not `reminderCount`. `warningCount` / `lastWarningAt` have no such caveat. @@ -477,7 +477,7 @@ result, err := client.TurboSign.ResendEmail(ctx, "document-uuid", []string{"reci ### Send reminder -Send a standalone reminder to whoever's turn it is to sign (`POST /turbosign/documents/:id/send-reminder`). It is independent of the automatic reminder cadence — it works even when reminders are disabled or the per-signer `MaxReminders` cap is already spent, does **not** consume that cap, and only emails signers at the **current** signing order. Pass `nil` for `recipientIDs` to remind everyone eligible; do **not** pass an empty slice, which the API rejects. +Send a standalone reminder to whoever's turn it is to sign (`POST /turbosign/documents/:id/send-reminder`). It is independent of the automatic reminder cadence: it works even when reminders are disabled or the per-signer `MaxReminders` cap is already spent, does **not** consume that cap, and only emails signers at the **current** signing order. Pass `nil` for `recipientIDs` to remind everyone eligible; do **not** pass an empty slice, which the API rejects. ```go resp, err := client.TurboSign.SendReminder(ctx, "document-uuid", nil) @@ -497,7 +497,7 @@ This differs from **Resend**: resend re-sends the original invitation email, whi ## Error Handling -The SDK provides typed errors for different error scenarios: +Every typed error embeds `TurboDocxError` by value, which promotes its `Message string`, `StatusCode int`, and `Code string` fields onto the typed error, so read them directly off the matched variable (`authErr.Message`, not a getter). Match with `errors.As`, as the example below does: ### Error Types @@ -508,16 +508,17 @@ The SDK provides typed errors for different error scenarios: | `AuthorizationError` | 403 | Authenticated but lacks required permissions | | `ValidationError` | 400 | Invalid request parameters | | `NotFoundError` | 404 | Resource not found | +| `ConflictError` | 409 | Request conflicts with current resource state; most common on the webhook routes (creating or renaming to a name that already exists) | | `RateLimitError` | 429 | Too many requests | | `NetworkError` | - | Network connectivity issues | ### Error Properties | Property | Type | Description | -| ------------ | -------- | ---------------------------- | -| `Message` | `string` | Human-readable error message | +| ------------ | -------- | ----------------------------- | +| `Message` | `string` | Human-readable error message. `Error()` does not return this bare string: it returns `TurboDocx API error [CODE]: MESSAGE (status N)`, omitting the `[CODE]` segment when `Code` is empty. Compare against `.Message` directly, not `err.Error()` | | `StatusCode` | `int` | HTTP status code | -| `Code` | `string` | Error code (if available) | +| `Code` | `string` | Machine-readable code; the API's code wins when present, otherwise the SDK fills in a per-status default for each of the 7 named types above. The bare `TurboDocxError` returned for an unmapped status (e.g. an unexpected 5xx) can have an empty `Code` if the API didn't supply one | ### Example @@ -535,6 +536,7 @@ if err != nil { var authzErr *turbodocx.AuthorizationError var validationErr *turbodocx.ValidationError var notFoundErr *turbodocx.NotFoundError + var conflictErr *turbodocx.ConflictError var rateLimitErr *turbodocx.RateLimitError var networkErr *turbodocx.NetworkError @@ -547,6 +549,8 @@ if err != nil { log.Printf("Validation error: %s", validationErr.Message) case errors.As(err, ¬FoundErr): log.Printf("Not found: %s", notFoundErr.Message) + case errors.As(err, &conflictErr): + log.Printf("Conflict: %s", conflictErr.Message) case errors.As(err, &rateLimitErr): log.Printf("Rate limited: %s", rateLimitErr.Message) case errors.As(err, &networkErr): @@ -610,7 +614,7 @@ The `Type` field accepts the following string values: | `Required` | `bool` | No | Make field required | | `BackgroundColor` | `string` | No | Background color | | `Template` | `*TemplateAnchor` | No | Template anchor configuration | -| `Metadata` | `*FieldMetadata` | No | Conditional (IF/THEN) metadata — see below | +| `Metadata` | `*FieldMetadata` | No | Conditional (IF/THEN) metadata, see below | \*Required when not using template anchors @@ -711,5 +715,5 @@ For detailed information about advanced configuration and API concepts, see: ## Resources - [GitHub Repository](https://github.com/TurboDocx/SDK/tree/main/packages/go-sdk) -- [API Reference](/docs/TurboSign/API-Signatures) +- [API Reference](/docs/TurboSign/API%20Signatures) - [Webhook Configuration](/docs/TurboSign/Webhooks) diff --git a/docs/SDKs/index.md b/docs/SDKs/index.md index cbc208ba..94238cd2 100644 --- a/docs/SDKs/index.md +++ b/docs/SDKs/index.md @@ -25,7 +25,7 @@ Official client libraries for the TurboDocx API. Build document generation, digi ## Choose Your Product -All five modules ship in the **same package** for each language — pick the one that matches what you're building: +All five modules ship in the **same package** for each language: pick the one that matches what you're building: | Product | Use it when you need to… | | :------------- | :----------------------------------------------------------------------------------------- | @@ -37,7 +37,7 @@ All five modules ship in the **same package** for each language — pick the one TurboSign, Deliverable, TurboQuote, and TurboWebhooks all use the same `TURBODOCX_API_KEY` + `TURBODOCX_ORG_ID`. See [credential requirements](#which-credentials-does-each-product-need) below. :::tip Install with one prompt -Skip the boilerplate — use the [TurboDocx Agent Skill](./agent-skills.md) to install the SDK, configure environment variables, and generate working integration code via Claude Code, GitHub Copilot, Cursor, OpenCode, Codex CLI, or Gemini CLI: +Skip the boilerplate: use the [TurboDocx Agent Skill](./agent-skills.md) to install the SDK, configure environment variables, and generate working integration code via Claude Code, GitHub Copilot, Cursor, OpenCode, Codex CLI, or Gemini CLI: ```bash npx skills add TurboDocx/quickstart @@ -58,7 +58,7 @@ Send documents for legally-binding eSignatures with full audit trails. ## TurboWebhooks SDKs -Subscribe to all 7 TurboSign signature events — `sent`, `viewed`, `recipient_signed`, `signed`, `completed`, `finalization_failed`, `voided` — and verify inbound signatures with HMAC-SHA256. Each SDK exports the full set as constants, so you never hand-write the wire strings. +Subscribe to all 7 TurboSign signature events (`sent`, `viewed`, `recipient_signed`, `signed`, `completed`, `finalization_failed`, `voided`) and verify inbound signatures with HMAC-SHA256. Each SDK exports the full set as constants, so you never hand-write the wire strings. | Language | Package | Install Command | Links | | :------------------------ | :-------------- | :---------------------------- | :----------------------------------------------------------------------------------------------------- | @@ -111,20 +111,20 @@ Before you begin, you'll need two things from your TurboDocx account: - **API Access Token**: Your authentication key - **Organization ID**: Your unique organization identifier -:::note senderEmail required for TurboSign -TurboSign also requires a `senderEmail` (used as the reply-to address for signature request emails). It is a **per-request body field on every signature request** and the SDK throws a validation error if it is missing. It can be passed in the SDK configuration or supplied via the `TURBODOCX_SENDER_EMAIL` environment variable. Deliverable and TurboWebhooks do not use it at all. +:::note senderEmail for TurboSign +TurboSign accepts a `senderEmail` (used as the reply-to address for signature request emails). The **JS/TS SDK enforces it client-side**: `TurboSign.configure()` throws a `ValidationError` (generic `VALIDATION_ERROR` code, not an API error code) if no `senderEmail` is supplied in configuration or via the `TURBODOCX_SENDER_EMAIL` environment variable; this check runs once at configure time, not per request. Other SDKs may differ; check each SDK's README. The **backend API itself does not require `senderEmail`** for TurboSign or TurboQuote; a request or org template with no sender falls back to a generic TurboDocx no-reply address and name and is never rejected. Deliverable and TurboWebhooks do not use `senderEmail` at all. -**TurboQuote is different:** there is **no `senderEmail` field on a quote request**, but a sender is still required. It is resolved from your organization's **quote template** (Quote Settings). An API-key caller whose template has no sender email gets `400 SenderEmailRequired` on create, duplicate, send, and handle-expired-sent — see [Prepared By & Sender Identity](/docs/TurboQuote/Prepared%20By%20and%20Sender%20Identity). +**TurboQuote:** there is **no `senderEmail` field on a quote request**. A sender is resolved from your organization's **quote template** (Quote Settings) when set; if none is configured, the quote falls back to a generic TurboDocx sender rather than failing. See [Prepared By & Sender Identity](/docs/TurboQuote/Prepared%20By%20and%20Sender%20Identity). ::: #### Which credentials does each product need? | Product | API key | Org ID | Also needs | | :------------- | :----------------------------- | :------------------------- | :-------------------------------------------------------------- | -| **TurboSign** | `TURBODOCX_API_KEY` | `TURBODOCX_ORG_ID` | `TURBODOCX_SENDER_EMAIL` (required — reply-to for signer emails) | -| **Deliverable** | `TURBODOCX_API_KEY` | `TURBODOCX_ORG_ID` | — | -| **TurboQuote** | `TURBODOCX_API_KEY` | `TURBODOCX_ORG_ID` | a **Sender Email + Sender Name on the org quote template** (no per-request sender field exists) | -| **TurboWebhooks** | `TURBODOCX_API_KEY` (**administrator** role — non-admin keys get 403) | `TURBODOCX_ORG_ID` | the webhook secret returned by `createWebhook`, to verify inbound events | +| **TurboSign** | `TURBODOCX_API_KEY` | `TURBODOCX_ORG_ID` | `TURBODOCX_SENDER_EMAIL` (required by the JS/TS SDK at configure time, reply-to for signer emails; the API itself falls back to a generic sender if omitted) | +| **Deliverable** | `TURBODOCX_API_KEY` | `TURBODOCX_ORG_ID` | None | +| **TurboQuote** | `TURBODOCX_API_KEY` | `TURBODOCX_ORG_ID` | a **Sender Email + Sender Name on the org quote template** recommended (no per-request sender field exists; falls back to a generic TurboDocx sender if not configured) | +| **TurboWebhooks** | `TURBODOCX_API_KEY` (**administrator** role, non-admin keys get 403) | `TURBODOCX_ORG_ID` | the webhook secret returned by `createWebhook`, to verify inbound events | #### How to Get Your Credentials @@ -447,7 +447,7 @@ public class Main { All TurboDocx SDKs provide access to: -### TurboSign — Digital Signatures +### TurboSign: Digital Signatures Send documents for legally-binding eSignatures with full audit trails. @@ -464,7 +464,7 @@ Send documents for legally-binding eSignatures with full audit trails. [Learn more about TurboSign →](/docs/TurboSign/Setting%20up%20TurboSign) -### Deliverable — Document Generation +### Deliverable: Document Generation Generate documents from templates with dynamic variable injection, download source files and PDFs. @@ -480,7 +480,7 @@ Generate documents from templates with dynamic variable injection, download sour [Learn more about Deliverable SDKs →](/docs/SDKs/deliverable-javascript) -### TurboQuote — Sales Quoting & CPQ +### TurboQuote: Sales Quoting & CPQ Build quotes and proposals: line items, a product/bundle catalog, price books, companies, and contacts. @@ -496,7 +496,7 @@ Build quotes and proposals: line items, a product/bundle catalog, price books, c [Learn more about TurboQuote SDKs →](/docs/SDKs/quote-javascript) -### TurboWebhooks — Signature Events +### TurboWebhooks: Signature Events Subscribe a per-org endpoint to TurboSign events and verify inbound deliveries with HMAC-SHA256. **Requires an administrator API key.** @@ -508,7 +508,7 @@ Subscribe a per-org endpoint to TurboSign events and verify inbound deliveries w | `testWebhook()` | Fire a synthetic delivery to all configured URLs | | `regenerateWebhookSecret()` | Rotate the HMAC secret | | `listWebhookDeliveries()` / `replayWebhookDelivery()` | Inspect and retry past deliveries | -| `verifyWebhookSignature()` | Free function — verify the `X-TurboDocx-Signature` header on a received event | +| `verifyWebhookSignature()` | Free function, verify the `X-TurboDocx-Signature` header on a received event | [Learn more about TurboWebhooks SDKs →](/docs/SDKs/webhooks-javascript) @@ -592,7 +592,8 @@ async def main(): try: result = await TurboSign.send_signature(...) except TurboDocxError as e: - print(f"Error {e.code}: {e.message}") + # TurboDocxError doesn't set a .message attribute; str(e) is the message + print(f"Error {e.code}: {e}") if e.code == "VALIDATION_ERROR": # Handle validation error pass @@ -616,7 +617,7 @@ try { echo "Validation error: {$e->getMessage()}\n"; // Handle validation error } catch (TurboDocxException $e) { - echo "Error {$e->getCode()}: {$e->getMessage()}\n"; + echo "Error {$e->errorCode}: {$e->getMessage()}\n"; echo "Status code: {$e->statusCode}\n"; } ``` @@ -627,12 +628,12 @@ try { ```go result, err := client.TurboSign.SendSignature(ctx, request) if err != nil { - var turboErr *sdk.TurboDocxError - if errors.As(err, &turboErr) { - fmt.Printf("Error %s: %s\n", turboErr.Code, turboErr.Message) - if turboErr.Code == "VALIDATION_ERROR" { - // Handle validation error - } + // errors.As must target the specific type: a *TurboDocxError target does not match + // *ValidationError, *AuthenticationError, etc., even though each embeds TurboDocxError. + // See the Go SDK's own Error Handling reference for the full set of named types. + var validationErr *sdk.ValidationError + if errors.As(err, &validationErr) { + fmt.Printf("Validation error [%s]: %s\n", validationErr.Code, validationErr.Message) } } ``` @@ -641,12 +642,12 @@ if err != nil { ```java -import com.turbodocx.sdk.TurboSign; -import com.turbodocx.sdk.TurboDocxException; -import com.turbodocx.sdk.TurboDocxException.*; +import com.turbodocx.TurboDocxException; +import com.turbodocx.TurboDocxException.*; +import com.turbodocx.models.*; try { - SigningResult result = turboSign.sendSignature(/* ... */); + SendSignatureResponse result = client.turboSign().sendSignature(/* ... */); } catch (AuthenticationException e) { System.err.println("Invalid API key: " + e.getMessage()); } catch (ValidationException e) { @@ -675,19 +676,18 @@ try { | `RATE_LIMIT_EXCEEDED` | 429 | Too many requests, retry with backoff | | `NETWORK_ERROR` | N/A | Network connection or timeout error | -`code` is **always populated**. When the API returns a specific code the SDK surfaces it -verbatim; otherwise it falls back to the class default above, so you can branch on `code` -without a null check. +When the API returns a specific code the SDK surfaces it verbatim; otherwise, for one of the +7 named categories above, it falls back to that class's default, so `code` is populated for +those without a null check. An error for a status code outside this table (an unexpected 5xx, +for example) is not guaranteed a `code`. ### TurboQuote / TurboSign specific codes These are returned by the API and passed through unchanged. They are more precise than the -generic codes above — prefer them when handling a specific failure. +generic codes above; prefer them when handling a specific failure. | Code | HTTP Status | Meaning | | :------------------------- | :---------- | :------------------------------------------------------------------------------------------ | -| `SenderEmailRequired` | 400 | No sender email could be resolved. TurboSign: set `senderEmail` on the request. TurboQuote: configure one on the org quote template (Quote Settings). | -| `SenderNameRequired` | 400 | No sender name could be resolved — the API key has no usable name. | | `QuoteHasNoLineItems` | 400 | The quote has no line items. Add at least one product, bundle, or custom line item. | | `QuoteExpired` | 400 | The quote is past its `validUntil` date. Update the date before sending. | | `QuoteValidUntilRequired` | 400 | The quote has no `validUntil` date set. | @@ -699,7 +699,7 @@ generic codes above — prefer them when handling a specific failure. ### Error messages carry the actionable reason The API reports validation failures in several envelopes. The SDKs unwrap all of them, so -`error.message` is the specific field-level reason — not a generic +`error.message` is the specific field-level reason, not a generic `"There was an issue validating the body"`. Multiple field errors are joined with `"; "`: ``` @@ -711,8 +711,8 @@ The API reports validation failures in several envelopes. The SDKs unwrap all of ## Audit Trail & Client Context Every action you take through an SDK is recorded in the TurboDocx audit trail. All six SDKs -automatically attach **client-context headers** to **every** request — including TurboSign, -Deliverable, TurboQuote, TurboWebhooks, and TurboPartner — so the audit trail records real +automatically attach **client-context headers** to **every** request, including TurboSign, +Deliverable, TurboQuote, TurboWebhooks, and TurboPartner, so the audit trail records real environment details instead of blanks: | Recorded column | What the SDK sends | @@ -723,7 +723,7 @@ environment details instead of blanks: | **Language** | The machine's locale (e.g. `en-US`) | | **Application** | `TurboDocx SDK ` | -You do not configure any of this — it is collected and sent for you. +You do not configure any of this: it is collected and sent for you. ### SDK / n8n calls vs. raw API calls @@ -735,7 +735,7 @@ The audit trail distinguishes how a request reached TurboDocx: | The TurboDocx n8n node | `TurboDocx n8n Node `, with real device, OS, timezone, and language | | A raw HTTP/API call | The **name of the HTTP library** that made the call, the action `API Request`, and `N/A` for the environment fields it cannot know | -Raw API calls show `N/A` — not `Unknown` — for the fields no client context was supplied for. If +Raw API calls show `N/A` (not `Unknown`) for the fields no client context was supplied for. If you want fully attributed audit entries, call through an SDK or the n8n node rather than hand-rolled HTTP. diff --git a/docs/SDKs/java.md b/docs/SDKs/java.md index 9a9f782e..2db1cd79 100644 --- a/docs/SDKs/java.md +++ b/docs/SDKs/java.md @@ -32,7 +32,7 @@ The official TurboDocx SDK for Java applications. Build document generation and com.turbodocx turbodocx-sdk - 0.5.0 + 0.7.0 ``` @@ -40,14 +40,14 @@ The official TurboDocx SDK for Java applications. Build document generation and ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.5.0") +implementation("com.turbodocx:turbodocx-sdk:0.7.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.5.0' +implementation 'com.turbodocx:turbodocx-sdk:0.7.0' ``` @@ -97,8 +97,8 @@ public class Main { | `senderName(String)` | `String` | No | - | Display name used on signature request emails | | `baseUrl(String)` | `String` | No | `https://api.turbodocx.com` | API base URL | | `connectTimeoutSeconds(int)` | `int` | No | `60` | Connection timeout | -| `readTimeoutSeconds(int)` | `int` | No | `120` | Read timeout — raise it for large document uploads | -| `writeTimeoutSeconds(int)` | `int` | No | `60` | Write timeout — raise it for large document uploads | +| `readTimeoutSeconds(int)` | `int` | No | `120` | Read timeout, raise it for large document uploads | +| `writeTimeoutSeconds(int)` | `int` | No | `60` | Write timeout, raise it for large document uploads | \*Provide either `apiKey` or `accessToken`. @@ -116,7 +116,7 @@ TurboDocxClient client = new TurboDocxClient.Builder() ### Closing the Client -`TurboDocxClient` implements `AutoCloseable`. Calling `close()` shuts down the underlying OkHttp dispatcher and connection pool, so long-running JVM services should close clients they no longer need — use try-with-resources for short-lived clients: +`TurboDocxClient` implements `AutoCloseable`. Calling `close()` shuts down the underlying OkHttp dispatcher and connection pool, so long-running JVM services should close clients they no longer need. Use try-with-resources for short-lived clients: ```java try (TurboDocxClient client = new TurboDocxClient.Builder() @@ -427,11 +427,11 @@ SendSignatureResponse result = client.turboSign().sendSignature( ); ``` -Each `Duration` is a `{value, unit}` pair where `unit` is `"hours"` or `"days"` and `value` is a whole number from **1 up to 999 days (23976 hours)**. `maxReminders` accepts **-1 to 50** (`-1` unlimited, `0` none, default `5`) and caps only automatic reminders — never expiry warnings; `expirationWarning` may be `0` to disable warnings. Reminders and expiry warnings run as two independent clocks, coordinated so a signer never receives both at the same moment — and a reminder cadence that would outlive the expiry window is rejected with `400`. +Each `Duration` is a `{value, unit}` pair where `unit` is `"hours"` or `"days"` and `value` is a whole number from **1 up to 999 days (23976 hours)**. `maxReminders` accepts **-1 to 50** (`-1` unlimited, `0` none, default `5`) and caps only automatic reminders, never expiry warnings; `expirationWarning` may be `0` to disable warnings. Reminders and expiry warnings run as two independent clocks, coordinated so a signer never receives both at the same moment, and a reminder cadence that would outlive the expiry window is rejected with `400`. ### Get status -Check the document-level status. When an expiration schedule is set, the response also carries `getExpiresAt()` — the signing-window deadline (ISO 8601), or `null` when expiration is off. Once that deadline passes, the document moves to the terminal `expired` status and its signing links stop working. `getRecipients()` exposes the same deadline on `getDocument().getExpiresAt()`. For per-signer detail, use [Get recipients](#get-recipients). +Check the document-level status. When an expiration schedule is set, the response also carries `getExpiresAt()` (the signing-window deadline, ISO 8601, or `null` when expiration is off). Once that deadline passes, the document moves to the terminal `expired` status and its signing links stop working. `getRecipients()` exposes the same deadline on `getDocument().getExpiresAt()`. For per-signer detail, use [Get recipients](#get-recipients). ```java DocumentStatusResponse status = client.turboSign().getStatus("document-uuid"); @@ -462,7 +462,7 @@ for (DocumentRecipientsResponse.RecipientSignatureStatus r : progress.getRecipie :::tip Two status fields, and they differ on purpose `status` is the raw database value and is only ever `pending`, `viewed` or `completed`. -`effectiveStatus` layers the document's outcome on top, adding `voided` and `expired` — that +`effectiveStatus` layers the document's outcome on top, adding `voided` and `expired`: that is the one to display. On a voided or expired document an unsigned signer still reads `pending` in `status`, so @@ -475,14 +475,14 @@ the document is terminal. ::: -Each recipient also carries a `delivery` block — `firstSentOn`, `lastSentOn`, `totalSent`, +Each recipient also carries a `delivery` block: `firstSentOn`, `lastSentOn`, `totalSent`, `reminderCount`, `lastRemindedAt`, `warningCount`, `lastWarningAt`. It counts the signature request, resends, reminders, expiry warnings and terminal notices; CC notifications are excluded, since a CC address is not a signer. :::warning `reminderCount` and `lastRemindedAt` do not mean what their names suggest -`reminderCount` counts **automatic (scheduled) reminders only** — the counter `maxReminders` +`reminderCount` counts **automatic (scheduled) reminders only**: the counter `maxReminders` caps. A manual "remind now" is a standalone nudge that must not consume the cap budget, so it does **not** increment this, even though the email it sends *does* appear in `totalSent`. @@ -491,7 +491,7 @@ signature-request send, each scheduled reminder, each manual "remind now" and ea warning all stamp it. Only scheduled reminders bump `reminderCount`. So a freshly-sent document returns a non-null `lastRemindedAt` equal to the invitation -timestamp alongside `reminderCount: 0` — nobody has been reminded. To answer "have we actually +timestamp alongside `reminderCount: 0`: nobody has been reminded. To answer "have we actually chased this person", read `totalSent`, not `reminderCount`. `warningCount` / `lastWarningAt` have no such caveat. @@ -541,7 +541,7 @@ ResendEmailResponse result = client.turboSign().resendEmail( ### Send reminder -Send a standalone reminder to whoever's turn it is to sign (`POST /turbosign/documents/:id/send-reminder`). It is independent of the automatic reminder cadence — it works even when reminders are disabled or the `maxReminders` cap is spent, does **not** consume that cap, and only emails signers at the **current** signing order. Use the single-arg overload to remind everyone eligible; pass a list to limit it to specific recipients, but do **not** pass an empty list, which the API rejects. +Send a standalone reminder to whoever's turn it is to sign (`POST /turbosign/documents/:id/send-reminder`). It is independent of the automatic reminder cadence: it works even when reminders are disabled or the `maxReminders` cap is spent, does **not** consume that cap, and only emails signers at the **current** signing order. Use the single-arg overload to remind everyone eligible; pass a list to limit it to specific recipients, but do **not** pass an empty list, which the API rejects. ```java // Remind everyone whose turn it is @@ -549,7 +549,7 @@ SendReminderResponse reminder = client.turboSign().sendReminder("document-uuid") for (SendReminderResponse.ReminderResult r : reminder.getResults()) { // status is e.g. "sent", "skipped_wrong_order", "skipped_completed" - System.out.println(r.getRecipientId() + " — " + r.getStatus()); + System.out.println(r.getRecipientId() + ": " + r.getStatus()); } // Or limit to specific recipients @@ -560,7 +560,7 @@ client.turboSign().sendReminder("document-uuid", Arrays.asList("recipient-uuid-1 ## Error Handling -The SDK provides typed exceptions for different error scenarios: +Every typed exception is a nested static class of `TurboDocxException` (`TurboDocxException.ValidationException`, not a separate top-level import) and extends `RuntimeException`, so the compiler never forces a catch: ### Error Types @@ -581,7 +581,7 @@ The SDK provides typed exceptions for different error scenarios: | ----------------- | -------- | ---------------------------- | | `getMessage()` | `String` | Human-readable error message | | `getStatusCode()` | `int` | HTTP status code | -| `getCode()` | `String` | Error code (if available) | +| `getCode()` | `String` | Machine-readable code; each of the 7 named subclasses falls back to its own default (e.g. `AuthenticationException`'s `AUTHENTICATION_ERROR`) whenever the API response carries none. The bare `TurboDocxException` thrown for an unmapped status (e.g. an unexpected 5xx) can return `null` | ### Example @@ -660,53 +660,9 @@ The coordinate-based constructor takes positional arguments in this order: `new | `required` | `Boolean` | No | Make field required | | `backgroundColor` | `String` | No | Background color | | `template` | `TemplateAnchor` | No | Template anchor configuration | -| `metadata` | `FieldMetadata` | No | Conditional (IF/THEN) metadata — see below | \*Required when not using template anchors -#### Metadata Configuration (Conditional Fields) - -The optional `metadata` builds IF/THEN relationships between fields. Put a `fieldKey` on a -controlling `checkbox`, then point each dependent field's `conditional.controllingFieldKey` back -at it. - -| Property | Type | Required | Description | -| ----------------------------------- | ----------------------- | -------- | ------------------------------------------------------------- | -| `fieldKey` | `String` | No | Stable id on a **controlling checkbox** (`type: "checkbox"`). | -| `conditional` | `FieldConditional` | No | Rule on a **dependent field** (see below). | -| `conditional.controllingFieldKey` | `String` | Yes | The controlling checkbox's `fieldKey`. Must be non-empty. | -| `conditional.operator` | `String` | Yes | `"is_checked"` or `"is_not_checked"`. | -| `conditional.action` | `String` | Yes | `"show"` (hidden until met) or `"unlock"` (locked until met). | - -`FieldMetadata` and `FieldConditional` are top-level model classes — import them with -`import com.turbodocx.models.*;`. `Field` is immutable and built with `Field.Builder` (there are -no setters), so attach the metadata while building the field. - -```java -import com.turbodocx.models.*; - -// Controlling checkbox — carries a stable fieldKey -Field checkbox = new Field.Builder() - .type("checkbox") - .recipientEmail("reviewer@company.com") - .page(1).x(100).y(400).width(20).height(20) - .metadata(FieldMetadata.forFieldKey("request_changes")) - .build(); - -// Dependent text field — hidden until the checkbox is checked -Field explain = new Field.Builder() - .type("text") - .recipientEmail("reviewer@company.com") - .page(1).x(130).y(400).width(300).height(60) - .metadata(FieldMetadata.forConditional( - new FieldConditional("request_changes", "is_checked", "show"))) - .build(); -``` - -A malformed rule returns `400 InvalidConditionalRule`; a well-formed rule whose -`controllingFieldKey` matches no checkbox **fails open** (the field stays visible/editable). See -[Conditional (IF/THEN) Fields](/docs/TurboSign/Conditional%20Fields). - #### Template Configuration When using `template` instead of coordinates: @@ -762,5 +718,5 @@ For detailed information about advanced configuration and API concepts, see: - [GitHub Repository](https://github.com/TurboDocx/SDK/tree/main/packages/java-sdk) - [Maven Central](https://search.maven.org/artifact/com.turbodocx/turbodocx-sdk) -- [API Reference](/docs/TurboSign/API-Signatures) +- [API Reference](/docs/TurboSign/API%20Signatures) - [Webhook Configuration](/docs/TurboSign/Webhooks) diff --git a/docs/SDKs/javascript.md b/docs/SDKs/javascript.md index 32e30d58..7cacc920 100644 --- a/docs/SDKs/javascript.md +++ b/docs/SDKs/javascript.md @@ -427,7 +427,7 @@ const result = await TurboSign.sendSignature({ :::tip Pass a file path directly -`file` accepts `string | File | Buffer`. A `string` is treated as a local file path — the SDK reads it and uses the basename as the document filename, so `file: "./contract.pdf"` works without `readFileSync`. A raw `Blob` is not supported; use a `Buffer` (Node) or a `File` (browser). +`file` accepts `string | File | Buffer`. A `string` is treated as a local file path: the SDK reads it and uses the basename as the document filename, so `file: "./contract.pdf"` works without `readFileSync`. A raw `Blob` is not supported; use a `Buffer` (Node) or a `File` (browser). When `file` is a `Buffer`, the filename defaults to `document.pdf` (extension detected from the content). Pass `fileName` to control it: @@ -783,7 +783,7 @@ const { documentId } = await TurboSign.sendSignature({ ### Reminders & expiration schedule -`sendSignature` (and `createSignatureReviewLink`) accept an optional **reminder and expiration schedule**. Both features are **off by default** — omit these fields and the send behaves exactly as before. The resolved schedule is **frozen onto the document when it is sent**, so later changes to your org defaults never touch a document already out for signature. +`sendSignature` (and `createSignatureReviewLink`) accept an optional **reminder and expiration schedule**. Both features are **off by default**: omit these fields and the send behaves exactly as before. The resolved schedule is **frozen onto the document when it is sent**, so later changes to your org defaults never touch a document already out for signature. @@ -792,13 +792,13 @@ const { documentId } = await TurboSign.sendSignature({ const result = await TurboSign.sendSignature({ // ...fileLink, recipients, fields, etc. - // Reminders — nudge signers who haven't signed yet + // Reminders: nudge signers who haven't signed yet remindersEnabled: true, reminderDelay: { value: 3, unit: "days" }, // time to the FIRST reminder reminderInterval: { value: 3, unit: "days" }, // gap between later reminders maxReminders: 5, // cap per signer - // Expiration — close the signing window + // Expiration: close the signing window expirationEnabled: true, expireAfter: { value: 30, unit: "days" }, // how long the document stays signable expirationWarning: { value: 3, unit: "days" }, // how far before expiry warnings start @@ -813,13 +813,13 @@ const result = await TurboSign.sendSignature({ const result = await TurboSign.sendSignature({ // ...fileLink, recipients, fields, etc. - // Reminders — nudge signers who haven't signed yet + // Reminders: nudge signers who haven't signed yet remindersEnabled: true, reminderDelay: { value: 3, unit: "days" }, // time to the FIRST reminder reminderInterval: { value: 3, unit: "days" }, // gap between later reminders maxReminders: 5, // cap per signer - // Expiration — close the signing window + // Expiration: close the signing window expirationEnabled: true, expireAfter: { value: 30, unit: "days" }, // how long the document stays signable expirationWarning: { value: 3, unit: "days" }, // how far before expiry warnings start @@ -830,20 +830,20 @@ const result = await TurboSign.sendSignature({ -Durations are `{ value, unit }` objects — `unit` is `"hours"` or `"days"`, and `value` is a whole number from **1 to a maximum of 999 days (23976 hours)**. +Durations are `{ value, unit }` objects: `unit` is `"hours"` or `"days"`, and `value` is a whole number from **1 to a maximum of 999 days (23976 hours)**. | Field | Type | Default | Notes | | --- | --- | --- | --- | | `remindersEnabled` | `boolean` | `false` | Send reminder emails at all | | `reminderDelay` | `Duration` | 3 days | Time to the **first** reminder, measured from that signer's invitation | | `reminderInterval` | `Duration` | 3 days | Gap between **subsequent** reminders | -| `maxReminders` | `number` | `5` | Cap per signer, range **-1..50** — `-1` unlimited, `0` none. Never caps expiry warnings | +| `maxReminders` | `number` | `5` | Cap per signer, range **-1..50** (`-1` unlimited, `0` none). Never caps expiry warnings | | `expirationEnabled` | `boolean` | `false` | Expire the document at all | | `expireAfter` | `Duration` | 120 days | How long the document stays signable, counted from **sending** | | `expirationWarning` | `Duration` | 3 days | How far **before** expiry warnings start. `0` = never warn | | `expirationWarningInterval` | `Duration` | 1 day | Gap between warnings once they start | -Reminders and expiry warnings run as **two independent clocks**, so a signer keeps getting reminders even after warnings begin; the two are coordinated so a reminder and a warning never land on the same tick. The API rejects a cadence that can't fit its window — for example a reminder interval that outlives `expireAfter` — with `400 InvalidSignatureSchedule`. See the [API validation rules](/docs/TurboSign/API%20Signatures#reminders--expiration) for the full list. +Reminders and expiry warnings run as **two independent clocks**, so a signer keeps getting reminders even after warnings begin; the two are coordinated so a reminder and a warning never land on the same tick. The API rejects a cadence that can't fit its window (for example a reminder interval that outlives `expireAfter`) with `400 InvalidSignatureSchedule`. See the [API validation rules](/docs/TurboSign/API%20Signatures#reminders--expiration) for the full list. ### Send reminder @@ -853,7 +853,7 @@ Send a **standalone reminder** to whoever's turn it is to sign. Unlike the sched ```javascript -// Remind everyone whose turn it is — omit the recipient ids +// Remind everyone whose turn it is: omit the recipient ids const { results } = await TurboSign.sendReminder("document-uuid"); results.forEach((r) => { @@ -881,7 +881,7 @@ await TurboSign.sendReminder("document-uuid", ["recipient-uuid-1"]); -:::warning Omit — don't send an empty array +:::warning Omit: don't send an empty array To remind everyone eligible, **omit** `recipientIds` entirely. Passing an empty array (`[]`) is rejected with a `400`. ::: @@ -910,7 +910,7 @@ console.log(result.status); // 'under_review' | 'completed' | 'voided' | ... -The response carries the document-level **`status`** (`under_review`, `completed`, `voided`, `expired`, …) and **`expiresAt`** — the ISO 8601 signing-window deadline, or `undefined`/`null` when expiration is off. Once that deadline passes the document moves to the terminal **`expired`** status and its signing links stop working. The same `document.expiresAt` is returned by `getRecipients()` alongside per-recipient detail. +The response carries the document-level **`status`** (`under_review`, `completed`, `voided`, `expired`, …) and **`expiresAt`** (the ISO 8601 signing-window deadline, or `undefined`/`null` when expiration is off). Once that deadline passes the document moves to the terminal **`expired`** status and its signing links stop working. The same `document.expiresAt` is returned by `getRecipients()` alongside per-recipient detail. ### Get recipients @@ -950,7 +950,7 @@ const chasing = recipients.filter( :::tip Two status fields, and they differ on purpose `status` is the raw database value and is only ever `pending`, `viewed` or `completed`. -`effectiveStatus` layers the document's outcome on top, adding `voided` and `expired` — that +`effectiveStatus` layers the document's outcome on top, adding `voided` and `expired`: that is the one to display. On a voided or expired document an unsigned signer still reads `pending` in `status`, so @@ -963,14 +963,14 @@ the document is terminal. ::: -Each recipient also carries a `delivery` block — `firstSentOn`, `lastSentOn`, `totalSent`, +Each recipient also carries a `delivery` block: `firstSentOn`, `lastSentOn`, `totalSent`, `reminderCount`, `lastRemindedAt`, `warningCount`, `lastWarningAt`. It counts the signature request, resends, reminders, expiry warnings and terminal notices; CC notifications are excluded, since a CC address is not a signer. :::warning `reminderCount` and `lastRemindedAt` do not mean what their names suggest -`reminderCount` counts **automatic (scheduled) reminders only** — the counter `maxReminders` +`reminderCount` counts **automatic (scheduled) reminders only**: the counter `maxReminders` caps. A manual "remind now" is a standalone nudge that must not consume the cap budget, so it does **not** increment this, even though the email it sends *does* appear in `totalSent`. @@ -979,7 +979,7 @@ signature-request send, each scheduled reminder, each manual "remind now" and ea warning all stamp it. Only scheduled reminders bump `reminderCount`. So a freshly-sent document returns a non-null `lastRemindedAt` equal to the invitation -timestamp alongside `reminderCount: 0` — nobody has been reminded. To answer "have we actually +timestamp alongside `reminderCount: 0`: nobody has been reminded. To answer "have we actually chased this person", read `totalSent`, not `reminderCount`. `warningCount` / `lastWarningAt` have no such caveat. @@ -1099,7 +1099,7 @@ console.log(JSON.stringify(result, null, 2)); ## Error Handling -The SDK provides typed error classes for different failure scenarios. All errors extend the base `TurboDocxError` class. +All errors are real `Error` subclasses (`instanceof` works) that extend the base `TurboDocxError`. `code` is a plain string, not an enum member: the HTTP client passes the API's own code through when the response includes one (for example `QUOTE_NOT_FOUND`), and only falls back to the class default below when it doesn't, so you can branch on `err.code` for the precise reason instead of just the HTTP category. ### Error Classes @@ -1231,7 +1231,7 @@ try { ### Error Properties -All errors include these properties: +All errors include these `readonly` properties: | Property | Type | Description | | ------------ | --------------------- | -------------------------------- | @@ -1307,7 +1307,7 @@ Field configuration supporting both coordinate-based and template-based position | `required` | `boolean` | No | Whether field is required | | `backgroundColor` | `string` | No | Background color (hex, rgb, or named) | | `template` | `object` | No | Template anchor configuration | -| `metadata` | `object` | No | Conditional (IF/THEN) metadata — see below | +| `metadata` | `object` | No | Conditional (IF/THEN) metadata, see below | \*Required when not using template anchors @@ -1374,7 +1374,7 @@ Request configuration for `createSignatureReviewLink` and `sendSignature` method | Property | Type | Required | Description | | --------------------- | ------------- | ----------- | ------------------------------ | | `file` | `string \| File \| Buffer` | Conditional | Document as a local file path, `Buffer`, or browser `File` | -| `fileName` | `string` | No | Original filename — used when `file` is a `Buffer` (defaults to `document.`) | +| `fileName` | `string` | No | Original filename, used when `file` is a `Buffer` (defaults to `document.`) | | `fileLink` | `string` | Conditional | URL to document file | | `deliverableId` | `string` | Conditional | TurboDocx deliverable ID | | `templateId` | `string` | Conditional | TurboDocx template ID | @@ -1382,17 +1382,17 @@ Request configuration for `createSignatureReviewLink` and `sendSignature` method | `fields` | `Field[]` | Yes | Signature fields configuration | | `documentName` | `string` | No | Document name | | `documentDescription` | `string` | No | Document description | -| `senderName` | `string` | No | Sender name — falls back to `senderName` in the SDK config, then your API key's name | -| `senderEmail` | `string` | Conditional | Sender email — **required on the request** unless supplied via `TurboSign.configure({ senderEmail })` or `TURBODOCX_SENDER_EMAIL` | +| `senderName` | `string` | No | Sender name, falls back to `senderName` in the SDK config, then your API key's name | +| `senderEmail` | `string` | Conditional | Sender email, **required on the request** unless supplied via `TurboSign.configure({ senderEmail })` or `TURBODOCX_SENDER_EMAIL` | | `ccEmails` | `string[]` | No | Array of CC email addresses | | `remindersEnabled` | `boolean` | No | Send reminder emails to signers who haven't signed (default `false`) | -| `reminderDelay` | `Duration` | No | `{ value, unit }` — time to the first reminder | -| `reminderInterval` | `Duration` | No | `{ value, unit }` — gap between later reminders | +| `reminderDelay` | `Duration` | No | `{ value, unit }`, time to the first reminder | +| `reminderInterval` | `Duration` | No | `{ value, unit }`, gap between later reminders | | `maxReminders` | `number` | No | Cap per signer, range **-1..50** (`-1` unlimited, `0` none, default `5`) | | `expirationEnabled` | `boolean` | No | Close the signing window after `expireAfter` (default `false`) | -| `expireAfter` | `Duration` | No | `{ value, unit }` — how long the document stays signable | -| `expirationWarning` | `Duration` | No | `{ value, unit }` — how far before expiry warnings start (`0` = never warn) | -| `expirationWarningInterval` | `Duration` | No | `{ value, unit }` — gap between warnings once they start | +| `expireAfter` | `Duration` | No | `{ value, unit }`, how long the document stays signable | +| `expirationWarning` | `Duration` | No | `{ value, unit }`, how far before expiry warnings start (`0` = never warn) | +| `expirationWarningInterval` | `Duration` | No | `{ value, unit }`, gap between warnings once they start | :::info Durations A `Duration` is `{ value: number, unit: "hours" | "days" }`. `value` is a whole number from **1 to 999 days (23976 hours)**. @@ -1402,11 +1402,14 @@ A `Duration` is `{ value: number, unit: "hours" | "days" }`. `value` is a whole Exactly one file source is required: `file`, `fileLink`, `deliverableId`, or `templateId`. ::: -:::caution Sender identity is always required for TurboSign +:::caution Sender email is enforced by the SDK, not by a `SenderEmailRequired`/`SenderNameRequired` API error Unlike TurboQuote (where the sender comes from the org quote template and there is no per-request -field), TurboSign resolves the sender **from the request body**. If no sender email can be resolved -from the request, the SDK config, or the environment, the API returns `400 SenderEmailRequired`; -if no sender name can be resolved it returns `400 SenderNameRequired`. +field), TurboSign expects the sender to come from the request body, `TurboSign.configure({ senderEmail })`, +or the `TURBODOCX_SENDER_EMAIL` environment variable. The **SDK enforces this itself**: `TurboSign.configure()` +throws a `ValidationError` if no `senderEmail` is configured (client-side, before any request is sent). +The API itself does not reject a send that omits a sender: if no sender email or name can be resolved, +it falls back to a generic TurboDocx sender identity rather than returning `400 SenderEmailRequired` or +`400 SenderNameRequired`. ::: --- diff --git a/docs/SDKs/partner-go.md b/docs/SDKs/partner-go.md index f776753a..2440a5d2 100644 --- a/docs/SDKs/partner-go.md +++ b/docs/SDKs/partner-go.md @@ -27,12 +27,12 @@ import QuickstartSkillNudge from '@site/src/components/QuickstartSkillNudge'; TurboPartner is available for integrators and partners. [Contact us](https://www.turbodocx.com/demo) to get started. ::: -The official TurboDocx Partner SDK for Go applications. Build multi-tenant SaaS applications with programmatic organization management, user provisioning, API key management, and entitlement control. Zero dependencies — standard library only. +The official TurboDocx Partner SDK for Go applications. Build multi-tenant SaaS applications with programmatic organization management, user provisioning, API key management, and entitlement control. Zero dependencies: standard library only.
:::info What is TurboPartner? -TurboPartner is the partner management API for TurboDocx. It allows you to programmatically create and manage organizations, users, API keys, and feature entitlements — perfect for building white-label or multi-tenant applications on top of TurboDocx. +TurboPartner is the partner management API for TurboDocx. It allows you to programmatically create and manage organizations, users, API keys, and feature entitlements, perfect for building white-label or multi-tenant applications on top of TurboDocx. ::: ## TLDR @@ -80,7 +80,7 @@ func main() { Name: "Production Key", Role: "admin", }) - fmt.Printf("API Key: %s\n", key.Data.Key) // Save this — only shown once! + fmt.Printf("API Key: %s\n", key.Data.Key) // Save this, only shown once! } ``` @@ -98,7 +98,7 @@ go get github.com/TurboDocx/SDK/packages/go-sdk - No external dependencies (standard library only) :::tip Zero Dependencies -The Go SDK uses only the standard library — no third-party packages required. This makes it easy to integrate into any Go project. +The Go SDK uses only the standard library: no third-party packages required. This makes it easy to integrate into any Go project. ::: --- @@ -440,7 +440,7 @@ fmt.Printf("Full Key: %s\n", result.Data.Key) // Only shown once! ``` :::caution Save Your API Key -The full API key is only returned once during creation. Store it securely — you won't be able to retrieve it again. +The full API key is only returned once during creation. Store it securely: you won't be able to retrieve it again. ::: ### `ListOrganizationAPIKeys()` @@ -551,11 +551,11 @@ result, err := partner.RevokePartnerAPIKey(ctx, "partner-key-uuid-here") ## Partner User Management :::danger Partner users use a different role enum -Partner portal users take `admin`, `member`, or `viewer`. **Organization** users and organization API keys take `admin`, `contributor`, `user`, or `viewer`. The two enums do not overlap beyond `admin`/`viewer` — `"member"` is rejected on an org call, and `"contributor"`/`"user"` are rejected on a partner call. See [Role Enums](#organization-user-roles). +Partner portal users take `admin`, `member`, or `viewer`. **Organization** users and organization API keys take `admin`, `contributor`, `user`, or `viewer`. The two enums do not overlap beyond `admin`/`viewer`: `"member"` is rejected on an org call, and `"contributor"`/`"user"` are rejected on a partner call. See [Role Enums](#organization-user-roles). ::: :::caution `Permissions` is all-or-nothing -The `Permissions` object itself is optional, but if you send it, **all seven fields are required**. There is no partial permissions update — the API rejects an incomplete object with `*ValidationError` (400). Because `PartnerPermissions` is a struct of plain `bool`s, any field you leave out silently serializes as `false` rather than "unchanged": read the current values first and re-send them with your change applied. +The `Permissions` object itself is optional, but if you send it, **all seven fields are required**. There is no partial permissions update: the API rejects an incomplete object with `*ValidationError` (400). Because `PartnerPermissions` is a struct of plain `bool`s, any field you leave out silently serializes as `false` rather than "unchanged": read the current values first and re-send them with your change applied. ::: ### `AddUserToPartnerPortal()` @@ -599,7 +599,7 @@ for _, user := range result.Data.Results { ### `UpdatePartnerUserPermissions()` -Update a partner user's role and permissions. If you set `Permissions`, populate **all seven fields** — a partial object is a 400, and unset bools default to `false`. +Update a partner user's role and permissions. If you set `Permissions`, populate **all seven fields**: a partial object is a 400, and unset bools default to `false`. ```go result, err := partner.UpdatePartnerUserPermissions(ctx, "partner-user-uuid-here", @@ -707,14 +707,14 @@ These are limits and capabilities you can configure for each organization: :::tip Pointer Helpers Use the provided helper functions for setting optional fields: -- `turbodocx.IntPtr(25)` — for `*int` fields -- `turbodocx.Int64Ptr(5368709120)` — for `*int64` fields (storage) -- `turbodocx.BoolPtr(true)` — for `*bool` fields +- `turbodocx.IntPtr(25)`, for `*int` fields +- `turbodocx.Int64Ptr(5368709120)`, for `*int64` fields (storage) +- `turbodocx.BoolPtr(true)`, for `*bool` fields ::: ### Tracking (Usage Counters) -Current consumption against the limits above. TurboDocx maintains these automatically, but `UpdateOrganizationEntitlements()` **accepts a `Tracking` object** — useful for seeding counters when migrating an existing customer: +Current consumption against the limits above. TurboDocx maintains these automatically, but `UpdateOrganizationEntitlements()` **accepts a `Tracking` object**, useful for seeding counters when migrating an existing customer: | Field | Type | Description | |-------|------|-------------| @@ -737,7 +737,7 @@ Every counter except `CurrentAICredits` floors at `0`. Only `CurrentAICredits` a ## Preferences Reference -TurboSign display preferences you can read and set per organization. Every key is a boolean and is validated strictly — the strings `"true"` / `"false"` are rejected with a 400, so pass real booleans. The API returns only these keys and never any of the organization's other settings. +TurboSign display preferences you can read and set per organization. Every key is a boolean and is validated strictly: the strings `"true"` / `"false"` are rejected with a 400, so pass real booleans. The API returns only these keys and never any of the organization's other settings. | Field | Type | Default | Description | |-------|------|---------|-------------| @@ -841,7 +841,7 @@ permissions := turbodocx.PartnerPermissions{ ## Error Handling -The SDK provides typed errors for different error scenarios: +`partner.CreateOrganization` and the other partner calls return `AuthorizationError` when the partner API key lacks the scope for the route, since partner keys are scoped separately from organization keys: ```go import "errors" @@ -852,6 +852,7 @@ if err != nil { var authzErr *turbodocx.AuthorizationError var validErr *turbodocx.ValidationError var notFoundErr *turbodocx.NotFoundError + var conflictErr *turbodocx.ConflictError var rateLimitErr *turbodocx.RateLimitError var networkErr *turbodocx.NetworkError @@ -868,6 +869,9 @@ if err != nil { case errors.As(err, ¬FoundErr): // 404 - Organization or resource not found fmt.Printf("Not found: %s\n", notFoundErr.Message) + case errors.As(err, &conflictErr): + // 409 - Resource conflict (e.g. AddUserToPartnerPortal on an existing user) + fmt.Printf("Conflict: %s\n", conflictErr.Message) case errors.As(err, &rateLimitErr): // 429 - Rate limit exceeded fmt.Printf("Rate limit: %s\n", rateLimitErr.Message) @@ -880,17 +884,7 @@ if err != nil { } ``` -### Error Types - -| Error Type | Status Code | Description | -|------------|-------------|-------------| -| `TurboDocxError` | varies | Base error for all SDK errors | -| `AuthenticationError` | 401 | Invalid or missing API credentials | -| `AuthorizationError` | 403 | Authenticated but the key lacks the required scope | -| `ValidationError` | 400 | Invalid request parameters | -| `NotFoundError` | 404 | Resource not found | -| `RateLimitError` | 429 | Too many requests | -| `NetworkError` | - | Network connectivity issues | +The full typed-error table and HTTP status mapping is documented once in the [Go SDK's Error Handling reference](./go.md#error-handling); partner calls use the same `AuthenticationError`/`AuthorizationError`/`ValidationError`/`NotFoundError`/`ConflictError`/`RateLimitError`/`NetworkError` types (for example, `AddUserToPartnerPortal()` returns a `*ConflictError` (409) when the target user already has partner-portal access). --- @@ -977,4 +971,4 @@ func main() { - [GitHub Repository](https://github.com/TurboDocx/SDK/tree/main/packages/go-sdk) - [Go Package Reference](https://pkg.go.dev/github.com/TurboDocx/SDK/packages/go-sdk) -- [TurboSign Go SDK](/docs/SDKs/go) — For digital signature operations +- [TurboSign Go SDK](/docs/SDKs/go): for digital signature operations diff --git a/docs/SDKs/partner-java.md b/docs/SDKs/partner-java.md index 9e806f37..35319961 100644 --- a/docs/SDKs/partner-java.md +++ b/docs/SDKs/partner-java.md @@ -32,7 +32,7 @@ The official TurboDocx Partner SDK for Java applications. Build multi-tenant Saa
:::info What is TurboPartner? -TurboPartner is the partner management API for TurboDocx. It allows you to programmatically create and manage organizations, users, API keys, and feature entitlements — perfect for building white-label or multi-tenant applications on top of TurboDocx. +TurboPartner is the partner management API for TurboDocx. It allows you to programmatically create and manage organizations, users, API keys, and feature entitlements, perfect for building white-label or multi-tenant applications on top of TurboDocx. ::: ## TLDR @@ -66,7 +66,7 @@ public class Main { // 4. Create an API key JsonObject key = client.turboPartner().createOrganizationApiKey(orgId, "Production Key", "admin"); - System.out.println("API Key: " + key.getAsJsonObject("data").get("key").getAsString()); // Save this — only shown once! + System.out.println("API Key: " + key.getAsJsonObject("data").get("key").getAsString()); // Save this, only shown once! } } ``` @@ -82,7 +82,7 @@ public class Main { com.turbodocx turbodocx-sdk - 0.5.0 + 0.7.0 ``` @@ -90,14 +90,14 @@ public class Main { ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.5.0") +implementation("com.turbodocx:turbodocx-sdk:0.7.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.5.0' +implementation 'com.turbodocx:turbodocx-sdk:0.7.0' ``` @@ -156,7 +156,7 @@ export TURBODOCX_PARTNER_ID=your-partner-uuid ``` :::info Responses are raw `JsonObject` -Every `TurboPartner` method returns a Gson `JsonObject` containing the raw API response — `success`, `data`, and sometimes `message`. Unlike the TurboSign and Deliverable modules, partner responses are **not** unwrapped into typed models, so read them with `getAsJsonObject("data")`, `getAsJsonArray("results")`, `getAsString()`, and friends. Iterating a results array needs `com.google.gson.JsonElement` alongside `com.google.gson.JsonObject`. Every method throws `IOException` on transport failure. +Every `TurboPartner` method returns a Gson `JsonObject` containing the raw API response: `success`, `data`, and sometimes `message`. Unlike the TurboSign and Deliverable modules, partner responses are **not** unwrapped into typed models, so read them with `getAsJsonObject("data")`, `getAsJsonArray("results")`, `getAsString()`, and friends. Iterating a results array needs `com.google.gson.JsonElement` alongside `com.google.gson.JsonObject`. Every method throws `IOException` on transport failure. ::: --- @@ -269,7 +269,7 @@ JsonObject result = client.turboPartner().updateOrganizationInfo( ### `updateOrganizationEntitlements()` -Update an organization's feature limits and capabilities. Both `features` and `tracking` are optional — pass `null` for the one you are not changing. +Update an organization's feature limits and capabilities. Both `features` and `tracking` are optional: pass `null` for the one you are not changing. ```java Map features = new LinkedHashMap<>(); @@ -442,7 +442,7 @@ System.out.println("Full Key: " + data.get("key").getAsString()); // Only shown ``` :::caution Save Your API Key -The full API key is only returned once during creation. Store it securely — you won't be able to retrieve it again. +The full API key is only returned once during creation. Store it securely: you won't be able to retrieve it again. ::: ### `listOrganizationApiKeys()` @@ -534,7 +534,7 @@ for (JsonElement element : result.getAsJsonObject("data").getAsJsonArray("result ### `updatePartnerApiKey()` -Update a partner API key. The argument order is `keyId, name, description, scopes` — pass `null` for anything you want to leave unchanged. +Update a partner API key. The argument order is `keyId, name, description, scopes`: pass `null` for anything you want to leave unchanged. ```java JsonObject result = client.turboPartner().updatePartnerApiKey( @@ -558,11 +558,11 @@ JsonObject result = client.turboPartner().revokePartnerApiKey("partner-key-uuid- ## Partner User Management :::danger Partner users use different role values -Partner portal users take `"admin"`, `"member"`, or `"viewer"`. **Organization** users and organization API keys take `"admin"`, `"contributor"`, `"user"`, or `"viewer"`. The two sets do not overlap beyond `admin`/`viewer` — `"member"` is rejected on an org call, and `"contributor"`/`"user"` are rejected on a partner call. See [Role Values](#role-values). +Partner portal users take `"admin"`, `"member"`, or `"viewer"`. **Organization** users and organization API keys take `"admin"`, `"contributor"`, `"user"`, or `"viewer"`. The two sets do not overlap beyond `admin`/`viewer`: `"member"` is rejected on an org call, and `"contributor"`/`"user"` are rejected on a partner call. See [Role Values](#role-values). ::: :::caution `permissions` is all-or-nothing -`addUserToPartnerPortal()` **requires** a permissions map containing all seven keys. On `updatePartnerUserPermissions()` the map is optional (`null` keeps the current values), but if you send it, **all seven keys are required**. There is no partial permissions update — the API rejects an incomplete map with `TurboDocxException.ValidationException` (400). Read the current values first and re-send them with your change applied. +`addUserToPartnerPortal()` **requires** a permissions map containing all seven keys. On `updatePartnerUserPermissions()` the map is optional (`null` keeps the current values), but if you send it, **all seven keys are required**. There is no partial permissions update: the API rejects an incomplete map with `TurboDocxException.ValidationException` (400). Read the current values first and re-send them with your change applied. ::: ### `addUserToPartnerPortal()` @@ -573,7 +573,7 @@ Add a user to the partner portal with specific permissions. import java.util.LinkedHashMap; import java.util.Map; -// Required on add — all 7 keys must be present. +// Required on add: all 7 keys must be present. Map permissions = new LinkedHashMap<>(); permissions.put("canManageOrgs", true); // Create, update, delete organizations permissions.put("canManageOrgUsers", true); // Manage users within organizations @@ -607,7 +607,7 @@ for (JsonElement element : result.getAsJsonObject("data").getAsJsonArray("result ### `updatePartnerUserPermissions()` -Update a partner user's role and/or permissions. Pass `null` for `role` or `permissions` to keep the current value — but if you pass `permissions`, supply **all seven keys**; a partial map is a 400. +Update a partner user's role and/or permissions. Pass `null` for `role` or `permissions` to keep the current value, but if you pass `permissions`, supply **all seven keys**; a partial map is a 400. ```java Map permissions = new LinkedHashMap<>(); @@ -648,7 +648,7 @@ JsonObject result = client.turboPartner().removeUserFromPartnerPortal("partner-u ### `getPartnerAuditLogs()` -Get audit logs for all partner activities with filtering. All nine arguments are positional — pass `null` for any filter you don't want. +Get audit logs for all partner activities with filtering. All nine arguments are positional: pass `null` for any filter you don't want. ```java JsonObject result = client.turboPartner().getPartnerAuditLogs( @@ -722,12 +722,12 @@ These are limits and capabilities you can configure for each organization: | `enableBulkSending` | boolean | Enable bulk document sending | :::info Map keys stay camelCase -The `features`, `tracking`, and `permissions` maps are serialized straight into the JSON request body, so the keys must match exactly as written above (`maxUsers`, `hasTDAI`, `canManageOrgAPIKeys`) — Java naming conventions do not apply to request-body keys. +The `features`, `tracking`, and `permissions` maps are serialized straight into the JSON request body, so the keys must match exactly as written above (`maxUsers`, `hasTDAI`, `canManageOrgAPIKeys`): Java naming conventions do not apply to request-body keys. ::: ### Tracking (Usage Counters) -Current consumption against the limits above. TurboDocx maintains these automatically, but `updateOrganizationEntitlements()` **accepts a `tracking` map** — useful for seeding counters when migrating an existing customer: +Current consumption against the limits above. TurboDocx maintains these automatically, but `updateOrganizationEntitlements()` **accepts a `tracking` map**, useful for seeding counters when migrating an existing customer: | Field | Type | Description | |-------|------|-------------| @@ -746,7 +746,7 @@ Every counter except `currentAICredits` floors at `0`. Only `currentAICredits` a ## Preferences Reference -TurboSign display preferences you can read and set per organization. Every key is a boolean and is validated strictly — the strings `"true"` / `"false"` are rejected with a 400, so pass real booleans. The API returns only these keys and never any of the organization's other settings. +TurboSign display preferences you can read and set per organization. Every key is a boolean and is validated strictly: the strings `"true"` / `"false"` are rejected with a 400, so pass real booleans. The API returns only these keys and never any of the organization's other settings. | Field | Type | Default | Description | |-------|------|---------|-------------| @@ -763,7 +763,7 @@ TurboSign display preferences you can read and set per organization. Every key i ### PartnerScope (22 Scopes) -`com.turbodocx.PartnerScope` is a constants class of `String` values — there is no scope enum. Pass them as a `List` to `createPartnerApiKey()` and `updatePartnerApiKey()`. +`com.turbodocx.PartnerScope` is a constants class of `String` values: there is no scope enum. Pass them as a `List` to `createPartnerApiKey()` and `updatePartnerApiKey()`. ```java import com.turbodocx.PartnerScope; @@ -807,9 +807,9 @@ PartnerScope.AUDIT_READ // "audit:read" ### Role Values -Roles are plain `String` values in the Java SDK — there is no role enum. +Roles are plain `String` values in the Java SDK: there is no role enum. -**Organization users and organization API keys** — used by `addUserToOrganization()`, `updateOrganizationUserRole()`, `createOrganizationApiKey()`, and `updateOrganizationApiKey()`: +**Organization users and organization API keys**, used by `addUserToOrganization()`, `updateOrganizationUserRole()`, `createOrganizationApiKey()`, and `updateOrganizationApiKey()`: | Value | Description | | --------------- | ---------------------------- | @@ -818,7 +818,7 @@ Roles are plain `String` values in the Java SDK — there is no role enum. | `"user"` | Standard user access | | `"viewer"` | Read-only access | -**Partner portal users** — used by `addUserToPartnerPortal()` and `updatePartnerUserPermissions()` only: +**Partner portal users**, used by `addUserToPartnerPortal()` and `updatePartnerUserPermissions()` only: | Value | Description | | ---------- | -------------------------------------------- | @@ -848,7 +848,7 @@ All seven keys are required whenever a permissions map is sent. Partial maps are ## Error Handling -The SDK provides typed exceptions for different error scenarios. They all extend `TurboDocxException`, which is a `RuntimeException`, so catch it after any checked `IOException` handling: +Partner calls throw `TurboDocxException.AuthenticationException` when the partner API key or partner ID is wrong, since partner credentials are validated separately from organization API keys. Every typed exception extends `TurboDocxException`, a `RuntimeException`, so catch it after any checked `IOException` handling: ```java import com.turbodocx.TurboDocxException; @@ -881,31 +881,14 @@ try { } ``` -### Error Types - -| Error Type | Status Code | Description | -| -------------------------------------------- | ----------- | -------------------------------------------------- | -| `TurboDocxException` | varies | Base exception for all API errors | -| `TurboDocxException.AuthenticationException` | 401 | Invalid or missing partner credentials | -| `TurboDocxException.ValidationException` | 400 | Invalid request parameters | -| `TurboDocxException.AuthorizationException` | 403 | Partner API key lacks the required scope | -| `TurboDocxException.NotFoundException` | 404 | Resource not found | -| `TurboDocxException.RateLimitException` | 429 | Too many requests | +The full typed-exception table and HTTP status mapping is documented once in the [Java SDK's Error Handling reference](./java.md#error-handling); partner calls use the same `AuthenticationException`/`ValidationException`/`AuthorizationException`/`NotFoundException`/`RateLimitException` types. Transport failures are **not** wrapped: the partner client propagates OkHttp's checked `IOException` directly, so catch `IOException` for connectivity problems rather than `TurboDocxException.NetworkException`. -:::caution 409 conflicts arrive as the base exception -`TurboDocxException.ConflictException` exists in the SDK, but the partner client does **not** raise it — a 409 (for example, a user that already exists) surfaces as the base `TurboDocxException` with `getStatusCode() == 409`. Handle it in the base `catch` block rather than adding a `ConflictException` catch, which would never fire on a partner call. +:::tip 409 Conflicts +`TurboDocxException.ConflictException` is raised for 409 responses on partner calls too (for example, a user that already exists), the same way as `AuthenticationException`, `ValidationException`, `AuthorizationException`, `NotFoundException`, and `RateLimitException`. Add a `catch (TurboDocxException.ConflictException e)` block if you want to handle conflicts separately from the base `TurboDocxException` catch-all. ::: -### Error Properties - -| Property | Type | Description | -| ----------------- | -------- | ---------------------------- | -| `getMessage()` | `String` | Human-readable error message | -| `getStatusCode()` | `int` | HTTP status code | -| `getCode()` | `String` | Error code (if available) | - --- ## Complete Example @@ -974,4 +957,4 @@ public class PartnerOnboarding { - [GitHub Repository](https://github.com/TurboDocx/SDK/tree/main/packages/java-sdk) - [Maven Central](https://search.maven.org/artifact/com.turbodocx/turbodocx-sdk) -- [TurboSign Java SDK](/docs/SDKs/java) — For digital signature operations +- [TurboSign Java SDK](/docs/SDKs/java): for digital signature operations diff --git a/docs/SDKs/partner-javascript.md b/docs/SDKs/partner-javascript.md index 67d20d4f..3ed325f9 100644 --- a/docs/SDKs/partner-javascript.md +++ b/docs/SDKs/partner-javascript.md @@ -33,7 +33,7 @@ The official TurboDocx Partner SDK for JavaScript and TypeScript applications. B
:::info What is TurboPartner? -TurboPartner is the partner management API for TurboDocx. It allows you to programmatically create and manage organizations, users, API keys, and feature entitlements — perfect for building white-label or multi-tenant applications on top of TurboDocx. +TurboPartner is the partner management API for TurboDocx. It allows you to programmatically create and manage organizations, users, API keys, and feature entitlements, perfect for building white-label or multi-tenant applications on top of TurboDocx. ::: ## TLDR @@ -69,7 +69,7 @@ const key = await TurboPartner.createOrganizationApiKey(orgId, { name: 'Production Key', role: 'admin', }); -console.log(`API Key: ${key.data.key}`); // Save this — only shown once! +console.log(`API Key: ${key.data.key}`); // Save this, only shown once! ``` --- @@ -90,7 +90,7 @@ pnpm add @turbodocx/sdk - TypeScript 4.7+ (optional, types included) :::tip Full TypeScript Support -This SDK includes complete TypeScript type definitions for all request/response types, enums, and configuration options — no additional `@types` packages needed. +This SDK includes complete TypeScript type definitions for all request/response types, enums, and configuration options: no additional `@types` packages needed. ::: --- @@ -404,7 +404,7 @@ const result = await TurboPartner.createOrganizationApiKey( 'org-uuid-here', { name: 'Production API Key', - role: 'admin', // 'admin' | 'contributor' | 'user' | 'viewer' — the ORG role enum + role: 'admin', // 'admin' | 'contributor' | 'user' | 'viewer' (the ORG role enum) } ); @@ -413,7 +413,7 @@ console.log(`Full Key: ${result.data.key}`); // Only shown once! ``` :::caution Save Your API Key -The full API key is only returned once during creation. Store it securely — you won't be able to retrieve it again. +The full API key is only returned once during creation. Store it securely: you won't be able to retrieve it again. ::: ### `listOrganizationApiKeys()` @@ -522,11 +522,11 @@ const result = await TurboPartner.revokePartnerApiKey('partner-key-uuid-here'); ## Partner User Management :::danger Partner users use a different role enum -Partner portal users take `'admin' | 'member' | 'viewer'`. **Organization** users and organization API keys take `'admin' | 'contributor' | 'user' | 'viewer'`. The two enums do not overlap beyond `admin`/`viewer` — `'member'` is rejected on an org call, and `'contributor'`/`'user'` are rejected on a partner call. See [Role Enums](#orguserrole-organization-users). +Partner portal users take `'admin' | 'member' | 'viewer'`. **Organization** users and organization API keys take `'admin' | 'contributor' | 'user' | 'viewer'`. The two enums do not overlap beyond `admin`/`viewer`: `'member'` is rejected on an org call, and `'contributor'`/`'user'` are rejected on a partner call. See [Role Enums](#orguserrole-organization-users-and-org-api-keys). ::: :::caution `permissions` is all-or-nothing -On `addUserToPartnerPortal()` the `permissions` object is **required**. On `updatePartnerUserPermissions()` it is optional, but if you send it, **all seven keys are required**. Either way there is no partial permissions update — omitting even one key is a `ValidationError` (400). Always send the complete object; read the current values first and re-send them with your change applied. +On `addUserToPartnerPortal()` the `permissions` object is **required**. On `updatePartnerUserPermissions()` it is optional, but if you send it, **all seven keys are required**. Either way there is no partial permissions update: omitting even one key is a `ValidationError` (400). Always send the complete object; read the current values first and re-send them with your change applied. ::: ### `addUserToPartnerPortal()` @@ -536,7 +536,7 @@ Add a user to the partner portal with specific permissions. ```typescript const result = await TurboPartner.addUserToPartnerPortal({ email: 'admin@partner.com', - role: 'admin', // 'admin' | 'member' | 'viewer' — the PARTNER role enum + role: 'admin', // 'admin' | 'member' | 'viewer' (the PARTNER role enum) // Required on this method, and all 7 keys must be present. permissions: { canManageOrgs: true, @@ -566,7 +566,7 @@ for (const user of result.data.results) { ### `updatePartnerUserPermissions()` -Update a partner user's role and permissions. If you include `permissions`, send **all seven keys** — a partial object is a 400. +Update a partner user's role and permissions. If you include `permissions`, send **all seven keys**: a partial object is a 400. ```typescript const result = await TurboPartner.updatePartnerUserPermissions( @@ -674,7 +674,7 @@ These are limits and capabilities you can configure for each organization: ### Tracking (Usage Counters) -Current consumption against the limits above. TurboDocx maintains these automatically, but `updateOrganizationEntitlements()` **accepts a `tracking` object** — useful for seeding counters when migrating an existing customer: +Current consumption against the limits above. TurboDocx maintains these automatically, but `updateOrganizationEntitlements()` **accepts a `tracking` object**, useful for seeding counters when migrating an existing customer: | Field | Type | Description | |-------|------|-------------| @@ -693,7 +693,7 @@ Every counter except `currentAICredits` floors at `0`. Only `currentAICredits` a ## Preferences Reference -TurboSign display preferences you can read and set per organization. Every key is a boolean and is validated strictly — the strings `"true"` / `"false"` are rejected with a 400, so pass real booleans. The API returns only these keys and never any of the organization's other settings. +TurboSign display preferences you can read and set per organization. Every key is a boolean and is validated strictly: the strings `"true"` / `"false"` are rejected with a 400, so pass real booleans. The API returns only these keys and never any of the organization's other settings. | Field | Type | Default | Description | |-------|------|---------|-------------| @@ -801,7 +801,7 @@ interface PartnerPermissions { ## Error Handling -The SDK provides typed error classes for different error scenarios: +`TurboPartner.createOrganization()` and the other partner calls reject with `AuthorizationError` when the partner API key lacks the scope for the route, since partner keys are scoped separately from organization keys: ```typescript import { @@ -846,18 +846,7 @@ try { } ``` -### Error Classes - -| Error Class | Status Code | Description | -|-------------|-------------|-------------| -| `TurboDocxError` | varies | Base error for all SDK errors | -| `AuthenticationError` | 401 | Invalid or missing API credentials | -| `AuthorizationError` | 403 | API key lacks required permissions (scope) | -| `ValidationError` | 400 | Invalid request parameters | -| `NotFoundError` | 404 | Resource not found | -| `ConflictError` | 409 | Resource conflict | -| `RateLimitError` | 429 | Too many requests | -| `NetworkError` | - | Network connectivity issues | +The full typed-error table and HTTP status mapping is documented once in the [JavaScript / TypeScript SDK's Error Handling reference](./javascript.md#error-handling); partner calls use the same `AuthenticationError`/`AuthorizationError`/`ValidationError`/`NotFoundError`/`ConflictError`/`RateLimitError`/`NetworkError` types. --- @@ -931,4 +920,4 @@ try { - [GitHub Repository](https://github.com/TurboDocx/SDK/tree/main/packages/js-sdk) - [npm Package](https://www.npmjs.com/package/@turbodocx/sdk) -- [TurboSign JavaScript SDK](/docs/SDKs/javascript) — For digital signature operations +- [TurboSign JavaScript SDK](/docs/SDKs/javascript): for digital signature operations diff --git a/docs/SDKs/partner-php.md b/docs/SDKs/partner-php.md index 1c944c67..1c84249c 100644 --- a/docs/SDKs/partner-php.md +++ b/docs/SDKs/partner-php.md @@ -32,7 +32,7 @@ The official TurboDocx Partner SDK for PHP applications. Build multi-tenant SaaS
:::info What is TurboPartner? -TurboPartner is the partner management API for TurboDocx. It allows you to programmatically create and manage organizations, users, API keys, and feature entitlements — perfect for building white-label or multi-tenant applications on top of TurboDocx. +TurboPartner is the partner management API for TurboDocx. It allows you to programmatically create and manage organizations, users, API keys, and feature entitlements, perfect for building white-label or multi-tenant applications on top of TurboDocx. ::: ## TLDR @@ -77,7 +77,7 @@ $user = TurboPartner::addUserToOrganization($orgId, $key = TurboPartner::createOrganizationApiKey($orgId, new CreateOrgApiKeyRequest(name: 'Production Key', role: 'admin') ); -echo "API Key: {$key->data->key}\n"; // Save this — only shown once! +echo "API Key: {$key->data->key}\n"; // Save this, only shown once! ``` --- @@ -449,7 +449,7 @@ echo "Full Key: {$result->data->key}\n"; // Only shown once! ``` :::caution Save Your API Key -The full API key is only returned once during creation. Store it securely — you won't be able to retrieve it again. +The full API key is only returned once during creation. Store it securely: you won't be able to retrieve it again. ::: ### `listOrganizationApiKeys()` @@ -573,11 +573,11 @@ $result = TurboPartner::revokePartnerApiKey('partner-key-uuid-here'); ## Partner User Management :::danger Partner users use a different role enum -Partner portal users take `admin`, `member`, or `viewer` (`PartnerUserRole`). **Organization** users and organization API keys take `admin`, `contributor`, `user`, or `viewer` (`OrgUserRole`). The two enums do not overlap beyond `admin`/`viewer` — `'member'` is rejected on an org call, and `'contributor'`/`'user'` are rejected on a partner call. See [Role Enums](#orguserrole-organization-users). +Partner portal users take `admin`, `member`, or `viewer` (`PartnerUserRole`). **Organization** users and organization API keys take `admin`, `contributor`, `user`, or `viewer` (`OrgUserRole`). The two enums do not overlap beyond `admin`/`viewer`: `'member'` is rejected on an org call, and `'contributor'`/`'user'` are rejected on a partner call. See [Role Enums](#orguserrole-organization-users-and-org-api-keys). ::: :::caution `permissions` is all-or-nothing -`AddPartnerUserRequest` **requires** `permissions` — omitting it is an `ArgumentCountError`. On `UpdatePartnerUserRequest` it is optional, but if you send it, **all seven arguments are required**. There is no partial permissions update — the API rejects an incomplete object with `ValidationException` (400). Read the current values first and re-send them with your change applied. +`AddPartnerUserRequest` **requires** `permissions`: omitting it is an `ArgumentCountError`. On `UpdatePartnerUserRequest` it is optional, but if you send it, **all seven arguments are required**. There is no partial permissions update: the API rejects an incomplete object with `ValidationException` (400). Read the current values first and re-send them with your change applied. ::: ### `addUserToPartnerPortal()` @@ -592,7 +592,7 @@ $result = TurboPartner::addUserToPartnerPortal( new AddPartnerUserRequest( email: 'admin@partner.com', role: 'admin', // PARTNER role enum: admin, member, or viewer - // Required on add — all 7 arguments must be supplied. + // Required on add: all 7 arguments must be supplied. permissions: new PartnerPermissions( canManageOrgs: true, canManageOrgUsers: true, @@ -626,7 +626,7 @@ foreach ($result->results as $user) { ### `updatePartnerUserPermissions()` -Update a partner user's role and permissions. If you pass `permissions`, supply **all seven arguments** — a partial object is a 400. +Update a partner user's role and permissions. If you pass `permissions`, supply **all seven arguments**: a partial object is a 400. ```php use TurboDocx\Types\Requests\Partner\UpdatePartnerUserRequest; @@ -736,7 +736,7 @@ These are limits and capabilities you can configure for each organization: ### Tracking (Usage Counters) -Current consumption against the limits above. TurboDocx maintains these automatically, but `updateOrganizationEntitlements()` **accepts a `tracking` array** — useful for seeding counters when migrating an existing customer: +Current consumption against the limits above. TurboDocx maintains these automatically, but `updateOrganizationEntitlements()` **accepts a `tracking` array**, useful for seeding counters when migrating an existing customer: | Field | Type | Description | |-------|------|-------------| @@ -755,7 +755,7 @@ Every counter except `currentAICredits` floors at `0`. Only `currentAICredits` a ## Preferences Reference -TurboSign display preferences you can read and set per organization. Every key is a boolean and is validated strictly — the strings `"true"` / `"false"` are rejected with a 400, so pass real booleans. The API returns only these keys and never any of the organization's other settings. +TurboSign display preferences you can read and set per organization. Every key is a boolean and is validated strictly: the strings `"true"` / `"false"` are rejected with a 400, so pass real booleans. The API returns only these keys and never any of the organization's other settings. | Field | Type | Default | Description | |-------|------|---------|-------------| @@ -863,7 +863,7 @@ $permissions = new PartnerPermissions( ## Error Handling -The SDK provides typed exceptions for different error scenarios: +`TurboPartner::createOrganization()` and the other partner calls throw `AuthenticationException` when the partner API key is invalid, missing, or the partner account is inactive, and `NotFoundException` when the `partnerId` doesn't match the key's own partner, since partner credentials are validated separately from organization API keys: ```php use TurboDocx\Exceptions\AuthenticationException; @@ -875,13 +875,13 @@ use TurboDocx\Exceptions\NetworkException; try { $result = TurboPartner::createOrganization(/* ... */); } catch (AuthenticationException $e) { - // 401 - Invalid API key or partner ID + // 401 - Invalid or missing partner API key echo "Authentication failed: {$e->getMessage()}\n"; } catch (ValidationException $e) { // 400 - Invalid request data echo "Validation error: {$e->getMessage()}\n"; } catch (NotFoundException $e) { - // 404 - Organization or resource not found + // 404 - Organization/resource not found, or partnerId doesn't match the key echo "Not found: {$e->getMessage()}\n"; } catch (RateLimitException $e) { // 429 - Rate limit exceeded @@ -892,16 +892,7 @@ try { } ``` -### Error Classes - -| Error Class | Status Code | Description | -|-------------|-------------|-------------| -| `TurboDocxException` | varies | Base exception for all SDK errors | -| `AuthenticationException` | 401 | Invalid or missing API credentials | -| `ValidationException` | 400 | Invalid request parameters | -| `NotFoundException` | 404 | Resource not found | -| `RateLimitException` | 429 | Too many requests | -| `NetworkException` | - | Network connectivity issues | +The full typed-exception table and HTTP status mapping is documented once in the [PHP SDK's Error Handling reference](./php.md#error-handling). --- @@ -983,4 +974,4 @@ try { - [GitHub Repository](https://github.com/TurboDocx/SDK/tree/main/packages/php-sdk) - [Packagist Package](https://packagist.org/packages/turbodocx/sdk) -- [TurboSign PHP SDK](/docs/SDKs/php) — For digital signature operations +- [TurboSign PHP SDK](/docs/SDKs/php): for digital signature operations diff --git a/docs/SDKs/partner-python.md b/docs/SDKs/partner-python.md index 07650048..6f5b51da 100644 --- a/docs/SDKs/partner-python.md +++ b/docs/SDKs/partner-python.md @@ -32,7 +32,7 @@ The official TurboDocx Partner SDK for Python applications. Build multi-tenant S
:::info What is TurboPartner? -TurboPartner is the partner management API for TurboDocx. It allows you to programmatically create and manage organizations, users, API keys, and feature entitlements — perfect for building white-label or multi-tenant applications on top of TurboDocx. +TurboPartner is the partner management API for TurboDocx. It allows you to programmatically create and manage organizations, users, API keys, and feature entitlements, perfect for building white-label or multi-tenant applications on top of TurboDocx. ::: ## TLDR @@ -70,7 +70,7 @@ async def main(): key = await TurboPartner.create_organization_api_key( org_id, name="Production Key", role="admin" ) - print(f"API Key: {key['data']['key']}") # Save this — only shown once! + print(f"API Key: {key['data']['key']}") # Save this, only shown once! asyncio.run(main()) ``` @@ -392,7 +392,7 @@ print(f"Full Key: {result['data']['key']}") # Only shown once! ``` :::caution Save Your API Key -The full API key is only returned once during creation. Store it securely — you won't be able to retrieve it again. +The full API key is only returned once during creation. Store it securely: you won't be able to retrieve it again. ::: ### `list_organization_api_keys()` @@ -510,13 +510,13 @@ result = await TurboPartner.revoke_partner_api_key("partner-key-uuid-here") ## Partner User Management :::danger Partner users use a different role enum -Partner portal users take `admin`, `member`, or `viewer`. **Organization** users and organization API keys take `admin`, `contributor`, `user`, or `viewer`. The two enums do not overlap beyond `admin`/`viewer` — `"member"` is rejected on an org call, and `"contributor"`/`"user"` are rejected on a partner call. See [Role Enums](#organization-user-roles). +Partner portal users take `admin`, `member`, or `viewer`. **Organization** users and organization API keys take `admin`, `contributor`, `user`, or `viewer`. The two enums do not overlap beyond `admin`/`viewer`: `"member"` is rejected on an org call, and `"contributor"`/`"user"` are rejected on a partner call. See [Role Enums](#organization-user-roles). ::: :::caution `permissions` is all-or-nothing -On `add_user_to_partner_portal()`, `permissions` is a **required** keyword argument — omitting it raises a Python `TypeError` before any request is sent. On `update_partner_user_permissions()`, the `permissions` dict itself is optional. +On `add_user_to_partner_portal()`, `permissions` is a **required** keyword argument: omitting it raises a Python `TypeError` before any request is sent. On `update_partner_user_permissions()`, the `permissions` dict itself is optional. -Either way, if you send `permissions`, **all seven keys are required**. There is no partial permissions update — omitting even one key raises `ValidationError` (400). Always send the complete dict; read the current values first and re-send them with your change applied. +Either way, if you send `permissions`, **all seven keys are required**. There is no partial permissions update: omitting even one key raises `ValidationError` (400). Always send the complete dict; read the current values first and re-send them with your change applied. ::: ### `add_user_to_partner_portal()` @@ -559,7 +559,7 @@ for user in result["data"]["results"]: ### `update_partner_user_permissions()` -Update a partner user's role and permissions. If you pass `permissions`, send **all seven keys** — a partial dict is a 400. +Update a partner user's role and permissions. If you pass `permissions`, send **all seven keys**: a partial dict is a 400. ```python result = await TurboPartner.update_partner_user_permissions( @@ -670,7 +670,7 @@ features={"maxUsers": 25, "hasTDAI": True} ### Tracking (Usage Counters) -Current consumption against the limits above. TurboDocx maintains these automatically, but `update_organization_entitlements()` **accepts a `tracking` dict** — useful for seeding counters when migrating an existing customer: +Current consumption against the limits above. TurboDocx maintains these automatically, but `update_organization_entitlements()` **accepts a `tracking` dict**, useful for seeding counters when migrating an existing customer: | Field | Type | Description | |-------|------|-------------| @@ -688,7 +688,7 @@ Every counter except `currentAICredits` floors at `0`. Only `currentAICredits` a ## Preferences Reference -TurboSign display preferences you can read and set per organization. Every key is a boolean and is validated strictly — the strings `"true"` / `"false"` are rejected with a 400, so pass real booleans. The API returns only these keys and never any of the organization's other settings. +TurboSign display preferences you can read and set per organization. Every key is a boolean and is validated strictly: the strings `"true"` / `"false"` are rejected with a 400, so pass real booleans. The API returns only these keys and never any of the organization's other settings. | Field | Type | Default | Description | |-------|------|---------|-------------| @@ -790,7 +790,7 @@ permissions = { ## Error Handling -The SDK provides typed exceptions for different error scenarios: +`TurboPartner.create_organization()` and the other partner calls raise `AuthorizationError` when the partner API key lacks the scope for the route, since partner keys are scoped separately from organization keys: ```python from turbodocx_sdk import ( @@ -834,18 +834,7 @@ except TurboDocxError as e: print(f" Error Code: {e.code}") ``` -### Error Types - -| Error Type | Status Code | Description | -|------------|-------------|-------------| -| `TurboDocxError` | varies | Base error for all SDK errors | -| `AuthenticationError` | 401 | Invalid or missing API credentials | -| `AuthorizationError` | 403 | Valid credentials without permission for this operation | -| `ValidationError` | 400 | Invalid request parameters | -| `NotFoundError` | 404 | Resource not found | -| `ConflictError` | 409 | Request conflicts with current resource state | -| `RateLimitError` | 429 | Too many requests | -| `NetworkError` | - | Network connectivity issues | +The full typed-error table and HTTP status mapping is documented once in the [Python SDK's Error Handling reference](./python.md#error-handling); partner calls use the same `AuthenticationError`/`AuthorizationError`/`ValidationError`/`NotFoundError`/`ConflictError`/`RateLimitError`/`NetworkError` types. --- @@ -905,5 +894,5 @@ asyncio.run(main()) - [GitHub Repository](https://github.com/TurboDocx/SDK/tree/main/packages/py-sdk) - [PyPI Package](https://pypi.org/project/turbodocx-sdk/) -- [TurboSign Python SDK](/docs/SDKs/python) — For digital signature operations -- [SDKs Overview](/docs/SDKs/) — All TurboDocx SDKs +- [TurboSign Python SDK](/docs/SDKs/python): for digital signature operations +- [SDKs Overview](/docs/SDKs/): all TurboDocx SDKs diff --git a/docs/SDKs/php.md b/docs/SDKs/php.md index 69ad930a..fb637aa8 100644 --- a/docs/SDKs/php.md +++ b/docs/SDKs/php.md @@ -487,7 +487,7 @@ echo "Document ID: {$result->documentId}\n"; `sendSignature` can also schedule automatic reminder emails and an expiration deadline. All eight schedule fields are optional and **both features are off by default**, so omitting them preserves -the original send behavior. The resolved schedule is **frozen onto the document when it is sent** — +the original send behavior. The resolved schedule is **frozen onto the document when it is sent**: changing your org defaults later never alters a document already out for signature. ```php @@ -517,7 +517,7 @@ deadline is readable afterwards via `getStatus()->expiresAt`. Send a standalone reminder to whoever's turn it is to sign (`POST /turbosign/documents/{documentId}/send-reminder`). It is independent of the automatic -cadence — it works even when reminders are disabled or the per-signer cap is already spent, does +cadence: it works even when reminders are disabled or the per-signer cap is already spent, does **not** consume that cap, and only emails signers at the *current* signing order. Pass `null` (or omit the argument) to remind everyone eligible; do not pass an empty array, which the API rejects. @@ -530,7 +530,7 @@ foreach ($result['results'] as $r) { echo "{$r['recipientId']}: {$r['status']}\n"; } -// Or limit to specific recipients — all-or-nothing: every id must be a current-order pending signer. +// Or limit to specific recipients (all-or-nothing): every id must be a current-order pending signer. TurboSign::sendReminder('document-uuid', ['recipient-uuid-1', 'recipient-uuid-2']); ``` @@ -566,7 +566,7 @@ foreach ($progress->recipients as $r) { :::tip Two status fields, and they differ on purpose `status` is the raw database value and is only ever `pending`, `viewed` or `completed`. -`effectiveStatus` layers the document's outcome on top, adding `voided` and `expired` — that +`effectiveStatus` layers the document's outcome on top, adding `voided` and `expired`: that is the one to display. On a voided or expired document an unsigned signer still reads `pending` in `status`, so @@ -579,14 +579,14 @@ the document is terminal. ::: -Each recipient also carries a `delivery` block — `firstSentOn`, `lastSentOn`, `totalSent`, +Each recipient also carries a `delivery` block: `firstSentOn`, `lastSentOn`, `totalSent`, `reminderCount`, `lastRemindedAt`, `warningCount`, `lastWarningAt`. It counts the signature request, resends, reminders, expiry warnings and terminal notices; CC notifications are excluded, since a CC address is not a signer. :::warning `reminderCount` and `lastRemindedAt` do not mean what their names suggest -`reminderCount` counts **automatic (scheduled) reminders only** — the counter `maxReminders` +`reminderCount` counts **automatic (scheduled) reminders only**: the counter `maxReminders` caps. A manual "remind now" is a standalone nudge that must not consume the cap budget, so it does **not** increment this, even though the email it sends *does* appear in `totalSent`. @@ -595,7 +595,7 @@ signature-request send, each scheduled reminder, each manual "remind now" and ea warning all stamp it. Only scheduled reminders bump `reminderCount`. So a freshly-sent document returns a non-null `lastRemindedAt` equal to the invitation -timestamp alongside `reminderCount: 0` — nobody has been reminded. To answer "have we actually +timestamp alongside `reminderCount: 0`: nobody has been reminded. To answer "have we actually chased this person", read `totalSent`, not `reminderCount`. `warningCount` / `lastWarningAt` have no such caveat. @@ -783,7 +783,7 @@ use TurboDocx\Types\FieldConditional; use TurboDocx\Types\ConditionalOperator; use TurboDocx\Types\ConditionalAction; -// Controlling checkbox — carries a stable fieldKey +// Controlling checkbox, carries a stable fieldKey new Field( type: SignatureFieldType::CHECKBOX, recipientEmail: 'reviewer@company.com', @@ -795,7 +795,7 @@ new Field( metadata: new FieldMetadata(fieldKey: 'request_changes') ); -// Dependent text field — hidden until the checkbox is checked +// Dependent text field, hidden until the checkbox is checked new Field( type: SignatureFieldType::TEXT, recipientEmail: 'reviewer@company.com', @@ -823,12 +823,14 @@ malformed rule returns `400 InvalidConditionalRule`; a well-formed rule whose ## Error Handling -The SDK provides typed exceptions for different error scenarios: +Every typed exception extends `TurboDocxException`, itself a plain `Exception` subclass with two extra readonly properties: `statusCode` (int, HTTP status) and `errorCode` (string, e.g. `'VALIDATION_ERROR'`). Because the constructor hardcodes PHP's built-in `Exception::getCode()` to `0`, read `$e->errorCode`, not `$e->getCode()`, for the machine-readable reason: ```php use TurboDocx\Exceptions\AuthenticationException; +use TurboDocx\Exceptions\AuthorizationException; use TurboDocx\Exceptions\ValidationException; use TurboDocx\Exceptions\NotFoundException; +use TurboDocx\Exceptions\ConflictException; use TurboDocx\Exceptions\RateLimitException; use TurboDocx\Exceptions\NetworkException; @@ -837,18 +839,27 @@ try { } catch (AuthenticationException $e) { // 401 - Invalid API key or access token echo "Authentication failed: {$e->getMessage()}\n"; +} catch (AuthorizationException $e) { + // 403 - Valid credentials without permission for this operation + echo "Authorization error: {$e->getMessage()}\n"; } catch (ValidationException $e) { // 400 - Invalid request data echo "Validation error: {$e->getMessage()}\n"; } catch (NotFoundException $e) { // 404 - Document not found echo "Not found: {$e->getMessage()}\n"; +} catch (ConflictException $e) { + // 409 - Conflicts with the current resource state + echo "Conflict: {$e->getMessage()}\n"; } catch (RateLimitException $e) { // 429 - Rate limit exceeded echo "Rate limit: {$e->getMessage()}\n"; } catch (NetworkException $e) { // Network/connection error echo "Network error: {$e->getMessage()}\n"; +} catch (TurboDocxException $e) { + // Catch-all: read the machine-readable reason from errorCode, not getCode() + echo "Error {$e->errorCode}: {$e->getMessage()} (status {$e->statusCode})\n"; } ``` @@ -858,16 +869,18 @@ try { | ------------------------- | ----------- | ---------------------------------- | | `TurboDocxException` | varies | Base exception for all SDK errors | | `AuthenticationException` | 401 | Invalid or missing API credentials | +| `AuthorizationException` | 403 | Valid credentials without permission for this operation | | `ValidationException` | 400 | Invalid request parameters | | `NotFoundException` | 404 | Document or resource not found | +| `ConflictException` | 409 | Request conflicts with current resource state | | `RateLimitException` | 429 | Too many requests | | `NetworkException` | - | Network connectivity issues | All exceptions extend `TurboDocxException` and include: - `getMessage()` - Human-readable error message -- `statusCode` - HTTP status code (if applicable) -- `errorCode` - Error code string (e.g., 'AUTHENTICATION_ERROR') +- `statusCode` - HTTP status code, a public readonly `?int` (null for `NetworkException`) +- `errorCode` - Error code string (e.g., `'AUTHENTICATION_ERROR'`), a public readonly `?string` --- @@ -912,13 +925,13 @@ enum DocumentStatus: string { case VOIDED = 'voided'; } -// Conditional (IF/THEN) operator — the condition evaluated against the controlling checkbox +// Conditional (IF/THEN) operator, the condition evaluated against the controlling checkbox enum ConditionalOperator: string { case IS_CHECKED = 'is_checked'; case IS_NOT_CHECKED = 'is_not_checked'; } -// Conditional (IF/THEN) action — what happens to the dependent field until the condition is met +// Conditional (IF/THEN) action, what happens to the dependent field until the condition is met enum ConditionalAction: string { case SHOW = 'show'; // hidden until met case UNLOCK = 'unlock'; // visible but read-only until met diff --git a/docs/SDKs/python.md b/docs/SDKs/python.md index 1461c189..084043bc 100644 --- a/docs/SDKs/python.md +++ b/docs/SDKs/python.md @@ -88,7 +88,7 @@ TURBODOCX_SENDER_NAME=Your Company ``` :::warning API Credentials Required -`api_key` and `org_id` are **required** for all API requests. TurboSign additionally **requires `sender_email`** (set it on `configure()`, per call, or via the `TURBODOCX_SENDER_EMAIL` environment variable) — `configure()` raises a `ValidationError` without it. `sender_name` is optional but strongly recommended. To get your credentials, follow the **[Get Your Credentials](/docs/SDKs#1-get-your-credentials)** steps from the SDKs main page. +`api_key` and `org_id` are **required** for all API requests. TurboSign additionally **requires `sender_email`** (set it on `configure()`, per call, or via the `TURBODOCX_SENDER_EMAIL` environment variable): `configure()` raises a `ValidationError` without it. `sender_name` is optional but strongly recommended. To get your credentials, follow the **[Get Your Credentials](/docs/SDKs#1-get-your-credentials)** steps from the SDKs main page. ::: --- @@ -424,7 +424,7 @@ for r in result["recipients"]: :::tip Two status fields, and they differ on purpose `status` is the raw database value and is only ever `pending`, `viewed` or `completed`. -`effectiveStatus` layers the document's outcome on top, adding `voided` and `expired` — that +`effectiveStatus` layers the document's outcome on top, adding `voided` and `expired`: that is the one to display. On a voided or expired document an unsigned signer still reads `pending` in `status`, so @@ -437,14 +437,14 @@ the document is terminal. ::: -Each recipient also carries a `delivery` block — `firstSentOn`, `lastSentOn`, `totalSent`, +Each recipient also carries a `delivery` block: `firstSentOn`, `lastSentOn`, `totalSent`, `reminderCount`, `lastRemindedAt`, `warningCount`, `lastWarningAt`. It counts the signature request, resends, reminders, expiry warnings and terminal notices; CC notifications are excluded, since a CC address is not a signer. :::warning `reminderCount` and `lastRemindedAt` do not mean what their names suggest -`reminderCount` counts **automatic (scheduled) reminders only** — the counter `maxReminders` +`reminderCount` counts **automatic (scheduled) reminders only**: the counter `maxReminders` caps. A manual "remind now" is a standalone nudge that must not consume the cap budget, so it does **not** increment this, even though the email it sends *does* appear in `totalSent`. @@ -453,7 +453,7 @@ signature-request send, each scheduled reminder, each manual "remind now" and ea warning all stamp it. Only scheduled reminders bump `reminderCount`. So a freshly-sent document returns a non-null `lastRemindedAt` equal to the invitation -timestamp alongside `reminderCount: 0` — nobody has been reminded. To answer "have we actually +timestamp alongside `reminderCount: 0`: nobody has been reminded. To answer "have we actually chased this person", read `totalSent`, not `reminderCount`. `warningCount` / `lastWarningAt` have no such caveat. @@ -491,7 +491,7 @@ result = await TurboSign.resend_email("document-uuid", recipient_ids=["recipient ### Send reminder Send a standalone reminder (`POST /turbosign/documents/:id/send-reminder`) to whoever's turn it -is to sign. It is independent of the automatic reminder cadence — it works even when reminders +is to sign. It is independent of the automatic reminder cadence: it works even when reminders are disabled or the per-signer `max_reminders` cap is already spent, does **not** consume that cap, and only emails signers at the *current* signing order. Omit `recipient_ids` to remind everyone eligible; do not pass an empty list, which the API rejects. @@ -522,7 +522,7 @@ print("Result:", json.dumps(result, indent=2)) ## Error Handling -The SDK provides typed error classes for different failure scenarios. All errors extend the base `TurboDocxError` class. +Every error is a plain `Exception` subclass; catch the most specific one first, since `except TurboDocxError` also matches every subclass below it. Each of the 7 named subclasses sets its own `DEFAULT_CODE` class attribute, so `e.code` is populated for those even when the API response itself carries none; the base `TurboDocxError` raised for an unmapped status (e.g. an unexpected 5xx) has `DEFAULT_CODE = None`, so `e.code` can be `None` there. ### Error Classes @@ -597,13 +597,13 @@ asyncio.run(send_with_error_handling()) ### Error Properties -All errors include these properties: +All errors include these instance attributes: | Property | Type | Description | | ------------- | ------------- | --------------------------------------------------- | | `message` | `str` | Human-readable error description (via `str(error)`) | | `status_code` | `int \| None` | HTTP status code (if applicable) | -| `code` | `str \| None` | Machine-readable error code | +| `code` | `str \| None` | Machine-readable error code; the API's code wins when present, otherwise the class's `DEFAULT_CODE` | --- @@ -679,7 +679,7 @@ Field configuration supporting both coordinate-based and template-based position | `required` | `bool` | No | Whether field is required | | `backgroundColor` | `str` | No | Background color (hex, rgb, or named) | | `template` | `Dict` | No | Template anchor configuration | -| `metadata` | `Dict` | No | Conditional (IF/THEN) metadata — see below | +| `metadata` | `Dict` | No | Conditional (IF/THEN) metadata, see below | \*Required when not using template anchors @@ -769,13 +769,13 @@ Request configuration for `create_signature_review_link` and `send_signature` me | `sender_email` | `str` | No\*\* | Sender / reply-to email (overrides the configured value) | | `cc_emails` | `List[str]` | No | Array of CC email addresses | | `reminders_enabled` | `bool` | No | Send reminder emails to signers who haven't signed. Off by default | -| `reminder_delay` | `Dict` | No | `{"value": N, "unit": "days"\|"hours"}` — time to the FIRST reminder | -| `reminder_interval` | `Dict` | No | `{"value": N, "unit": ...}` — gap between later reminders | +| `reminder_delay` | `Dict` | No | `{"value": N, "unit": "days"\|"hours"}`, time to the FIRST reminder | +| `reminder_interval` | `Dict` | No | `{"value": N, "unit": ...}`, gap between later reminders | | `max_reminders` | `int` | No | Cap per signer. `-1` unlimited, `0` none, max `50`. Default `5` | | `expiration_enabled` | `bool` | No | Close the signing window after `expire_after`. Off by default | -| `expire_after` | `Dict` | No | `{"value": N, "unit": ...}` — how long the document stays signable | -| `expiration_warning` | `Dict` | No | `{"value": N, "unit": ...}` — how far before expiry warnings start. `0` = never warn | -| `expiration_warning_interval` | `Dict` | No | `{"value": N, "unit": ...}` — gap between warnings once they start | +| `expire_after` | `Dict` | No | `{"value": N, "unit": ...}`, how long the document stays signable | +| `expiration_warning` | `Dict` | No | `{"value": N, "unit": ...}`, how far before expiry warnings start. `0` = never warn | +| `expiration_warning_interval` | `Dict` | No | `{"value": N, "unit": ...}`, gap between warnings once they start | :::info Duration bounds Each duration `{"value", "unit"}` uses `"days"` or `"hours"`; `value` is a whole number from `1` diff --git a/docs/SDKs/quote-go.md b/docs/SDKs/quote-go.md index 7c094a47..4560bd79 100644 --- a/docs/SDKs/quote-go.md +++ b/docs/SDKs/quote-go.md @@ -2,7 +2,7 @@ title: TurboQuote Go SDK sidebar_position: 22 sidebar_label: "TurboQuote: Go" -description: Official TurboDocx TurboQuote SDK for Go. Create and send quotes, manage line items, products, bundles, price books, companies, contacts, and quote templates programmatically with idiomatic Go and full context support. +description: "Go TurboQuote SDK: create and send quotes, manage line items, products, bundles, price books, companies, and contacts." keywords: - turboquote go - turboquote sdk golang diff --git a/docs/SDKs/quote-java.md b/docs/SDKs/quote-java.md index e300d2a7..73689126 100644 --- a/docs/SDKs/quote-java.md +++ b/docs/SDKs/quote-java.md @@ -2,7 +2,7 @@ title: TurboQuote Java SDK sidebar_position: 21 sidebar_label: "TurboQuote: Java" -description: Official TurboDocx TurboQuote SDK for Java. Create and send quotes, manage line items, products, bundles, and price books programmatically with full CPQ lifecycle support. +description: "Java TurboQuote SDK: create and send quotes, manage line items, products, bundles, and price books with full CPQ support." keywords: - turboquote java - quote sdk java @@ -41,7 +41,7 @@ TurboQuote is TurboDocx's CPQ (Configure, Price, Quote) module. Build a product com.turbodocx turbodocx-sdk - 0.5.0 + 0.7.0 ``` @@ -49,14 +49,14 @@ TurboQuote is TurboDocx's CPQ (Configure, Price, Quote) module. Build a product ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.5.0' +implementation 'com.turbodocx:turbodocx-sdk:0.7.0' ``` ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.5.0") +implementation("com.turbodocx:turbodocx-sdk:0.7.0") ``` diff --git a/docs/SDKs/quote-javascript.md b/docs/SDKs/quote-javascript.md index b78bdaeb..20d5af2e 100644 --- a/docs/SDKs/quote-javascript.md +++ b/docs/SDKs/quote-javascript.md @@ -2,7 +2,7 @@ title: TurboQuote JavaScript / TypeScript SDK sidebar_position: 20 sidebar_label: "TurboQuote: JavaScript / TypeScript" -description: Official TurboDocx TurboQuote SDK for JavaScript and TypeScript. Create quotes and proposals, manage line items, products, bundles, price books, companies, and contacts — all with full TypeScript types and async/await patterns. +description: "JavaScript/TypeScript TurboQuote SDK: create quotes, manage line items, products, bundles, price books, companies, contacts." keywords: - turboquote javascript - turboquote typescript @@ -98,7 +98,7 @@ TurboQuote.configure({ :::tip No senderEmail on the client — but set one on your quote template Unlike TurboSign, `TurboQuote.configure()` does **not** require `senderEmail` or `senderName` — quotes are not sent as signature emails. Only a credential is required — either `apiKey` or an OAuth `accessToken` (`accessToken` wins when both are set); `orgId` is recommended but falls back to `TURBODOCX_ORG_ID`. If you skip `configure()` entirely, the SDK auto-initialises from environment variables on the first method call. -The quote's **"Prepared by"** sender comes from your **org quote template** instead. Because an API key has no mailbox of its own, every sender-resolving call — `createQuote`, `duplicateQuote`, `sendQuote` / `sendQuoteWithDeliverable`, and `handleExpiredQuote` — fails with `400 SenderEmailRequired` when the org's quote template has no sender email set. A companion `400 SenderNameRequired` is returned when no sender **name** resolves. Configure both **Sender Name** and **Sender Email** once (`TurboQuote.updateTemplate({ senderEmail, senderName })`) and all of them resolve cleanly. +The quote's **"Prepared by"** sender comes from your **org quote template** instead. Because an API key has no mailbox of its own, if the org's quote template has no sender email set, `createQuote`, `duplicateQuote`, `sendQuote` / `sendQuoteWithDeliverable`, and `handleExpiredQuote` still succeed: they fall back to a generic TurboDocx sender (`no-reply@turbodocx.com`) rather than rejecting the call. Configure both **Sender Name** and **Sender Email** once (`const tmpl = await TurboQuote.getTemplate(); await TurboQuote.updateTemplate(tmpl.id, { senderEmail, senderName });`) so quotes show your own sender identity instead of the generic fallback. ::: ### Environment Variables @@ -436,7 +436,6 @@ specific error `code` before anything is created or emailed: | No line items | `QuoteHasNoLineItems` | | Contact missing a name or email | `QuoteContactRequired` | | Company or contact deleted/deactivated | `QuoteCustomerInactive` | -| No sender email resolvable (API-key callers) | `SenderEmailRequired` | A quote with **no line items cannot be sent** — add at least one product, bundle, or custom line item first. Likewise an **expired quote is rejected**; update `validUntil`, or use the diff --git a/docs/SDKs/quote-php.md b/docs/SDKs/quote-php.md index 6035da82..162c824c 100644 --- a/docs/SDKs/quote-php.md +++ b/docs/SDKs/quote-php.md @@ -2,7 +2,7 @@ title: TurboQuote PHP SDK sidebar_position: 16 sidebar_label: "TurboQuote: PHP" -description: Official TurboDocx TurboQuote SDK for PHP. Create, manage, and send quotes/proposals with full CPQ capabilities — line items, products, bundles, price books, companies, contacts, and quote templates, all from PHP 8.1+. +description: "PHP TurboQuote SDK: create, manage, and send quotes with line items, products, bundles, price books, companies, and contacts." keywords: - turboquote php - quote sdk php diff --git a/docs/SDKs/quote-python.md b/docs/SDKs/quote-python.md index 70e22b12..9b298eba 100644 --- a/docs/SDKs/quote-python.md +++ b/docs/SDKs/quote-python.md @@ -2,7 +2,7 @@ title: TurboQuote Python SDK sidebar_position: 20 sidebar_label: "TurboQuote: Python" -description: Official TurboDocx TurboQuote SDK for Python. Create, manage, and send quotes/proposals with full CPQ capabilities — line items, products, bundles, price books, companies, contacts, and quote templates, all via async Python 3.9+. +description: "Python TurboQuote SDK: create, manage, and send quotes with line items, products, bundles, and price books. Async, Python 3.9+." keywords: - turboquote python - quote sdk python diff --git a/docs/SDKs/webhooks-go.md b/docs/SDKs/webhooks-go.md index ea844b5c..2e27bbb8 100644 --- a/docs/SDKs/webhooks-go.md +++ b/docs/SDKs/webhooks-go.md @@ -2,7 +2,7 @@ title: TurboWebhooks Go SDK sidebar_position: 18 sidebar_label: "TurboWebhooks: Go" -description: Official TurboDocx Webhooks SDK for Go. Subscribe to all seven TurboSign signature events with the typed WebhookEvent constants, verify inbound webhook signatures with HMAC-SHA256, and manage delivery history programmatically. +description: "Go TurboWebhooks SDK: subscribe to all seven TurboSign events, verify HMAC-SHA256 signatures, manage delivery history." keywords: - turbodocx webhooks - turbowebhooks go diff --git a/docs/SDKs/webhooks-java.md b/docs/SDKs/webhooks-java.md index 0b122f40..2691ff90 100644 --- a/docs/SDKs/webhooks-java.md +++ b/docs/SDKs/webhooks-java.md @@ -2,7 +2,7 @@ title: TurboWebhooks Java SDK sidebar_position: 19 sidebar_label: "TurboWebhooks: Java" -description: Official TurboDocx Webhooks SDK for Java. Subscribe to all seven TurboSign signature events with the WebhookEvent enum, verify inbound webhook signatures with HMAC-SHA256, and manage delivery history programmatically. +description: "Java TurboWebhooks SDK: subscribe to all seven TurboSign events, verify HMAC-SHA256 signatures, manage delivery history." keywords: - turbodocx webhooks - turbowebhooks java @@ -45,7 +45,7 @@ For the full conceptual overview of how webhooks work in TurboSign (delivery ret com.turbodocx turbodocx-sdk - 0.5.0 + 0.7.0 ``` @@ -53,14 +53,14 @@ For the full conceptual overview of how webhooks work in TurboSign (delivery ret ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.5.0' +implementation 'com.turbodocx:turbodocx-sdk:0.7.0' ``` ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.5.0") +implementation("com.turbodocx:turbodocx-sdk:0.7.0") ``` diff --git a/docs/SDKs/webhooks-javascript.md b/docs/SDKs/webhooks-javascript.md index 85708d07..f54ca6d5 100644 --- a/docs/SDKs/webhooks-javascript.md +++ b/docs/SDKs/webhooks-javascript.md @@ -2,7 +2,7 @@ title: TurboWebhooks JavaScript / TypeScript SDK sidebar_position: 16 sidebar_label: "TurboWebhooks: JavaScript" -description: Official TurboDocx Webhooks SDK for JavaScript and TypeScript. Subscribe to all seven TurboSign signature events with the typed WebhookEvents constants, verify inbound webhook signatures with HMAC-SHA256, and manage delivery history programmatically. +description: "JavaScript/TypeScript TurboWebhooks SDK: subscribe to TurboSign events, verify HMAC-SHA256 signatures, manage delivery history." keywords: - turbodocx webhooks - turbowebhooks javascript diff --git a/docs/SDKs/webhooks-php.md b/docs/SDKs/webhooks-php.md index b7ba7ce5..d728f72a 100644 --- a/docs/SDKs/webhooks-php.md +++ b/docs/SDKs/webhooks-php.md @@ -2,7 +2,7 @@ title: TurboWebhooks PHP SDK sidebar_position: 15 sidebar_label: "TurboWebhooks: PHP" -description: Official TurboDocx Webhooks SDK for PHP. Subscribe to all seven TurboSign signature events with the WebhookEvent backed enum, verify inbound webhook signatures with HMAC-SHA256, and manage delivery history programmatically. +description: "PHP TurboWebhooks SDK: subscribe to all seven TurboSign events, verify HMAC-SHA256 signatures, manage delivery history." keywords: - turbodocx webhooks - turbowebhooks php diff --git a/docs/SDKs/webhooks-python.md b/docs/SDKs/webhooks-python.md index 130e4573..a96c1d67 100644 --- a/docs/SDKs/webhooks-python.md +++ b/docs/SDKs/webhooks-python.md @@ -2,7 +2,7 @@ title: TurboWebhooks Python SDK sidebar_position: 17 sidebar_label: "TurboWebhooks: Python" -description: Official TurboDocx Webhooks SDK for Python. Subscribe to all seven TurboSign signature events with the WEBHOOK_EVENT_* constants, verify inbound webhook signatures with HMAC-SHA256, and manage delivery history programmatically. +description: "Python TurboWebhooks SDK: subscribe to all seven TurboSign events, verify HMAC-SHA256 signatures, manage delivery history." keywords: - turbodocx webhooks - turbowebhooks python diff --git a/docs/TurboDocx Templating/API Templates.md b/docs/TurboDocx Templating/API Templates.md index 270f141f..6a32160f 100644 --- a/docs/TurboDocx Templating/API Templates.md +++ b/docs/TurboDocx Templating/API Templates.md @@ -1,7 +1,7 @@ --- title: Template Generation API Integration sidebar_position: 1 -description: Complete guide for integrating Template Generation API to upload templates, browse existing templates, and generate deliverables. Learn the dual-path process with detailed examples and code samples. +description: Integrate Template Generation API to upload templates, browse existing templates, and generate deliverables with detailed examples. keywords: - template generation api - document template api @@ -853,16 +853,12 @@ Content-Length: 287456 Now that you've mastered the basics, consider exploring these advanced capabilities: 📖 **[AI-Powered Content Generation →](/docs/TurboDocx%20Templating/ai-variable-generation)** -📖 **[Webhook Integration for Status Updates →](/docs/Webhooks/webhook-configuration)** -📖 **[Bulk Document Generation →](/docs/Templates/bulk-generation)** -📖 **[Template Version Management →](/docs/Templates/version-control)** +📖 **[Webhook Integration for Status Updates →](/docs/TurboSign/Webhooks)** ### Related Documentation -- [Template Management Guide](/docs/Templates/template-management) - [Variable Types and Formatting](/docs/API/Deliverable%20API#variable-object-structure) - [API Authentication](/docs/API/turbodocx-api-documentation) -- [Integration Examples](/docs/Integrations) ## Support diff --git a/docs/TurboDocx Templating/How to Create a Document Template.md b/docs/TurboDocx Templating/How to Create a Document Template.md index fc56d1d2..6b456d33 100644 --- a/docs/TurboDocx Templating/How to Create a Document Template.md +++ b/docs/TurboDocx Templating/How to Create a Document Template.md @@ -1,7 +1,7 @@ --- title: How to Create Document Templates sidebar_position: 2 -description: Learn how to create document templates for proposals, statements of work, quotes, and contracts that automatically populate with data from meetings, CRM systems, and business integrations. +description: Create document templates for proposals, SOWs, quotes, and contracts. Templates auto-populate with data from CRM systems and integrations. keywords: - document template creation - automated proposal generation diff --git a/docs/TurboDocx Templating/How to Create a Presentation Template.md b/docs/TurboDocx Templating/How to Create a Presentation Template.md index 63d1d346..fbcfca0f 100644 --- a/docs/TurboDocx Templating/How to Create a Presentation Template.md +++ b/docs/TurboDocx Templating/How to Create a Presentation Template.md @@ -1,7 +1,7 @@ --- title: How to Create Presentation Templates sidebar_position: 3 -description: Learn how to create PowerPoint presentation templates that automatically populate with content from meetings, CRM data, project management systems, and business integrations. +description: Create PowerPoint presentation templates. Auto-populate with content from meetings, CRM data, project management systems, and integrations. keywords: - powerpoint template creation - automated powerpoint generation diff --git a/docs/TurboDocx Templating/ai-variable-generation.md b/docs/TurboDocx Templating/ai-variable-generation.md index a91d71f6..64a08626 100644 --- a/docs/TurboDocx Templating/ai-variable-generation.md +++ b/docs/TurboDocx Templating/ai-variable-generation.md @@ -629,16 +629,12 @@ const generatedContent = await Promise.all( ### Advanced AI Features to Explore 📖 **[Template Generation API →](/docs/TurboDocx%20Templating/API%20Templates)** -📖 **[Webhook Integration →](/docs/Webhooks/webhook-configuration)** -📖 **[Bulk Processing →](/docs/Templates/bulk-generation)** +📖 **[Webhook Integration →](/docs/TurboSign/Webhooks)** 📖 **[API Authentication →](/docs/API/turbodocx-api-documentation)** ### Related Documentation -- [Template Management Guide](/docs/Templates/template-management) - [Variable Types and Formatting](/docs/API/Deliverable%20API#variable-object-structure) -- [Integration Examples](/docs/Integrations) -- [Best Practices Guide](/docs/Templates/best-practices) ## Support diff --git a/docs/TurboQuote/Bulk Importing from a Spreadsheet.md b/docs/TurboQuote/Bulk Importing from a Spreadsheet.md index 27ba53f2..03af2092 100644 --- a/docs/TurboQuote/Bulk Importing from a Spreadsheet.md +++ b/docs/TurboQuote/Bulk Importing from a Spreadsheet.md @@ -1,7 +1,7 @@ --- title: Bulk Importing from a Spreadsheet sidebar_position: 3 -description: Import products, companies, contacts, bundles, price books, and categories into TurboQuote in bulk from a CSV or XLSX spreadsheet, with column mapping, validation, and a downloadable error report. +description: Bulk import products, companies, contacts, and bundles into TurboQuote from CSV or XLSX with column mapping, validation, and error reports. keywords: - turboquote - bulk import diff --git a/docs/TurboQuote/Prepared By and Sender Identity.md b/docs/TurboQuote/Prepared By and Sender Identity.md index 85863b8c..3b84ed84 100644 --- a/docs/TurboQuote/Prepared By and Sender Identity.md +++ b/docs/TurboQuote/Prepared By and Sender Identity.md @@ -1,7 +1,7 @@ --- title: 'Prepared By & Sender Identity' sidebar_position: 5 -description: 'How TurboQuote decides the "Prepared by" name and email shown on a quote, and how to set your organization''s sender identity for quotes created in the UI or through the API, SDKs, and n8n.' +description: 'Configure TurboQuote sender identity: manage "Prepared by" name and email on quotes in the UI, API, SDKs, and n8n.' keywords: - turboquote - prepared by diff --git a/docs/TurboSign/API Bulk Signatures.md b/docs/TurboSign/API Bulk Signatures.md index ccdef36f..c5b72cf4 100644 --- a/docs/TurboSign/API Bulk Signatures.md +++ b/docs/TurboSign/API Bulk Signatures.md @@ -1,7 +1,7 @@ --- title: TurboSign Bulk API Integration sidebar_position: 5 -description: Send documents for signature at scale using TurboSign Bulk API. Process hundreds or thousands of signature requests in batches with comprehensive tracking and management capabilities. +description: Send documents for signature at scale with TurboSign Bulk API. Process hundreds or thousands of requests with tracking and management. keywords: - turbosign bulk api - bulk signature api diff --git a/docs/TurboSign/API Signatures.md b/docs/TurboSign/API Signatures.md index 12eaa017..0ae2d32e 100644 --- a/docs/TurboSign/API Signatures.md +++ b/docs/TurboSign/API Signatures.md @@ -1,7 +1,7 @@ --- title: TurboSign API Integration sidebar_position: 4 -description: Complete guide for integrating TurboSign API using single-step document preparation. Send documents for electronic signatures in one API call with our simplified workflow. +description: Integrate TurboSign API with single-step document preparation. Send documents for electronic signatures in one API call with simplified workflow. keywords: - turbosign api - single-step signature api @@ -1844,7 +1844,6 @@ Now that you've integrated the single-step signing flow, the next step is settin - [TurboSign Setup Guide](/docs/TurboSign/Setting%20up%20TurboSign) - [Webhook Configuration](/docs/TurboSign/Webhooks) - [API Authentication](/docs/API/turbodocx-api-documentation) -- [Integration Examples](/docs/Integrations) ## Support diff --git a/docs/TurboSign/Email Deliverability and DKIM DMARC.md b/docs/TurboSign/Email Deliverability and DKIM DMARC.md index 50e796a4..e65f97f9 100644 --- a/docs/TurboSign/Email Deliverability and DKIM DMARC.md +++ b/docs/TurboSign/Email Deliverability and DKIM DMARC.md @@ -1,7 +1,7 @@ --- title: Email Deliverability (DKIM / DMARC / SPF) sidebar_position: 7 -description: How to diagnose and resolve DKIM, DMARC, or SPF failures on TurboDocx and TurboSign emails, including the common case where a security gateway rewrites the message in transit. +description: Diagnose and resolve DKIM, DMARC, or SPF failures on TurboDocx and TurboSign emails, including security gateway message rewrites. keywords: - turbosign email deliverability - dkim failure diff --git a/docs/TurboSign/Webhooks.md b/docs/TurboSign/Webhooks.md index a505c09a..e0e4ed83 100644 --- a/docs/TurboSign/Webhooks.md +++ b/docs/TurboSign/Webhooks.md @@ -1,7 +1,7 @@ --- title: TurboSign Webhooks sidebar_position: 6 -description: Configure real-time webhooks to receive instant notifications across the full TurboSign signature lifecycle — sent, viewed, per-recipient signed, partial progress, completed, voided, and finalization failures. Integrate TurboSign events with your existing systems through secure webhook endpoints. +description: "Configure TurboSign webhooks to receive notifications for signature events: sent, viewed, signed, completed, voided, and finalization failures." keywords: - webhook configuration - signature webhooks diff --git a/docusaurus.config.js b/docusaurus.config.js index babe49cf..49c74a9a 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -159,6 +159,12 @@ const config = { theme: { customCss: require.resolve('./src/css/custom.scss'), }, + sitemap: { + // '/' is a client-side redirect to '/docs' (the real hub) and + // carries a noindex meta tag; exclude it from the sitemap too so + // the two signals don't conflict. + ignorePatterns: ['/'], + }, }), ], ], diff --git a/package-lock.json b/package-lock.json index b7326b63..944e5eef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6262,6 +6262,13 @@ "integrity": "sha512-dGGHpb61hLwifAu7sotuHFDBw6GTdpG8aKC0fsK17EuTzMRvUrH7lEAr6LTJ+sx3AZYed9yZ77rltVDHyg2hRg==", "license": "MIT" }, + "node_modules/@faker-js/faker": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-5.5.3.tgz", + "integrity": "sha512-R11tGE6yIFwqpaIqcfkcg7AICXzFg14+5h5v0TfF/9+RMDL6jhzCy/pxHVOfbALGdtVYdt6JdR21tuxEgl34dw==", + "deprecated": "Please update to a newer version.", + "license": "MIT" + }, "node_modules/@floating-ui/core": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", @@ -6353,9 +6360,9 @@ } }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.0.tgz", - "integrity": "sha512-ZgaYEwaj+lx/5n4W8GmZ2IYz0PQHjN5eqRcfijWGB+2Aq7ZInZGa0qJyAn6DEtyLuWHRSrmWOqT9q3qqTBvmUQ==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.4.tgz", + "integrity": "sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==", "cpu": [ "arm64" ], @@ -6371,13 +6378,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.3.0" + "@img/sharp-libvips-darwin-arm64": "1.3.3" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.0.tgz", - "integrity": "sha512-c1z9LFpKB0slQW3RchwBE8iSVzGp70TNjUUO9k4BZwwW4HH7JBGHeIy4b+kk4n/kcBASb9evKCE3/7Slmslgiw==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.4.tgz", + "integrity": "sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==", "cpu": [ "x64" ], @@ -6393,20 +6400,20 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.3.0" + "@img/sharp-libvips-darwin-x64": "1.3.3" } }, "node_modules/@img/sharp-freebsd-wasm32": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.0.tgz", - "integrity": "sha512-Li2KTev0H90kEtnJHkI9xQojXt1AqWmFBMXiPw5kqd1jQgP7gi5HVK/qC5Rmh/59NuAwUuPzzPITmX22NomYYQ==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.4.tgz", + "integrity": "sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==", "license": "Apache-2.0", "optional": true, "os": [ "freebsd" ], "dependencies": { - "@img/sharp-wasm32": "0.35.0" + "@img/sharp-wasm32": "0.35.4" }, "engines": { "node": ">=20.9.0" @@ -6416,9 +6423,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.0.tgz", - "integrity": "sha512-EKbmBKtyTH+GPFDRw2TgK2oV6hyxxlJVIar4hoTYSNmIwipgMFdxPQqR392GmfdsPGWga0mCFN1cCKjRb9cljw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.3.tgz", + "integrity": "sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==", "cpu": [ "arm64" ], @@ -6432,9 +6439,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.0.tgz", - "integrity": "sha512-Pl2OmOvrJ42adUllESxBsG54PfXLo1OYg9i3c5/5Ln/qJ0gZuTM9YMhQJPIbXqwidLRc/c2zuHt4RsrymmNv7A==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.3.tgz", + "integrity": "sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==", "cpu": [ "x64" ], @@ -6448,9 +6455,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.0.tgz", - "integrity": "sha512-A8UpHoUDW4DwnXoV6+q3C1s7QLRAHtPDEjWuNZjwHMyoCNZnm0GeNN8ls9f/bsEYTRQRW96C/n34XJQHJ2fT7A==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.3.tgz", + "integrity": "sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==", "cpu": [ "arm" ], @@ -6467,9 +6474,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.0.tgz", - "integrity": "sha512-C0SqjoFKnszqa44EQ7xoaT48nnO0lOyXEULfXMWi8krrjOPGYkeK30Okzla6ATbBYsyZ0ySinK0FVkpv3DwzfQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.3.tgz", + "integrity": "sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==", "cpu": [ "arm64" ], @@ -6486,9 +6493,9 @@ } }, "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.0.tgz", - "integrity": "sha512-WOpkVxAjFd369iaIzEgNRreFD+gWdUMIGD5zplhNKNeqS6mm5dac3q2AFyCBmzYoAdouzZvRBgxy4z8QHZb4/A==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.3.tgz", + "integrity": "sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==", "cpu": [ "ppc64" ], @@ -6505,9 +6512,9 @@ } }, "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.0.tgz", - "integrity": "sha512-DRWw0mOHusrCCuw2rqP87oLg6PGlkomVDFqw2hIwsSfwWpu4k3XLcBPaKKl6ct/GtL/cwNkgwjV/tc0Mqht3VA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.3.tgz", + "integrity": "sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==", "cpu": [ "riscv64" ], @@ -6524,9 +6531,9 @@ } }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.0.tgz", - "integrity": "sha512-9APy+nFWhHS+kzLgWZfLcyrUd7YqnAQVa4BPOo4xkoHpdoktOAPG4cEr9+Jpl0TtqfVmcMJimNL5qNTyyOHZNA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.3.tgz", + "integrity": "sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==", "cpu": [ "s390x" ], @@ -6543,9 +6550,9 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.0.tgz", - "integrity": "sha512-y9RNUYDe2A1UAdhLyfeOodGRszQdaEoe4nfOpp/sNVPl2CWIcUyFaDoCh4vPLPxu19803j2naLqZup2WxDXCLA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.3.tgz", + "integrity": "sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==", "cpu": [ "x64" ], @@ -6562,9 +6569,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.0.tgz", - "integrity": "sha512-cC1wkC0Mlucd0KSiGrLkJnB/ZqPvZCntc/Lk7ZnYO5ZSbF2euNek4Xvxafojq+wN1q/W0eprdpUIjUr/EV2PBg==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.3.tgz", + "integrity": "sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==", "cpu": [ "arm64" ], @@ -6581,9 +6588,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.0.tgz", - "integrity": "sha512-LiYMhUZicB1QG//+RvmYZpXJO8fYRENfp+MZUCnG9aw+AKvGAy9gPaCnuwsPcBFs8EV66M0NNxj9VHcNklE8zw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.3.tgz", + "integrity": "sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==", "cpu": [ "x64" ], @@ -6600,9 +6607,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.0.tgz", - "integrity": "sha512-VVlpEWwizEFIOom0zdoeKuO5nuTswzVE5uHcBNvHzmeHUpNFajY3HFfbQ+zIH4E2kVaZ/yVxmsShW56TtEy4uA==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.4.tgz", + "integrity": "sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==", "cpu": [ "arm" ], @@ -6621,13 +6628,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.3.0" + "@img/sharp-libvips-linux-arm": "1.3.3" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.0.tgz", - "integrity": "sha512-4+4XHLNT5wDT0roYlHTEmH9lDKt0acf9Tv+3hM3iceOirkxrR404/3WjAYZ9F9CkHrxeRcGLJXbi4vluMZ9O+A==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.4.tgz", + "integrity": "sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==", "cpu": [ "arm64" ], @@ -6646,13 +6653,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.3.0" + "@img/sharp-libvips-linux-arm64": "1.3.3" } }, "node_modules/@img/sharp-linux-ppc64": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.0.tgz", - "integrity": "sha512-N3hzbEpUTJC8pWpPVJvgzGxM+so/MAXc8O2s/53B0LL9ZGpfXpME7Wizkc5d/8fRBlBtkDjzoZGDCqqNDHqLEw==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.4.tgz", + "integrity": "sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==", "cpu": [ "ppc64" ], @@ -6671,13 +6678,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.3.0" + "@img/sharp-libvips-linux-ppc64": "1.3.3" } }, "node_modules/@img/sharp-linux-riscv64": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.0.tgz", - "integrity": "sha512-l6vmKVPnbS0RhVMbyxP5meAARsbhCnBN4fy31qz0+3a6Rv4jEqfzDrT89y6ZPkCi0AJGnwp2En528yXo401Hpw==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.4.tgz", + "integrity": "sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==", "cpu": [ "riscv64" ], @@ -6696,13 +6703,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.3.0" + "@img/sharp-libvips-linux-riscv64": "1.3.3" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.0.tgz", - "integrity": "sha512-MYlMiPFiv/EKPAHnp3yNZ9AAWFsxga9c5Bkc6wkar6bqzHLlkGVJHRm0u1ei+VXnZxp3Mz9MG9ZIsI8vSOf3sQ==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.4.tgz", + "integrity": "sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==", "cpu": [ "s390x" ], @@ -6721,13 +6728,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.3.0" + "@img/sharp-libvips-linux-s390x": "1.3.3" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.0.tgz", - "integrity": "sha512-TYaItB5oj1ioXjhyn2xrR208vf+YuIIcHptQWRRaBmFhvIvL9D72DXN8w75xup0KXA8UdEAhQ9Qb2S49FD/9Cw==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.4.tgz", + "integrity": "sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==", "cpu": [ "x64" ], @@ -6746,13 +6753,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.3.0" + "@img/sharp-libvips-linux-x64": "1.3.3" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.0.tgz", - "integrity": "sha512-DSTb6ijQzqe6DdAaOBVqJ/SYf1vO8EW5bK6X6LRXufEBebf2722VCdvBUtZ3rtV0x2ApfPNDy/p7LrrjaWjiyQ==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.4.tgz", + "integrity": "sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==", "cpu": [ "arm64" ], @@ -6771,13 +6778,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.3.0" + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.0.tgz", - "integrity": "sha512-K7ykQ+26Rt6+4BTU80AuGgTPIYX86UxiAKT4rcXX/WNTo7k1ZxpKz+TguHnwVpCqQK3B5PK0vZ0ZBe6nz/ib1w==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.4.tgz", + "integrity": "sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==", "cpu": [ "x64" ], @@ -6796,17 +6803,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.3.0" + "@img/sharp-libvips-linuxmusl-x64": "1.3.3" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.0.tgz", - "integrity": "sha512-9woLIFORERCr+6cWu87dQ22J34EExkhc73U1kZW0c+RclQqWetoodByp4dWZ/hN8/KVmTRAx2HOnUwib8AwZdA==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.4.tgz", + "integrity": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==", "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.11.0" + "@emnapi/runtime": "^1.11.3" }, "engines": { "node": ">=20.9.0" @@ -6816,16 +6823,16 @@ } }, "node_modules/@img/sharp-webcontainers-wasm32": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.0.tgz", - "integrity": "sha512-t+kie1TOyaDM6Dho+f+y0VqIUNhYQaKCUahuZVi0E0frgdiaOaPsDxDW3wfKacUdaNBCnK/ZDBMg33ydvHj8uA==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.4.tgz", + "integrity": "sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==", "cpu": [ "wasm32" ], "license": "Apache-2.0", "optional": true, "dependencies": { - "@img/sharp-wasm32": "0.35.0" + "@img/sharp-wasm32": "0.35.4" }, "engines": { "node": ">=20.9.0" @@ -6835,9 +6842,9 @@ } }, "node_modules/@img/sharp-win32-arm64": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.0.tgz", - "integrity": "sha512-M5eKxug0dabbaWgFKvPa3odNs2OpaP+81NASfGKkt4GcYXpNhSu7CaeYxWkLNV6vHmUp4hnCxnxrUyhUJhXbKA==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.4.tgz", + "integrity": "sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==", "cpu": [ "arm64" ], @@ -6854,9 +6861,9 @@ } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.0.tgz", - "integrity": "sha512-z0+pZ03QCDvdVN0Ez9IX/yjWC19ikMlXrmdYMwYNLTh2BLPx3hXWPvyqWfquZ0BTO9O6GVOjIVoTcyyacMnWlQ==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.4.tgz", + "integrity": "sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==", "cpu": [ "ia32" ], @@ -6873,9 +6880,9 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.0.tgz", - "integrity": "sha512-feNnlz5ZHKr0MY1LPHvZQyJeBkbo4ctsn0D8FvA53VTw5TC63rfEL2UrWbkSBR19htSE7Mw78xYVwdJqoMWVHw==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.4.tgz", + "integrity": "sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==", "cpu": [ "x64" ], @@ -8720,9 +8727,9 @@ "license": "MIT" }, "node_modules/@popperjs/core": { - "version": "2.11.6", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", - "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "license": "MIT", "funding": { "type": "opencollective", @@ -10468,9 +10475,9 @@ } }, "node_modules/@tiptap/core": { - "version": "2.27.2", - "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.27.2.tgz", - "integrity": "sha512-ABL1N6eoxzDzC1bYvkMbvyexHacszsKdVPYqhl5GwHLOvpZcv9VE9QaKwDILTyz5voCA0lGcAAXZp+qnXOk5lQ==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.27.3.tgz", + "integrity": "sha512-a5LfRbLpfaGI3hbL/LPHUYHI0I+FQHdSHsy8L4YnVIuu3hXcm3QZgkWbpEGf8hCz8krk6zEiu0+iFOjTySU2FA==", "license": "MIT", "funding": { "type": "github", @@ -10481,39 +10488,37 @@ } }, "node_modules/@tiptap/extension-blockquote": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.202.tgz", - "integrity": "sha512-weLbMxM7VfI4hJsThw1+mB4jbQnVFizmzRlGU40LKMzEU5yIgIhuaomQ02Z7V0cRgfXsoKX9oc0BYGiO0Ra6/g==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.27.3.tgz", + "integrity": "sha512-NwK7FUFF0CKGJt/qNDR7plL/9vkJQBy8ziiyn8lk3j/j6tAFlCpgBMj420A1T26ItDpwOCyyaq+PMWHML+E4VQ==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.1" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-bold": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.202.tgz", - "integrity": "sha512-AsfoChIleoSbY9gAuhbLF8BAEhHPrRKofmU09xJ62SBkL1rtgci8YzJYhL9leQCM4n1MQZEDeVf0ho75HeTPMA==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.27.3.tgz", + "integrity": "sha512-d5tQLAl5nHNrHNkBEgHJ0GYQ52iAsq83fUiKnDxPWuF6leKMOtkUBt9rw918p/L6MPg/MHROZ3Qt4Q+lmVYbfQ==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-bubble-menu": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.202.tgz", - "integrity": "sha512-Xa0BO5liIHitaxj70JbbmiC70Yg9+EcF9airfI32uOFNHwgEKyXVb5MRyQadRSmXnwPMPLVGWgf3Kg/5rnDqeg==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.27.3.tgz", + "integrity": "sha512-08dt5pG9j3NTID1BnKT+FlfVgf16BPXEYtDCmPMLQq/jKHlOP49SRBAGhvYHZt8K7xkj0+JYhcgcJfytukTcKQ==", "license": "MIT", "dependencies": { - "prosemirror-state": "^1.4.1", - "prosemirror-view": "^1.28.2", "tippy.js": "^6.3.7" }, "funding": { @@ -10521,126 +10526,114 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" } }, "node_modules/@tiptap/extension-bullet-list": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.202.tgz", - "integrity": "sha512-Su+GvRGyW9FTBtcFjvNkkYwzDRo+1O2YTNOZi1Z/OkDqbg3g89kRue78avs0nHW7HEgdhCap+z8KtAPrie4eBg==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.27.3.tgz", + "integrity": "sha512-LEYkcuCCHYDm6NHWZRIl3Lpac1jXFhABZZpEj+V/ypPgPwKQSIzUMCySHXXNCUQOK3ipF0Z+O18kFnekag8ZLQ==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-code": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.0.0-beta.202.tgz", - "integrity": "sha512-XwAr7ysSWJVZWHNXDaNBTPH1CTyVxHnPv/PiCWTGhf8Fkx7R7xW2QCUKx4ablwxFlTY7H8xGmCujaewUQBdO5w==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.27.3.tgz", + "integrity": "sha512-gETwHmS1NsQsBEeSOtd/erAQpiRRPyd2dg2HCrIASdiSApVbOfOnSfoHPrHDUp66S8WI5aR9j+d7e4Zz/gmorQ==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-code-block": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.2.4.tgz", - "integrity": "sha512-h6WV9TmaBEZmvqe1ezMR83DhCPUap6P2mSR5pwVk0WVq6rvZjfgU0iF3EetBJOeDgPlz7cNe2NMDfVb1nGTM/g==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.27.3.tgz", + "integrity": "sha512-vzIt0orLs/59WlMOR8f9ULmwRLlOE1YB+zQuPdBVSRCOxVUYRUwtf7m1lOPNKKdorHadDpvWsT0hFMeNoyqQpQ==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0", - "@tiptap/pm": "^2.0.0" + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" } }, "node_modules/@tiptap/extension-code-block-lowlight": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.3.tgz", - "integrity": "sha512-thFXcFdFyHF0/dr9sqBedjj0Vt14k3m52YVc4l65+d65wRuHp4f8suu8T2ZGRJwqLCE3NIrvwQTSHhzjIqJVxQ==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.27.3.tgz", + "integrity": "sha512-VKQ9uoJKLSNuU2/+TqyCmloY5wAQgvC/sxJiZkr41W5KwMnzST4TCB8twRP5O7bq+tbnRpemYYg89ptr4ZrXeg==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0", - "@tiptap/extension-code-block": "^2.0.0", - "@tiptap/pm": "^2.0.0" + "@tiptap/core": "^2.7.0", + "@tiptap/extension-code-block": "^2.7.0", + "@tiptap/pm": "^2.7.0", + "highlight.js": "^11", + "lowlight": "^2 || ^3" } }, "node_modules/@tiptap/extension-color": { - "version": "2.0.0-beta.212", - "resolved": "https://registry.npmjs.org/@tiptap/extension-color/-/extension-color-2.0.0-beta.212.tgz", - "integrity": "sha512-iz2inN0IAEDcyWA9qgV0KCdUdRwn5M2qn4OvSud0dvm3qIPyKzM5mlC9JXrxxQVW+8iHsXBsfi6BQ7zGTSYdUA==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-color/-/extension-color-2.27.3.tgz", + "integrity": "sha512-+xHveJ8YfneusZIp87/8UW7VfdtCVgE5iN3JkTudC1TdYCnMqxbaIwQaGtsBH+UxinXhJSU9tcsD1P6QgKJSqg==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.209", - "@tiptap/extension-text-style": "^2.0.0-beta.209" + "@tiptap/core": "^2.7.0", + "@tiptap/extension-text-style": "^2.7.0" } }, "node_modules/@tiptap/extension-document": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.0.0-beta.202.tgz", - "integrity": "sha512-UsDSe93QtnuDrUo11wYCMtp7XlTIBvL5HNhx+enLRY7B8nUhX+d78u1BzspTpCkMYKcdwDmAGfIYMqqPViPEvA==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.27.3.tgz", + "integrity": "sha512-U10TnvBa6WTjBu64U4gn/HaxkBs/96q0U6mKH0PO9Ab0n3Bf/iN4HMtix2TEa3qWlJ8peVk9/RBwjyxNVNub4w==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-dropcursor": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.0-beta.202.tgz", - "integrity": "sha512-4Q3LnqvMnxP0KdX7tIgCoTCKg949rg351m0wguVb1bo4v9lA0zfJpSgqjQ1Xs2vaYVBwkFjLoqrfhTRn5mnopQ==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.27.3.tgz", + "integrity": "sha512-dIBb5AdfoNx2bCnwP3W1e3qez5s/XxrBBT3agtDt+VYOdx0Mi9MgT6GpGF+zfE2nnB7I0bYPfe2Z8cBqP9CU1w==", "license": "MIT", - "dependencies": { - "prosemirror-dropcursor": "1.5.0" - }, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" - } - }, - "node_modules/@tiptap/extension-dropcursor/node_modules/prosemirror-dropcursor": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.5.0.tgz", - "integrity": "sha512-vy7i77ddKyXlu8kKBB3nlxLBnsWyKUmQIPB5x8RkYNh01QNp/qqGmdd5yZefJs0s3rtv5r7Izfu2qbtr+tYAMQ==", - "license": "MIT", - "dependencies": { - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.1.0", - "prosemirror-view": "^1.1.0" + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" } }, "node_modules/@tiptap/extension-floating-menu": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.202.tgz", - "integrity": "sha512-09liirOFsPDFRLS2FiFdnfzyyOQwwyVXLzI6MzUOw5RZbOsGJ5kB8jZdkXvsAIiOs0YYsH3fyOyWirIwSRhBTQ==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.27.3.tgz", + "integrity": "sha512-4Be2efRPxLqZT0QB/IStVdVR1wP+FVPQxw/7qJ+xRk+m7EX45LVO0hvRdMK9aMO8Yd8JK2Wh9V3DbCN6cZ89vw==", "license": "MIT", "dependencies": { - "prosemirror-state": "^1.4.1", - "prosemirror-view": "^1.28.2", "tippy.js": "^6.3.7" }, "funding": { @@ -10648,113 +10641,108 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" } }, "node_modules/@tiptap/extension-gapcursor": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.202.tgz", - "integrity": "sha512-jOPMPPnTfVuc5YpFTcQM42/cg1J3+OeHitYb1/vBMpaNinVijuafsK14xDoVP8+sydKVgtBzYkfP/faN82I9iA==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.27.3.tgz", + "integrity": "sha512-GhK8Xl0jlJJkeJhdMfItCyselxGDt44UmaYTB3mSpH3dbvjT/NvYx7ABrPlRffogvRJ6eIi4ebU5FRuGYDmAuA==", "license": "MIT", - "dependencies": { - "prosemirror-gapcursor": "^1.3.1" - }, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" } }, "node_modules/@tiptap/extension-hard-break": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.202.tgz", - "integrity": "sha512-Nr9BXeP+dXS5vLP/C2voTrhl+4YkDHBtPlc+5xm5NPBn04slTGSPO2lgV3YrMsfUOMNXHqeob1lq4qiLF4pybQ==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.27.3.tgz", + "integrity": "sha512-lvjELj0ZOgbgVNkUb3tQ0t96PLXybDTjL5nUyobkgIpkSUZTnuuXU9imiH7O/+frDiTCQ+Xp//VUB1XaMylfdg==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-heading": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.202.tgz", - "integrity": "sha512-sF271jSWHgtoJLDNFLS7eyUcUStl7mBDQNJIENWVI+lFu2Ax8GmO7AoB74Q6L5Zaw4h73L6TAvaafHIXurz7tA==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.27.3.tgz", + "integrity": "sha512-VWcj9b5VAhMJSAeG8xZyzCaVCcwmBGJL2k77lE2ZQaCS/jSvKUTN5ntd/1vwLrmaduciB7FmdVgOmWFcODyX1Q==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-history": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.0.0-beta.202.tgz", - "integrity": "sha512-BLwaOWmFHBQjOonojYHl1Po27IHxgjSAPw+ijMKtKzqa2msJRJevjC4tBaX5s/YrB7PQ2tFE7rfJED4HLjBm6w==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.27.3.tgz", + "integrity": "sha512-btT7Teg9xtWbv9q6uc38aIQbZsbMhgNu1NGLf7nLf7Vqzm+GRCpRF5EzlF9RpwEPtC2j1bxrDzpy427Su1qF7w==", "license": "MIT", - "dependencies": { - "prosemirror-history": "^1.3.0" - }, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" } }, "node_modules/@tiptap/extension-horizontal-rule": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.202.tgz", - "integrity": "sha512-ut2Im/TNQynnuqdoY9yOjMDUKmxn97ERVEpqcQSaIgqBuF6bjk60Wa13ob6oS2g6vqXxwWFrnQVz48A9TcF5FQ==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.27.3.tgz", + "integrity": "sha512-G9ENe55ykj1dt5FCNAySQUh17ev5wvvGreSt3vvaCOHBPWaEdMARTGISn30X2fSPUVntTeYSB+oPP3XClunLEw==", "license": "MIT", - "dependencies": { - "prosemirror-state": "^1.4.1" - }, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" } }, "node_modules/@tiptap/extension-image": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-image/-/extension-image-2.0.0-beta.202.tgz", - "integrity": "sha512-aHPJMXuoMgToTYkGZsz2ue8gKzes+B92qb9lVRYlY9f+r/tC2K4q3HMtx6qvh8l4Dei5/yeV9TqliY79E9A5dg==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-image/-/extension-image-2.27.3.tgz", + "integrity": "sha512-YCOxC+UOFisHVpowPc3UmUtJDV9tjKJLeHKef3DZ6h1ixOnp2LStuhy2ohcSjISg1mZlYrx+/GoYottjwj7pww==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-italic": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.202.tgz", - "integrity": "sha512-vgSLy4KDp6AmnAHLHXe/nWeNbLnyUXxmf4U4+esebAV5Hu2F7LgceknFt9D8AGEtYUU+/fYKSeE2NGJgTQG9lA==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.27.3.tgz", + "integrity": "sha512-ycgP6h7QQ4WXojOlH7gQEWwzNEzkIkVzdfH6jAZtZ2nw71L5KO1t5kt6Iu382CmQa60skDTuErbfiBUx7a3e2A==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-link": { - "version": "2.27.2", - "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-2.27.2.tgz", - "integrity": "sha512-bnP61qkr0Kj9Cgnop1hxn2zbOCBzNtmawxr92bVTOE31fJv6FhtCnQiD6tuPQVGMYhcmAj7eihtvuEMFfqEPcQ==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-2.27.3.tgz", + "integrity": "sha512-0KF+iweOlegWjsRDJO7EZL1bmmcghNmjPbcSvvyeF19Lh7Nit44dYV0w1JCDvweRRAXECYFXpxZTcIvSf0fEng==", "license": "MIT", "dependencies": { "linkifyjs": "^4.3.2" @@ -10769,180 +10757,180 @@ } }, "node_modules/@tiptap/extension-list-item": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.202.tgz", - "integrity": "sha512-15yAsO+CCM8ievdX4oxg8kMBVFqhzVAw7pU6E8KL76kIwWCIIyVW6hU3VZdglyBVnAG0ws5/DaZ4VRFtVPRDvg==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.27.3.tgz", + "integrity": "sha512-jWh5tZdNiZDx8X3jKV80EM6zMfUeRD3HKNVGcj5izqNncgH+/jJtF3hDmpP0nbFmhren8BQFo6W5f9L/GqtAVA==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-ordered-list": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.202.tgz", - "integrity": "sha512-PpJn8EtS8MLZ4NN9R3crmrivbjTMHjuSE2Ab3Y9TdeR9x9DIF23O/EkunnkPUiBUx6sNADprEWJIQesgpakrtw==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.27.3.tgz", + "integrity": "sha512-RvxSnE8rpiMSosD7ANCsyA+7XPEz0R6mDOFlORMqAf+NnPfCnH8dguVuKBGOdodPj69NcTSlA/6VBCS+3J0CLw==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-paragraph": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.202.tgz", - "integrity": "sha512-QI86DMUAz5froDJJXpbFV0I+iSFikjhQ8W5clYDbnrP/clRI/FYxklQ3oxSk4VzGBGB5EaBJf+jD7htLKb39UA==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.27.3.tgz", + "integrity": "sha512-Nbevu3wZk212NDpp1FaN05UbTHA4NHP2B5bAmkP8z3I+/ITvEgp7p9vFqJxZhe7fmqCSFlzhKj8ibmBc+Iu4CQ==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-strike": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.202.tgz", - "integrity": "sha512-cs87UI/VTkmSfIwlHpm7nAPXok2bAQvxmNJ1y7UPzTATVl+ixP1F4aIkwiYk+X7rE/Sys+09PGg1Pr1shwUUkQ==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.27.3.tgz", + "integrity": "sha512-9Ax1UIRDOdPk/bGnHbKM39Bw+Zb0PV8IInlT6hr8K1or0wWZuiyE4zlKP3bhAB6IcDr4mJLJQ6TEmxKihivC5A==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-table": { - "version": "2.0.0-beta.217", - "resolved": "https://registry.npmjs.org/@tiptap/extension-table/-/extension-table-2.0.0-beta.217.tgz", - "integrity": "sha512-8PwfNXIRPy1zxZAk0kS+sqFeUE2M6al1y/mA6p0SA9YhSN0iWvjQfmq9Ds52hmRcL2Dv9QmLR97S7WGRmHKcQg==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-table/-/extension-table-2.27.3.tgz", + "integrity": "sha512-xBDaT/ixkmrHKuCUlJNbzRolxjf0fFkHxybyeqfcGNDbVwOb6pOGZly6mGjBG1TXrx3U37y0jmFpwW6WU1zokA==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.209", - "@tiptap/pm": "^2.0.0-beta.209" + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" } }, "node_modules/@tiptap/extension-table-cell": { - "version": "2.0.0-beta.217", - "resolved": "https://registry.npmjs.org/@tiptap/extension-table-cell/-/extension-table-cell-2.0.0-beta.217.tgz", - "integrity": "sha512-W5UxsZxQdBms916hHp4giXi6AOkwCEfSaTXfi3FQqxcg/EQnmzMNB82/9BcVqBUaoJrx1dIVm4ploIL+GikG/w==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-table-cell/-/extension-table-cell-2.27.3.tgz", + "integrity": "sha512-f697x9RDiva8EFZvLBxEp6Nx6sY5KRbHdNMhbCnqC1PrkRKNCTOib9ddWpqIERzs3HhmqZWL7XCPzvE/t8C+IQ==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.209" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-table-header": { - "version": "2.0.0-beta.217", - "resolved": "https://registry.npmjs.org/@tiptap/extension-table-header/-/extension-table-header-2.0.0-beta.217.tgz", - "integrity": "sha512-oahTLhItvoPzCA9RuGLowZ0ZGro+Yn3+1NefXu/yGlp3twKQyhrwOv3+TqZ21L+8uKGOVLfLgPZnF6oNozEdJQ==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-table-header/-/extension-table-header-2.27.3.tgz", + "integrity": "sha512-x//GuYJlTzM3GavsDxBRDjGHMY9bbnmglQ0EAPVwQM5QHXpjwKzZN7wvDMM/RwxmxzYWd6Z+Fp7Zk8RYckpzhg==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.209" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-table-row": { - "version": "2.0.0-beta.217", - "resolved": "https://registry.npmjs.org/@tiptap/extension-table-row/-/extension-table-row-2.0.0-beta.217.tgz", - "integrity": "sha512-6ie3YtnOliIzER4JtVh0T8HQl3Z2gwTBoCOvqoetsoKIk0zNdsai+ZjVjVN4ZiMLFNYm5xnCUfr83usp9kawhQ==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-table-row/-/extension-table-row-2.27.3.tgz", + "integrity": "sha512-0ekXiw6aAESlcrKFmI90ar/j7XJmfdxeJEDeGZuMwOAQs+qq5RAB7ug5WPCZjG0Kqa+Kyxzb1jMw9pSkuTYp+w==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.209" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-task-item": { - "version": "2.0.0-beta.213", - "resolved": "https://registry.npmjs.org/@tiptap/extension-task-item/-/extension-task-item-2.0.0-beta.213.tgz", - "integrity": "sha512-yjdLBfFQcFFn4KQauwViZGiMScuUW838nmsa1nONHIWo8jDNrmAYLlanKiA8CKZUdwSpzIWM6eo1Ks2X5Pr5WA==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-task-item/-/extension-task-item-2.27.3.tgz", + "integrity": "sha512-7ES+qMoMgjb2iXI8iRzgegMeM1pE4zQAekT/5lQyuTv6oEyZw5s3TUZWeTYCq5TI/MezYGu3X2sV5PQnfBAsdA==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.209", - "@tiptap/pm": "^2.0.0-beta.209" + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" } }, "node_modules/@tiptap/extension-task-list": { - "version": "2.0.0-beta.213", - "resolved": "https://registry.npmjs.org/@tiptap/extension-task-list/-/extension-task-list-2.0.0-beta.213.tgz", - "integrity": "sha512-6pwJQhb4F+hSAXN/arh0fz99NQVVL0GkCuFKdhhkpRjKF5Fqs657RcKphzAkNmm7IPiHcrMr19og930sjSrjKQ==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-task-list/-/extension-task-list-2.27.3.tgz", + "integrity": "sha512-T8Y3S95ZzYlh82KGd0H81QOsJZVWweUVps6l7wkiOReNsJxhkb4qW/smNE0TeNhvbU307emiPL0CH5e+eHxjEg==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.209" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-text": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.0.0-beta.202.tgz", - "integrity": "sha512-6UsfU9xvKTxHfZYxVJy5DSQ0ibnhC403KLRQ4ePwpJql0TotBx93/CBfPCVLFEwF86HNhf1fFUCx+j2wuwVxmA==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.27.3.tgz", + "integrity": "sha512-9VnSK7qXUuZevNzE0FIymbc8BbY5X+0k4NxxO2dtPBOX4IoNHcWzmpLcuCggd3uN6XYLAXhDi/w2hkmBtig8Mw==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-text-align": { - "version": "2.0.0-beta.212", - "resolved": "https://registry.npmjs.org/@tiptap/extension-text-align/-/extension-text-align-2.0.0-beta.212.tgz", - "integrity": "sha512-1d1sgQaekWJ2Od2F278WauYVmGAkpCF2agTaUeYmBtQSkRjIlL5Y11KtvdqmhBaYVOLBwoSPD3Wtg1FHCqhaeA==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text-align/-/extension-text-align-2.27.3.tgz", + "integrity": "sha512-1gUN+rdCkuYDePfY8/AixiftkXZDqDN1czZS+e5QIZCNcYnFPIIVu4qurE9kaE0NYo46/RPhPERFBQAbK+dWFw==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.209" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/extension-text-style": { - "version": "2.0.0-beta.212", - "resolved": "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-2.0.0-beta.212.tgz", - "integrity": "sha512-z8UMzM4VYFJOZBx3ndjKj90LNYf/uxovHPMACgDQZeSlB21PWIEqco2kBNMPYzziAFIwKFRwKZj4+P7RPNVW8g==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-2.27.3.tgz", + "integrity": "sha512-Z4ZKju7vA2vUCeWVgEWERHvnln6XtgEMcb29xW8i25dSrw5Qefn/b+ym7JPkaMvjWbbQ+5VtECiaEYdL3rRH6Q==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.209" + "@tiptap/core": "^2.7.0" } }, "node_modules/@tiptap/pm": { - "version": "2.27.2", - "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.27.2.tgz", - "integrity": "sha512-kaEg7BfiJPDQMKbjVIzEPO3wlcA+pZb2tlcK9gPrdDnEFaec2QTF1sXz2ak2IIb2curvnIrQ4yrfHgLlVA72wA==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.27.3.tgz", + "integrity": "sha512-E9mBCSwe8YdWXvpjRMqddx4Yd5lEj+EprNM+4J+MtBXPGFZCUAa90rkOKU4m+Pn7rd1N5s7wRsExqFco79twbg==", "license": "MIT", "dependencies": { "prosemirror-changeset": "^2.3.0", @@ -10962,7 +10950,7 @@ "prosemirror-tables": "^1.6.4", "prosemirror-trailing-node": "^3.0.0", "prosemirror-transform": "^1.10.2", - "prosemirror-view": "^1.37.0" + "prosemirror-view": "^1.42.3" }, "funding": { "type": "github", @@ -10970,50 +10958,55 @@ } }, "node_modules/@tiptap/react": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-2.0.0-beta.202.tgz", - "integrity": "sha512-K0vjWOhqBFSN68wdIWvfUOer38GbBdOi80cZH7bafZQbka2gD8l6v0qknwM4KxOiq9FpqGBOVmGQs0ukgWGSDA==", + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-2.27.3.tgz", + "integrity": "sha512-7kqQXcRv56QQjB6nnv4P3Lc0D5ChFxzvnWmyQ70eYXZ56pxPfAlgxdViVAb17X89bZ/ypWHbpWZRrd3gUydMwQ==", "license": "MIT", "dependencies": { - "@tiptap/extension-bubble-menu": "^2.0.0-beta.202", - "@tiptap/extension-floating-menu": "^2.0.0-beta.202", - "prosemirror-view": "^1.28.2" + "@tiptap/extension-bubble-menu": "^2.27.3", + "@tiptap/extension-floating-menu": "^2.27.3", + "@types/use-sync-external-store": "^0.0.6", + "fast-deep-equal": "^3", + "use-sync-external-store": "^1" }, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.193", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/@tiptap/starter-kit": { - "version": "2.0.0-beta.202", - "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.0.0-beta.202.tgz", - "integrity": "sha512-hmtHgSKMAYtPNA12pa6kPortaKtsz4D6a18KncP26cWkuIwSBZLANls8L7vBISAcbIKRrSizsmqDBoDrFqtQcg==", - "license": "MIT", - "dependencies": { - "@tiptap/core": "^2.0.0-beta.202", - "@tiptap/extension-blockquote": "^2.0.0-beta.202", - "@tiptap/extension-bold": "^2.0.0-beta.202", - "@tiptap/extension-bullet-list": "^2.0.0-beta.202", - "@tiptap/extension-code": "^2.0.0-beta.202", - "@tiptap/extension-code-block": "^2.0.0-beta.202", - "@tiptap/extension-document": "^2.0.0-beta.202", - "@tiptap/extension-dropcursor": "^2.0.0-beta.202", - "@tiptap/extension-gapcursor": "^2.0.0-beta.202", - "@tiptap/extension-hard-break": "^2.0.0-beta.202", - "@tiptap/extension-heading": "^2.0.0-beta.202", - "@tiptap/extension-history": "^2.0.0-beta.202", - "@tiptap/extension-horizontal-rule": "^2.0.0-beta.202", - "@tiptap/extension-italic": "^2.0.0-beta.202", - "@tiptap/extension-list-item": "^2.0.0-beta.202", - "@tiptap/extension-ordered-list": "^2.0.0-beta.202", - "@tiptap/extension-paragraph": "^2.0.0-beta.202", - "@tiptap/extension-strike": "^2.0.0-beta.202", - "@tiptap/extension-text": "^2.0.0-beta.202" + "version": "2.27.3", + "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.27.3.tgz", + "integrity": "sha512-xqglSBavS4PDCWVFVruQPPRbmisWatXu7PZvzZSbR6HrLEX4ccRC3fNayRy9dUgDhuh2iLtEaXkVmy1Sd8DjBw==", + "license": "MIT", + "dependencies": { + "@tiptap/core": "^2.27.3", + "@tiptap/extension-blockquote": "^2.27.3", + "@tiptap/extension-bold": "^2.27.3", + "@tiptap/extension-bullet-list": "^2.27.3", + "@tiptap/extension-code": "^2.27.3", + "@tiptap/extension-code-block": "^2.27.3", + "@tiptap/extension-document": "^2.27.3", + "@tiptap/extension-dropcursor": "^2.27.3", + "@tiptap/extension-gapcursor": "^2.27.3", + "@tiptap/extension-hard-break": "^2.27.3", + "@tiptap/extension-heading": "^2.27.3", + "@tiptap/extension-history": "^2.27.3", + "@tiptap/extension-horizontal-rule": "^2.27.3", + "@tiptap/extension-italic": "^2.27.3", + "@tiptap/extension-list-item": "^2.27.3", + "@tiptap/extension-ordered-list": "^2.27.3", + "@tiptap/extension-paragraph": "^2.27.3", + "@tiptap/extension-strike": "^2.27.3", + "@tiptap/extension-text": "^2.27.3", + "@tiptap/extension-text-style": "^2.27.3", + "@tiptap/pm": "^2.27.3" }, "funding": { "type": "github", @@ -13037,9 +13030,9 @@ "license": "MIT" }, "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.10.0.tgz", + "integrity": "sha512-AidJptpBJmjTclAp9BkLwJi0T93fo5epJnbaZslpg6QVzpHjAiveF55mE9AcUJiGMqRHgMDY8soMsQtuNYMHfw==", "license": "MIT" }, "node_modules/colorette": { @@ -14268,9 +14261,9 @@ "link": true }, "node_modules/docusaurus-plugin-openapi-docs": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/docusaurus-plugin-openapi-docs/-/docusaurus-plugin-openapi-docs-5.0.2.tgz", - "integrity": "sha512-WCC2m6PpylXZfNga+ScelTG0a7jUGtbB9+AmbR9lUj93FPryTs8VHTMJ3fKtO0senJTWgOU3MDvZw0v+mE3ztA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/docusaurus-plugin-openapi-docs/-/docusaurus-plugin-openapi-docs-5.2.0.tgz", + "integrity": "sha512-MjrfRAMB64uvdxRVz6L9AXWe4QFjCdoBAzYs306yyI3nnXHsFj2lv2FnLA90JV9CAUZaGiYMvvkzBo2Nrkq/9w==", "license": "MIT", "dependencies": { "@apidevtools/json-schema-ref-parser": "^15.3.3", @@ -14334,9 +14327,9 @@ } }, "node_modules/docusaurus-theme-openapi-docs": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/docusaurus-theme-openapi-docs/-/docusaurus-theme-openapi-docs-5.0.2.tgz", - "integrity": "sha512-BD6WhbunR6kXqtoUUDlhxO4HlCNM2nYENGr/TbiTEknkgXYKQz+FEIhY4Hyz5GSLpuhPih0CDuNl7Xkfpcz0Yw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/docusaurus-theme-openapi-docs/-/docusaurus-theme-openapi-docs-5.2.0.tgz", + "integrity": "sha512-L0b80LzaMUfr76a9EQXRPCf8nxkEz8Xo6Aknnke1UeE2oXsgoiVki6U+RTE7GmJRjO8zSNKXyckGmGmqqWuHeA==", "license": "MIT", "dependencies": { "@hookform/error-message": "^2.0.1", @@ -14348,7 +14341,7 @@ "crypto-js": "^4.2.0", "file-saver": "^2.0.5", "lodash": "^4.17.21", - "pako": "^2.1.0", + "pako": "^3.0.1", "path-browserify": "^1.0.1", "postman-code-generators": "^2.0.0", "postman-collection": "^5.0.2", @@ -14363,7 +14356,7 @@ "rehype-raw": "^7.0.0", "remark-gfm": "4.0.1", "sass": "^1.89.2", - "sass-loader": "^16.0.5", + "sass-loader": "^17.0.0", "unist-util-visit": "^5.0.0", "url": "^0.11.4", "xml-formatter": "^3.6.6" @@ -14388,6 +14381,55 @@ "node": ">=6" } }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/pako": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pako/-/pako-3.0.2.tgz", + "integrity": "sha512-uBv6IT2aT1A78iU6dpNEbf6+CyhlV/6g9JlJs9kpgjFGFhruIICVRysF/W0SLzXg5+hCl+KroH7e4YUyfEmgLg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "(MIT AND Zlib)" + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/sass-loader": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-17.0.1.tgz", + "integrity": "sha512-pgJMwCuLjVTSIWsv/2luVRXKlCeaViUGcgSe8dx95zMG4hUwqIMFmjbhq29ypFLflJU0GyiJZeLM9iI1n3KYAA==", + "license": "MIT", + "engines": { + "node": ">= 22.11.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, "node_modules/dom-converter": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", @@ -15815,9 +15857,9 @@ } }, "node_modules/gray-matter/node_modules/js-yaml": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.1.tgz", - "integrity": "sha512-S99WuO3HlhO3XN41EtYUNl9zzXjoJx7QvmipxsJVxtCBT0YHEFy+iOJhjSvrmV12nYhWpZaM8lPHkJm0yUMbag==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.2.tgz", + "integrity": "sha512-6EuL879VkRA+1Cz578mKMiKvjPNEuk6+r1JaFzoSWejZmtf7xWbIyw1e3KkxlkzTIt9Taw6JBhEppG7utc1P+w==", "license": "MIT", "dependencies": { "argparse": "^1.0.7", @@ -17320,15 +17362,15 @@ } }, "node_modules/image-size": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-2.0.2.tgz", - "integrity": "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-2.0.4.tgz", + "integrity": "sha512-QRUkFFsRV/6fuESxb9Vkq+a0LkSrgKXuc2NEqfikiXxxN/G3tjWt5EVUlMaImRBZRZK/jRBEbYvpPYZL8t08Zw==", "license": "MIT", "bin": { "image-size": "bin/image-size.js" }, "engines": { - "node": ">=16.x" + "node": ">=18" } }, "node_modules/immer": { @@ -17880,9 +17922,9 @@ } }, "node_modules/joi": { - "version": "17.13.4", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.4.tgz", - "integrity": "sha512-1RuuER6kmt8K8I3nIWvPZKi5RQCb568ZPyY4Pwjlua+yo+63ZTmIwxLZH0heBmiKN4uxjvCiarDrjaeH84xicQ==", + "version": "17.13.8", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.8.tgz", + "integrity": "sha512-iPKOGmiRw1jxf/JOPwxmCcUQAOdF359mdzYiP2DJ+TMX0YK2zjK3D+zYOaGjpumWxOFF/l2xVWjRVK5bGSLdEw==", "license": "BSD-3-Clause", "dependencies": { "@hapi/hoek": "^9.3.0", @@ -17908,9 +17950,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", - "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", "funding": [ { "type": "github", @@ -21633,9 +21675,9 @@ } }, "node_modules/openapi-to-postmanv2": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/openapi-to-postmanv2/-/openapi-to-postmanv2-6.0.1.tgz", - "integrity": "sha512-zAjaTwXo07az6jjvZTw4d26QMQsFxZBxTqjj3LQQMDCCuO6+peATQc9bSmAq3QbzvikP+h2WEjTphMcIrcSurg==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/openapi-to-postmanv2/-/openapi-to-postmanv2-6.3.3.tgz", + "integrity": "sha512-o0u6qqMMRLt7eAyFBpL/lCresQ1VqQFGe6/iPMBvNkWDXrpgGo5jo+YnP1e0MwF3tdUKLfkHssufGWMdojpPLg==", "license": "Apache-2.0", "dependencies": { "ajv": "^8.11.0", @@ -21644,10 +21686,10 @@ "async": "3.2.6", "commander": "2.20.3", "graphlib": "2.1.8", - "js-yaml": "4.1.0", + "js-yaml": "4.3.0", "json-pointer": "0.6.2", "json-schema-merge-allof": "0.8.1", - "lodash": "4.17.21", + "lodash": "4.18.1", "neotraverse": "0.6.15", "oas-resolver-browser": "2.5.6", "object-hash": "3.0.0", @@ -24200,9 +24242,9 @@ } }, "node_modules/postman-collection": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-5.3.0.tgz", - "integrity": "sha512-PMa5vRheqDFfS1bkRg8WBidWxunRA80sT5YNLP27YC5+ycyfiLMCwPnqQd1zfvxkGk04Pr9UronWmmgsbpsVyQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-5.3.1.tgz", + "integrity": "sha512-+ixY4KEGerw3I5dE6obXgXx31na8URU5ODNIA6Rjkbt3/BUpNRk03pxUAZFHr5dDXwCikJSa7pt5o0x1QXT77w==", "license": "Apache-2.0", "dependencies": { "@faker-js/faker": "5.5.3", @@ -24210,7 +24252,7 @@ "http-reasons": "0.1.0", "iconv-lite": "0.6.3", "liquid-json": "0.3.1", - "lodash": "4.17.23", + "lodash": "4.18.1", "mime": "3.0.0", "mime-format": "2.0.2", "postman-url-encoder": "3.0.8", @@ -24221,13 +24263,6 @@ "node": ">=18" } }, - "node_modules/postman-collection/node_modules/@faker-js/faker": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-5.5.3.tgz", - "integrity": "sha512-R11tGE6yIFwqpaIqcfkcg7AICXzFg14+5h5v0TfF/9+RMDL6jhzCy/pxHVOfbALGdtVYdt6JdR21tuxEgl34dw==", - "deprecated": "Please update to a newer version.", - "license": "MIT" - }, "node_modules/postman-collection/node_modules/semver": { "version": "7.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", @@ -24450,9 +24485,9 @@ } }, "node_modules/prosemirror-model": { - "version": "1.25.4", - "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.4.tgz", - "integrity": "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==", + "version": "1.25.11", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.11.tgz", + "integrity": "sha512-QWg9RhnpLlogAmp3p96uEFrE5txQpFynd4vhBAELkwgOCWQs/X0yCzB3/hrHqiPwf91RG5KyWq6553zs9JqIOQ==", "license": "MIT", "dependencies": { "orderedmap": "^2.0.0" @@ -24527,12 +24562,12 @@ } }, "node_modules/prosemirror-view": { - "version": "1.41.8", - "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.8.tgz", - "integrity": "sha512-TnKDdohEatgyZNGCDWIdccOHXhYloJwbwU+phw/a23KBvJIR9lWQWW7WHHK3vBdOLDNuF7TaX98GObUZOWkOnA==", + "version": "1.42.4", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.42.4.tgz", + "integrity": "sha512-H/LErnE8Vms1GYkvhfj6G3K9rc2p+o5EHGmTwvPOl0f21wPPxlMVRB8ICOseH+COb2oPKFEoufbgY6yet/dR4w==", "license": "MIT", "dependencies": { - "prosemirror-model": "^1.20.0", + "prosemirror-model": "^1.25.8", "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.1.0" } @@ -29227,14 +29262,14 @@ "license": "MIT" }, "node_modules/sharp": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.0.tgz", - "integrity": "sha512-BqvG5XbwPZ4NV0DK90d86leEECMsoa8bO0nqnKWlBDYxri4GJ7c4EDInaF6q20lTh/mATmnDIKWJFfXnoVfH5g==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.4.tgz", + "integrity": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==", "license": "Apache-2.0", "dependencies": { "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", - "semver": "^7.8.4" + "semver": "^7.8.5" }, "engines": { "node": ">=20.9.0" @@ -29243,31 +29278,36 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.35.0", - "@img/sharp-darwin-x64": "0.35.0", - "@img/sharp-freebsd-wasm32": "0.35.0", - "@img/sharp-libvips-darwin-arm64": "1.3.0", - "@img/sharp-libvips-darwin-x64": "1.3.0", - "@img/sharp-libvips-linux-arm": "1.3.0", - "@img/sharp-libvips-linux-arm64": "1.3.0", - "@img/sharp-libvips-linux-ppc64": "1.3.0", - "@img/sharp-libvips-linux-riscv64": "1.3.0", - "@img/sharp-libvips-linux-s390x": "1.3.0", - "@img/sharp-libvips-linux-x64": "1.3.0", - "@img/sharp-libvips-linuxmusl-arm64": "1.3.0", - "@img/sharp-libvips-linuxmusl-x64": "1.3.0", - "@img/sharp-linux-arm": "0.35.0", - "@img/sharp-linux-arm64": "0.35.0", - "@img/sharp-linux-ppc64": "0.35.0", - "@img/sharp-linux-riscv64": "0.35.0", - "@img/sharp-linux-s390x": "0.35.0", - "@img/sharp-linux-x64": "0.35.0", - "@img/sharp-linuxmusl-arm64": "0.35.0", - "@img/sharp-linuxmusl-x64": "0.35.0", - "@img/sharp-webcontainers-wasm32": "0.35.0", - "@img/sharp-win32-arm64": "0.35.0", - "@img/sharp-win32-ia32": "0.35.0", - "@img/sharp-win32-x64": "0.35.0" + "@img/sharp-darwin-arm64": "0.35.4", + "@img/sharp-darwin-x64": "0.35.4", + "@img/sharp-freebsd-wasm32": "0.35.4", + "@img/sharp-libvips-darwin-arm64": "1.3.3", + "@img/sharp-libvips-darwin-x64": "1.3.3", + "@img/sharp-libvips-linux-arm": "1.3.3", + "@img/sharp-libvips-linux-arm64": "1.3.3", + "@img/sharp-libvips-linux-ppc64": "1.3.3", + "@img/sharp-libvips-linux-riscv64": "1.3.3", + "@img/sharp-libvips-linux-s390x": "1.3.3", + "@img/sharp-libvips-linux-x64": "1.3.3", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3", + "@img/sharp-libvips-linuxmusl-x64": "1.3.3", + "@img/sharp-linux-arm": "0.35.4", + "@img/sharp-linux-arm64": "0.35.4", + "@img/sharp-linux-ppc64": "0.35.4", + "@img/sharp-linux-riscv64": "0.35.4", + "@img/sharp-linux-s390x": "0.35.4", + "@img/sharp-linux-x64": "0.35.4", + "@img/sharp-linuxmusl-arm64": "0.35.4", + "@img/sharp-linuxmusl-x64": "0.35.4", + "@img/sharp-webcontainers-wasm32": "0.35.4", + "@img/sharp-win32-arm64": "0.35.4", + "@img/sharp-win32-ia32": "0.35.4", + "@img/sharp-win32-x64": "0.35.4" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, "node_modules/shebang-command": { @@ -30001,9 +30041,9 @@ "license": "MIT" }, "node_modules/svgo": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.4.tgz", - "integrity": "sha512-GsNRis4e8jxn2Y9ENz/8lbJ93CstG8svtMnuRaHbiF2LTJ5tK0/q3t/URPq9Zc7zVWBJnNnJMIp6bevK7bSmNg==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.5.tgz", + "integrity": "sha512-8SQMzdrvWaD8deUmrnYB+ASyxBVgWUOilg+A75nE/76WdLpj6LopCwiAVvkzkcqy/9b7t2Mg7faFLjg0ZRcZ3w==", "license": "MIT", "dependencies": { "commander": "^7.2.0", diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 3ccbe501..3407e79a 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,6 +1,7 @@ import React from 'react'; import clsx from 'clsx'; import Link from '@docusaurus/Link'; +import Head from '@docusaurus/Head'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import Layout from '@theme/Layout'; import HomepageFeatures from '@site/src/components/HomepageFeatures'; @@ -35,6 +36,11 @@ export default function Home(): JSX.Element { const {siteConfig} = useDocusaurusContext() const data = landingJson return ( - + <> + + + + + ); } \ No newline at end of file