From bd2011b1308595ca548ced975b6be177de62aaa3 Mon Sep 17 00:00:00 2001 From: Amit Sharma Date: Fri, 18 Sep 2026 18:57:56 +0530 Subject: [PATCH 01/17] =?UTF-8?q?chore(deps):=20patch-duty=20=E2=80=94=20c?= =?UTF-8?q?lose=206=20advisories=20in=20the=20lockfile=20(48=20->=2042)=20?= =?UTF-8?q?(#164)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lockfile-only, semver-compatible bumps: 4 high and 1 low closed, 48 -> 42 total. The 42 that remain both need a major bump of a direct dependency and so are not appropriate for a lockfile sweep — recorded in the Change Request issue instead: - @faker-js/faker (high), reached through postman-collection; fix is docusaurus-theme-openapi-docs@2.1.3, a major. - @tiptap/core (moderate, 36 instances across the tiptap extension set); fix is the tiptap 3.31.3 line, also a major. Not addressed here: vendor/docusaurus-plugin-llms is a git submodule, so it has no lockfile entry in this repo and Dependabot cannot see it. Its own tree audits at 44 advisories, but every one is in upstream's dev/test toolchain rather than anything this site ships. Noted in the CR issue. Co-authored-by: Claude Opus 5 (1M context) --- package-lock.json | 786 ++++++++++++++++++++++++---------------------- 1 file changed, 413 insertions(+), 373 deletions(-) diff --git a/package-lock.json b/package-lock.json index b7326b6..944e5ee 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", From 679e4d38e2b7eaf11ececcbd90c7bf862dcae97a Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 09:01:32 -0400 Subject: [PATCH 02/17] fix(ci): deploy with cloudflare/wrangler-action (pages-action was removed) --- .github/workflows/deploy.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7ba91bd..628adb4 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 From 7129a467b761d9f609cb7f2983f69cd3a17c1a35 Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 06:56:57 -0400 Subject: [PATCH 03/17] [Trace] Content audit: enrich thin API reference pages: 21 of 24 remaining docs/API/*.api.mdx Rolls out the PR #155 pattern (real description, when-to-use, curl example, verified request/response, common-errors table, related links) to every docs/API/*.api.mdx page under 300 live words, excluding the 3 pages #155 already enriched (delete-template, get-templates-and-folders, upload-template-with-optional-default-values) and the turbodocx-api-documentation info page. Covered: 3 template endpoints (edit-template-metadata, get-template-by-id, extract-template-placeholders-and-generate-preview), all 10 TurboSign webhook endpoints (create/get/update/delete/notify/test/regenerate-secret/ list-deliveries/replay-delivery/get-stats), and 8 tag/variable endpoints (create/read/update-tag, delete-tags-by-i-ds, create-image-variable-folder, read-variables-folder, update-variable-by-id, delete-variables-by-i-ds). Every path, method, field, response shape, and error was verified against the route/handler code in RapidDocxBackend (Template, Webhooks, Tag, Variable routes + handlers), not the OpenAPI spec, which is stale in several places. Also fixed two pre-existing frontmatter issues on webhook pages: an em-dash and an inaccurate "soft-delete" claim on delete-webhook (the handler hard-deletes the row). --- docs/API/create-image-variable-folder.api.mdx | 71 ++++++++++++++++- docs/API/create-tag.api.mdx | 54 ++++++++++++- docs/API/create-webhook.api.mdx | 68 +++++++++++++++- docs/API/delete-tags-by-i-ds.api.mdx | 48 +++++++++++- docs/API/delete-variables-by-i-ds.api.mdx | 47 ++++++++++- docs/API/delete-webhook.api.mdx | 45 ++++++++++- docs/API/edit-template-metadata.api.mdx | 47 ++++++++++- ...-placeholders-and-generate-preview.api.mdx | 64 ++++++++++++++- docs/API/get-template-by-id.api.mdx | 77 ++++++++++++++++++- docs/API/get-webhook-stats.api.mdx | 73 +++++++++++++++++- docs/API/get-webhook.api.mdx | 72 ++++++++++++++++- docs/API/list-webhook-deliveries.api.mdx | 67 +++++++++++++++- docs/API/notify-webhook.api.mdx | 65 +++++++++++++++- docs/API/read-tag.api.mdx | 57 +++++++++++++- docs/API/read-variables-folder.api.mdx | 64 ++++++++++++++- docs/API/regenerate-webhook-secret.api.mdx | 50 +++++++++++- docs/API/replay-webhook-delivery.api.mdx | 62 ++++++++++++++- docs/API/test-webhook.api.mdx | 65 +++++++++++++++- docs/API/update-tag.api.mdx | 52 ++++++++++++- docs/API/update-variable-by-id.api.mdx | 66 +++++++++++++++- docs/API/update-webhook.api.mdx | 67 +++++++++++++++- 21 files changed, 1200 insertions(+), 81 deletions(-) diff --git a/docs/API/create-image-variable-folder.api.mdx b/docs/API/create-image-variable-folder.api.mdx index 1d5c767..67229ce 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,72 @@ 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 + }' +``` + +Send exactly one of `templateFolderId` (scopes the variable to that folder) or `isGlobal: true` (adds it to your org-wide knowledge base); 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) | +| 400 | `mimeType` or `text` is missing, `placeholder` is not wrapped in `{ }`, or both `isGlobal` and `templateFolderId` are set | `{ "message", "type": "ValidationError", "data": { "errors": [...] } }` | +| 400 | `placeholder` 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 5bc01bc..0a7c590 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 0dcec8f..d427865 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` within your org; every TurboDocx SDK sends `"signature"`, so a second create call with the default name fails with a conflict instead of creating a duplicate. + +## 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_9f1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f8", + "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 | `{ "error": "..." }` (validation) | +| 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 43bd89a..fb608a4 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 a091066..80a5b56 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 e65e2be..eaa7d93 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 8cc7363..7bc21a5 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 a294ce2..b69616a 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`, a base64-encoded PDF rendering of the uploaded file. 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 726c2b1..2c7871c 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 0190dfa..3f8fd4d 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 f763efa..b5bef80 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 b4f583b..87d4a8c 100644 --- a/docs/API/list-webhook-deliveries.api.mdx +++ b/docs/API/list-webhook-deliveries.api.mdx @@ -16,9 +16,70 @@ 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`. + +## 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 (1, 5, then 10 minutes) up to `maxAttempts` (3) 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 d9c9a8c..aa8988f 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 b03b62c..a5a35b6 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,58 @@ 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; there is no dedicated "get tag by ID" endpoint. + +## 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 + diff --git a/docs/API/read-variables-folder.api.mdx b/docs/API/read-variables-folder.api.mdx index 93cb9e3..bbb7ff9 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" +``` + +Pass exactly one of `isGlobal=true` (your org-wide knowledge base) or `templateFolderId=` (a specific folder); the two are mutually exclusive. `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 ada4d07..9329032 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_1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f809", + "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 c847a78..2fff874 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 attempts redelivery to all configured URLs." 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 webhook's configured URL. + +## 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 004ab81..db8794f 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`, `status: "retrying"` or `"failed"`, and the failure is counted in `summary.failed` with a message in `summary.errors`. + +## 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 2ef7f7b..0c92465 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 can usefully send; the tag's other fields (`id`, `orgId`) are not accepted in the body. + +## 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 217e2f9..480d161 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,67 @@ 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, along with either `isGlobal` or `templateFolderId`. + +## 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`. Send exactly one of `isGlobal: true` or `templateFolderId`; 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 | Empty (status only) | +| 423 | The template the variable belongs to is locked | `{ "error": "Resource is locked", "message", "data": { "locked": true, "lockedBy", "lockedOn" } }` | +| 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 6577d59..9009d83 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 | `{ "error": "..." }` | +| 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 + From 4d10aa175f95a68ab33db8040d9253e665fe4da3 Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 11:28:09 -0400 Subject: [PATCH 04/17] [Trace] Accuracy fixes from SDK-main/backend-master review --- docs/API/create-image-variable-folder.api.mdx | 7 ++++--- docs/API/create-webhook.api.mdx | 4 ++-- ...ract-template-placeholders-and-generate-preview.api.mdx | 2 +- docs/API/list-webhook-deliveries.api.mdx | 4 +++- docs/API/read-tag.api.mdx | 3 ++- docs/API/read-variables-folder.api.mdx | 2 +- docs/API/replay-webhook-delivery.api.mdx | 4 ++-- docs/API/test-webhook.api.mdx | 2 +- docs/API/update-tag.api.mdx | 2 +- docs/API/update-variable-by-id.api.mdx | 7 +++---- docs/API/update-webhook.api.mdx | 2 +- 11 files changed, 21 insertions(+), 18 deletions(-) diff --git a/docs/API/create-image-variable-folder.api.mdx b/docs/API/create-image-variable-folder.api.mdx index 67229ce..986c100 100644 --- a/docs/API/create-image-variable-folder.api.mdx +++ b/docs/API/create-image-variable-folder.api.mdx @@ -40,7 +40,7 @@ curl -X POST "https://api.turbodocx.com/Variable" \ }' ``` -Send exactly one of `templateFolderId` (scopes the variable to that folder) or `isGlobal: true` (adds it to your org-wide knowledge base); 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}`. +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 @@ -73,8 +73,9 @@ On success the endpoint returns the created variable: | ------ | ---- | ------------- | | 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 | `mimeType` or `text` is missing, `placeholder` is not wrapped in `{ }`, or both `isGlobal` and `templateFolderId` are set | `{ "message", "type": "ValidationError", "data": { "errors": [...] } }` | -| 400 | `placeholder` already exists in that folder or knowledge base | `{ "message", "type": "TemplateError", "data": [{ "message", "type", "data": { "explanation", "context" } }] }` | +| 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 diff --git a/docs/API/create-webhook.api.mdx b/docs/API/create-webhook.api.mdx index d427865..7091f14 100644 --- a/docs/API/create-webhook.api.mdx +++ b/docs/API/create-webhook.api.mdx @@ -17,7 +17,7 @@ custom_edit_url: null # 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` within your org; every TurboDocx SDK sends `"signature"`, so a second create call with the default name fails with a conflict instead of creating a duplicate. +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 @@ -70,7 +70,7 @@ On success the endpoint returns `201 Created`: | ------ | ---- | ------------- | | 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 | `{ "error": "..." }` (validation) | +| 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 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 b69616a..572c7d6 100644 --- a/docs/API/extract-template-placeholders-and-generate-preview.api.mdx +++ b/docs/API/extract-template-placeholders-and-generate-preview.api.mdx @@ -57,7 +57,7 @@ With `skipFile=true`: } ``` -Without `skipFile`, the response also includes `templatePdf`, a base64-encoded PDF rendering of the uploaded file. 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). +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 diff --git a/docs/API/list-webhook-deliveries.api.mdx b/docs/API/list-webhook-deliveries.api.mdx index 87d4a8c..92e44b8 100644 --- a/docs/API/list-webhook-deliveries.api.mdx +++ b/docs/API/list-webhook-deliveries.api.mdx @@ -34,6 +34,8 @@ curl "https://api.turbodocx.com/api/webhooks/signature/deliveries?limit=20&offse 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 @@ -64,7 +66,7 @@ Supported filters: `eventType`, `isDelivered` (`true`/`false`), and `httpStatus` } ``` -`status` summarizes the row as `"delivered"`, `"failed"` (all `maxAttempts` attempts exhausted), `"retrying"`, or `"pending"`. Failed deliveries retry automatically with backoff (1, 5, then 10 minutes) up to `maxAttempts` (3) before landing in the dead-letter state. +`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 diff --git a/docs/API/read-tag.api.mdx b/docs/API/read-tag.api.mdx index a5a35b6..4c48775 100644 --- a/docs/API/read-tag.api.mdx +++ b/docs/API/read-tag.api.mdx @@ -17,7 +17,7 @@ custom_edit_url: null # 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; there is no dedicated "get tag by ID" endpoint. +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 @@ -67,6 +67,7 @@ curl "https://api.turbodocx.com/Tag?limit=25&offset=0&query=legal" \ - [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 bbb7ff9..2429601 100644 --- a/docs/API/read-variables-folder.api.mdx +++ b/docs/API/read-variables-folder.api.mdx @@ -32,7 +32,7 @@ curl "https://api.turbodocx.com/Variable?isGlobal=true&limit=25&offset=0&showTag -H "Accept: application/json" ``` -Pass exactly one of `isGlobal=true` (your org-wide knowledge base) or `templateFolderId=` (a specific folder); the two are mutually exclusive. `limit` defaults to `6`, `offset` to `0`, and `query` filters by name. +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 diff --git a/docs/API/replay-webhook-delivery.api.mdx b/docs/API/replay-webhook-delivery.api.mdx index 2fff874..174fb9c 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 one past delivery by its ID. Creates a new delivery row and immediately attempts redelivery to all configured URLs." +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 @@ -17,7 +17,7 @@ custom_edit_url: null # 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 webhook's configured URL. +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 diff --git a/docs/API/test-webhook.api.mdx b/docs/API/test-webhook.api.mdx index db8794f..33f2d19 100644 --- a/docs/API/test-webhook.api.mdx +++ b/docs/API/test-webhook.api.mdx @@ -61,7 +61,7 @@ Both `eventType` and `payload` are optional; omit them to send a default sample } ``` -If a URL returns a non-2xx status or times out, its entry has `isDelivered: false`, `status: "retrying"` or `"failed"`, and the failure is counted in `summary.failed` with a message in `summary.errors`. +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 diff --git a/docs/API/update-tag.api.mdx b/docs/API/update-tag.api.mdx index 0c92465..6829518 100644 --- a/docs/API/update-tag.api.mdx +++ b/docs/API/update-tag.api.mdx @@ -17,7 +17,7 @@ custom_edit_url: null # Update Tag -The Update Tag endpoint changes a tag's `label`. It is a `PUT`, but in practice `label` is the only field you can usefully send; the tag's other fields (`id`, `orgId`) are not accepted in the body. +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 diff --git a/docs/API/update-variable-by-id.api.mdx b/docs/API/update-variable-by-id.api.mdx index 480d161..5b786f9 100644 --- a/docs/API/update-variable-by-id.api.mdx +++ b/docs/API/update-variable-by-id.api.mdx @@ -17,7 +17,7 @@ custom_edit_url: null # 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, along with either `isGlobal` or `templateFolderId`. +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 @@ -41,7 +41,7 @@ curl -X PUT "https://api.turbodocx.com/Variable/e4f5a6b7-8c9d-4e0f-a1b2-3c4d5e6f }' ``` -`{VariableId}` in the path is the `variableMapId` returned by [Read Variables (Folder)](/docs/API/read-variables-folder), not the underlying `Variable.id`. Send exactly one of `isGlobal: true` or `templateFolderId`; sending both is rejected. For an image variable, set `mimeType` to `"image"` and `text` to a base64 data string. +`{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 @@ -67,8 +67,7 @@ On success the endpoint returns `200 OK` with the updated variable wrapped in a | 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 the variable belongs to is locked | `{ "error": "Resource is locked", "message", "data": { "locked": true, "lockedBy", "lockedOn" } }` | +| 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" } }` | diff --git a/docs/API/update-webhook.api.mdx b/docs/API/update-webhook.api.mdx index 9009d83..69b9731 100644 --- a/docs/API/update-webhook.api.mdx +++ b/docs/API/update-webhook.api.mdx @@ -69,7 +69,7 @@ On success the endpoint returns `200 OK` with the updated webhook, in the same s | 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 | `{ "error": "..." }` | +| 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 From 8204c670990e7d9b1c18ea670be3f201907b9fb2 Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 07:31:59 -0400 Subject: [PATCH 05/17] [Trace] Template de-dup: de-duplicate SDK doc boilerplate across docs/SDKs 10 deliverable-*/partner-* pages carried a full copy of the generic Error Handling intro + status-code table already documented once on each language's canonical page (javascript.md, python.md, go.md, php.md, java.md). template-detector.mjs flagged the same 5-word phrases across ~17 files, matching the URL Inspection evidence that javascript, python, java, quote-javascript, webhooks-java, deliverable-go, and deliverable-php are crawled/discovered but not indexed. Replaced the duplicated table on each deliverable-*/partner-* page with a short paragraph naming the errors that operation actually raises (verified against /home/nicolas/repos/SDK), followed by a link to the language's own Error Handling reference for the full table. Kept the already-differentiated code samples and product-specific notes (Go's errors.As, PHP's typed exceptions, Java's nested TurboDocxException.* classes, partner's IOException/409-conflict callouts) as-is. Also: - Fixed a real bug found while verifying code samples: index.md's PHP error handling example called $e->getCode(), but PHP's Exception::getCode() is hardcoded to 0 by TurboDocxException's constructor; the real field is $e->errorCode. - Fixed two broken links (go.md, java.md pointed at /docs/TurboSign/API-Signatures instead of the correctly-encoded .../API%20Signatures used elsewhere in the same files) and two broken anchors (partner-php.md, partner-javascript.md linked to #orguserrole-organization-users, truncated; the real heading slugifies to #orguserrole-organization-users-and-org-api-keys). - Shortened 11 frontmatter descriptions over 160 chars (agent-skills + 5 quote-*/5 webhooks-* pages) to <=155 chars, language + product first. Not fixed (noted for the owner): docs/SDKs/ruby.md and deliverable-ruby.md 404 live but still get search impressions. This is intentional (draft: true, set in 40efd12 because the gem isn't on RubyGems yet); Docusaurus excludes draft pages from the production build. If those impressions are worth capturing, that needs a redirect decision, not a content change. --- docs/SDKs/agent-skills.md | 2 +- docs/SDKs/deliverable-go.md | 25 ++---------- docs/SDKs/deliverable-java.md | 29 +++----------- docs/SDKs/deliverable-javascript.md | 29 ++------------ docs/SDKs/deliverable-php.md | 25 ++---------- docs/SDKs/deliverable-python.md | 27 ++----------- docs/SDKs/go.md | 20 +++++----- docs/SDKs/index.md | 40 +++++++++---------- docs/SDKs/java.md | 32 +++++++-------- docs/SDKs/partner-go.md | 42 ++++++++------------ docs/SDKs/partner-java.md | 61 +++++++++++------------------ docs/SDKs/partner-javascript.md | 39 +++++++----------- docs/SDKs/partner-php.md | 33 ++++++---------- docs/SDKs/partner-python.md | 37 ++++++----------- docs/SDKs/quote-go.md | 2 +- docs/SDKs/quote-java.md | 2 +- docs/SDKs/quote-javascript.md | 2 +- docs/SDKs/quote-php.md | 2 +- docs/SDKs/quote-python.md | 2 +- docs/SDKs/webhooks-go.md | 2 +- docs/SDKs/webhooks-java.md | 2 +- docs/SDKs/webhooks-javascript.md | 2 +- docs/SDKs/webhooks-php.md | 2 +- docs/SDKs/webhooks-python.md | 2 +- 24 files changed, 152 insertions(+), 309 deletions(-) diff --git a/docs/SDKs/agent-skills.md b/docs/SDKs/agent-skills.md index d09b37c..a336459 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 13f61d3..8ae6151 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` most commonly returns `NotFoundError` when `TemplateID` doesn't match a template in the org, and `ValidationError` when a `DeliverableVariable` is missing `Placeholder` or `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 9df5d27..2c6bd24 100644 --- a/docs/SDKs/deliverable-java.md +++ b/docs/SDKs/deliverable-java.md @@ -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()` most commonly 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 0f85628..ee39b35 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()` most commonly rejects with `NotFoundError` when `templateId` doesn't match a template in the org, and `ValidationError` when an entry in `variables` is missing `placeholder` or `mimeType`. 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 d93524b..43eeec0 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()` most commonly throws `NotFoundException` when `templateId` doesn't match a template in the org, and `ValidationException` when a variable in the `variables` array is missing `placeholder` or `mimeType`: ### 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 9b916d1..a1cef4c 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()` most commonly raises `NotFoundError` when `template_id` doesn't match a template in the org, and `ValidationError` when a variable dict is missing `placeholder` or `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 760124e..b877cc2 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) @@ -610,7 +610,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 +711,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 cbc208b..2e11eee 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 | | :------------------------ | :-------------- | :---------------------------- | :----------------------------------------------------------------------------------------------------- | @@ -114,17 +114,17 @@ Before you begin, you'll need two things from your TurboDocx account: :::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. -**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 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). ::: #### 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` | — | +| **TurboSign** | `TURBODOCX_API_KEY` | `TURBODOCX_ORG_ID` | `TURBODOCX_SENDER_EMAIL` (required, reply-to for signer emails) | +| **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** (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 | +| **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) @@ -616,7 +616,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"; } ``` @@ -682,12 +682,12 @@ without a null check. ### 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. | +| `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 9a9f782..ace6d4f 100644 --- a/docs/SDKs/java.md +++ b/docs/SDKs/java.md @@ -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 @@ -660,7 +660,7 @@ 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 | +| `metadata` | `FieldMetadata` | No | Conditional (IF/THEN) metadata, see below | \*Required when not using template anchors @@ -678,14 +678,14 @@ at it. | `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 +`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 +// Controlling checkbox, carries a stable fieldKey Field checkbox = new Field.Builder() .type("checkbox") .recipientEmail("reviewer@company.com") @@ -693,7 +693,7 @@ Field checkbox = new Field.Builder() .metadata(FieldMetadata.forFieldKey("request_changes")) .build(); -// Dependent text field — hidden until the checkbox is checked +// Dependent text field, hidden until the checkbox is checked Field explain = new Field.Builder() .type("text") .recipientEmail("reviewer@company.com") @@ -762,5 +762,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/partner-go.md b/docs/SDKs/partner-go.md index f776753..80cebe1 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 most commonly 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" @@ -880,17 +880,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`/`RateLimitError`/`NetworkError` types. --- @@ -977,4 +967,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 9e806f3..a902aad 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! } } ``` @@ -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 most commonly 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. +`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. ::: -### 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 67d20d4..fbd68bb 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 most commonly 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 1c944c6..8372b6a 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 most commonly throw `AuthenticationException` when the partner API key or partner ID is wrong, since partner credentials are validated separately from organization API keys: ```php use TurboDocx\Exceptions\AuthenticationException; @@ -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 0765004..07e87d3 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 most commonly 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/quote-go.md b/docs/SDKs/quote-go.md index 7c094a4..0bb177d 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 e300d2a..38257b0 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 diff --git a/docs/SDKs/quote-javascript.md b/docs/SDKs/quote-javascript.md index b78bdae..a8ebdc2 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 diff --git a/docs/SDKs/quote-php.md b/docs/SDKs/quote-php.md index 6035da8..bf88961 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 70e22b1..3a73770 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 ea844b5..a9c6421 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 0b122f4..5488d56 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 diff --git a/docs/SDKs/webhooks-javascript.md b/docs/SDKs/webhooks-javascript.md index 85708d0..1e01d7a 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 b7ba7ce..39832b4 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 130e457..7e2b9fa 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 From 00185b5230f883966d872751431edcbfd1de5413 Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 07:52:43 -0400 Subject: [PATCH 06/17] [Trace] Template de-dup: rewrite base-language Error Handling sections, fix canonical tables Follow-up to the previous commit after review found three real gaps: 1. The 5 canonical per-language pages (javascript.md, python.md, go.md, php.md, java.md) still shared the generic "The SDK provides typed error(s)/exception(s) for different ... scenarios" intro sentence verbatim, and 3 of them (javascript, python, java) are themselves evidence pages (crawled/discovered but not indexed). Rewrote each intro to state the real, verified idiom for that language: Go's errors.As + embedded struct, PHP's readonly statusCode/errorCode (and the getCode()-returns-0 gotcha), Java's nested TurboDocxException.* classes with getCode()'s orDefault fallback, JS's code passthrough from the API response, Python's DEFAULT_CODE class attribute and Exception-subclass catch order. Sourced from packages/{go,php,java,js,py}-sdk directly (errors.ts, TurboDocxException.java, TurboDocxException.php, http.py). 2. deliverable-go.md and deliverable-php.md linked to go.md/php.md as the canonical Error Handling reference for classes those pages didn't actually document: go.md's table was missing ConflictError (it exists in http.go) and php.md's was missing AuthorizationException and ConflictException (both exist in packages/php-sdk/src/Exceptions/). Added the missing rows so the canonical pages actually contain what the product pages point to. 3. Removed unverified "most commonly" frequency language from the 10 deliverable-*/partner-* pages' Error Handling intros (added in the previous commit); rephrased as "returns/throws/raises X when Y" without a frequency claim. Also swept remaining em-dashes in the 5 base-language pages, now that they have real body edits (previously only go.md/java.md were fully swept, for their link fixes). --- docs/SDKs/deliverable-go.md | 2 +- docs/SDKs/deliverable-java.md | 2 +- docs/SDKs/deliverable-javascript.md | 2 +- docs/SDKs/deliverable-php.md | 2 +- docs/SDKs/deliverable-python.md | 2 +- docs/SDKs/go.md | 12 ++++--- docs/SDKs/java.md | 4 +-- docs/SDKs/javascript.md | 54 ++++++++++++++--------------- docs/SDKs/partner-go.md | 2 +- docs/SDKs/partner-java.md | 2 +- docs/SDKs/partner-javascript.md | 2 +- docs/SDKs/partner-php.md | 2 +- docs/SDKs/partner-python.md | 2 +- docs/SDKs/php.md | 41 ++++++++++++++-------- docs/SDKs/python.md | 30 ++++++++-------- 15 files changed, 89 insertions(+), 72 deletions(-) diff --git a/docs/SDKs/deliverable-go.md b/docs/SDKs/deliverable-go.md index 8ae6151..39102ca 100644 --- a/docs/SDKs/deliverable-go.md +++ b/docs/SDKs/deliverable-go.md @@ -422,7 +422,7 @@ if err != nil { ## Error Handling -`GenerateDeliverable` most commonly returns `NotFoundError` when `TemplateID` doesn't match a template in the org, and `ValidationError` when a `DeliverableVariable` is missing `Placeholder` or `MimeType`. Match on the concrete type with `errors.As`, same as every other Go SDK call: +`GenerateDeliverable` returns `NotFoundError` when `TemplateID` doesn't match a template in the org, and `ValidationError` when a `DeliverableVariable` is missing `Placeholder` or `MimeType`. Match on the concrete type with `errors.As`, same as every other Go SDK call: ### Handling Errors diff --git a/docs/SDKs/deliverable-java.md b/docs/SDKs/deliverable-java.md index 2c6bd24..75d4773 100644 --- a/docs/SDKs/deliverable-java.md +++ b/docs/SDKs/deliverable-java.md @@ -400,7 +400,7 @@ Files.write(Paths.get("report.pdf"), pdfData); ## Error Handling -`deliverable.generateDeliverable()` most commonly 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: +`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 diff --git a/docs/SDKs/deliverable-javascript.md b/docs/SDKs/deliverable-javascript.md index ee39b35..5adaf34 100644 --- a/docs/SDKs/deliverable-javascript.md +++ b/docs/SDKs/deliverable-javascript.md @@ -602,7 +602,7 @@ writeFileSync("report.pdf", Buffer.from(buffer)); ## Error Handling -`Deliverable.generateDeliverable()` most commonly rejects with `NotFoundError` when `templateId` doesn't match a template in the org, and `ValidationError` when an entry in `variables` is missing `placeholder` or `mimeType`. Both extend the base `TurboDocxError` class: +`Deliverable.generateDeliverable()` rejects with `NotFoundError` when `templateId` doesn't match a template in the org, and `ValidationError` when an entry in `variables` is missing `placeholder` or `mimeType`. Both extend the base `TurboDocxError` class: ### Handling Errors diff --git a/docs/SDKs/deliverable-php.md b/docs/SDKs/deliverable-php.md index 43eeec0..3a8f43a 100644 --- a/docs/SDKs/deliverable-php.md +++ b/docs/SDKs/deliverable-php.md @@ -361,7 +361,7 @@ echo $pdfFile; ## Error Handling -`Deliverable::generateDeliverable()` most commonly throws `NotFoundException` when `templateId` doesn't match a template in the org, and `ValidationException` when a variable in the `variables` array is missing `placeholder` or `mimeType`: +`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 `placeholder` or `mimeType`: ### Handling Errors diff --git a/docs/SDKs/deliverable-python.md b/docs/SDKs/deliverable-python.md index a1cef4c..c79a785 100644 --- a/docs/SDKs/deliverable-python.md +++ b/docs/SDKs/deliverable-python.md @@ -349,7 +349,7 @@ with open("report.pdf", "wb") as f: ## Error Handling -`Deliverable.generate_deliverable()` most commonly raises `NotFoundError` when `template_id` doesn't match a template in the org, and `ValidationError` when a variable dict is missing `placeholder` or `mimeType`. Both extend the base `TurboDocxError`: +`Deliverable.generate_deliverable()` raises `NotFoundError` when `template_id` doesn't match a template in the org, and `ValidationError` when a variable dict is missing `placeholder` or `mimeType`. Both extend the base `TurboDocxError`: ### Handling Errors diff --git a/docs/SDKs/go.md b/docs/SDKs/go.md index b877cc2..ccc752e 100644 --- a/docs/SDKs/go.md +++ b/docs/SDKs/go.md @@ -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` (`Message string`, `StatusCode int`, `Code string`) by value, so match the concrete type with `errors.As` rather than a type switch on the interface, and read the fields directly off the matched variable (`authErr.Message`, not a getter): ### 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, also returned by the `Error()` method | | `StatusCode` | `int` | HTTP status code | -| `Code` | `string` | Error code (if available) | +| `Code` | `string` | Machine-readable code; always populated, the API's code wins when present, otherwise the SDK fills in a per-status default | ### 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): diff --git a/docs/SDKs/java.md b/docs/SDKs/java.md index ace6d4f..42e8ec0 100644 --- a/docs/SDKs/java.md +++ b/docs/SDKs/java.md @@ -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; always populated, since each subclass falls back to its own default (e.g. `AuthenticationException`'s `AUTHENTICATION_ERROR`) whenever the API response carries none | ### Example diff --git a/docs/SDKs/javascript.md b/docs/SDKs/javascript.md index 32e30d5..54485c6 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)**. diff --git a/docs/SDKs/partner-go.md b/docs/SDKs/partner-go.md index 80cebe1..0a6a3a8 100644 --- a/docs/SDKs/partner-go.md +++ b/docs/SDKs/partner-go.md @@ -841,7 +841,7 @@ permissions := turbodocx.PartnerPermissions{ ## Error Handling -`partner.CreateOrganization` and the other partner calls most commonly return `AuthorizationError` when the partner API key lacks the scope for the route, since partner keys are scoped separately from organization keys: +`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" diff --git a/docs/SDKs/partner-java.md b/docs/SDKs/partner-java.md index a902aad..f8b6fd0 100644 --- a/docs/SDKs/partner-java.md +++ b/docs/SDKs/partner-java.md @@ -848,7 +848,7 @@ All seven keys are required whenever a permissions map is sent. Partial maps are ## Error Handling -Partner calls most commonly 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: +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; diff --git a/docs/SDKs/partner-javascript.md b/docs/SDKs/partner-javascript.md index fbd68bb..3ed325f 100644 --- a/docs/SDKs/partner-javascript.md +++ b/docs/SDKs/partner-javascript.md @@ -801,7 +801,7 @@ interface PartnerPermissions { ## Error Handling -`TurboPartner.createOrganization()` and the other partner calls most commonly reject with `AuthorizationError` when the partner API key lacks the scope for the route, since partner keys are scoped separately from organization keys: +`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 { diff --git a/docs/SDKs/partner-php.md b/docs/SDKs/partner-php.md index 8372b6a..5eea3ad 100644 --- a/docs/SDKs/partner-php.md +++ b/docs/SDKs/partner-php.md @@ -863,7 +863,7 @@ $permissions = new PartnerPermissions( ## Error Handling -`TurboPartner::createOrganization()` and the other partner calls most commonly throw `AuthenticationException` when the partner API key or partner ID is wrong, since partner credentials are validated separately from organization API keys: +`TurboPartner::createOrganization()` and the other partner calls throw `AuthenticationException` when the partner API key or partner ID is wrong, since partner credentials are validated separately from organization API keys: ```php use TurboDocx\Exceptions\AuthenticationException; diff --git a/docs/SDKs/partner-python.md b/docs/SDKs/partner-python.md index 07e87d3..6f5b51d 100644 --- a/docs/SDKs/partner-python.md +++ b/docs/SDKs/partner-python.md @@ -790,7 +790,7 @@ permissions = { ## Error Handling -`TurboPartner.create_organization()` and the other partner calls most commonly raise `AuthorizationError` when the partner API key lacks the scope for the route, since partner keys are scoped separately from organization keys: +`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 ( diff --git a/docs/SDKs/php.md b/docs/SDKs/php.md index 69ad930..146d77e 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 (if applicable), a public readonly int +- `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 1461c18..bd1e780 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 subclass sets its own `DEFAULT_CODE` class attribute, so `e.code` is always populated even when the API response itself carries none. ### 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` From 92ed97d2f2139b5a7ce25e60ea999f0f5d1e6809 Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 08:07:43 -0400 Subject: [PATCH 07/17] [Trace] Template de-dup: fix an overreaching claim in go.md's Error Handling intro The previous wording implied errors.As was needed specifically because TurboDocxError is embedded by value ("so match... rather than a type switch"), which isn't the right causal link and isn't accurate SDK guidance (a plain type switch would work fine on the unwrapped return values; errors.As is just the more defensive/robust choice against any future wrapping). Reworded to state two independently-true facts: by- value embedding promotes the fields for direct access, and the SDK's own example already uses errors.As. --- docs/SDKs/go.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/SDKs/go.md b/docs/SDKs/go.md index ccc752e..ebdc672 100644 --- a/docs/SDKs/go.md +++ b/docs/SDKs/go.md @@ -497,7 +497,7 @@ This differs from **Resend**: resend re-sends the original invitation email, whi ## Error Handling -Every typed error embeds `TurboDocxError` (`Message string`, `StatusCode int`, `Code string`) by value, so match the concrete type with `errors.As` rather than a type switch on the interface, and read the fields directly off the matched variable (`authErr.Message`, not a getter): +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 From 38be18da5afc0e361825b517625b57a5614ea503 Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 08:25:52 -0400 Subject: [PATCH 08/17] [Trace] Template de-dup: fix overreaching claims and a genuine Java bug Second review pass found more accuracy issues: - go.md/java.md/python.md's Code-field descriptions said the machine- readable code is "always populated". True only for the 7 named subclasses (each has a default). The bare base error returned for an unmapped HTTP status (e.g. an unexpected 5xx) can have an empty/null code, verified: Go's defaultErrorCode() returns "" in its default case, Java's HttpClient.java falls through to `new TurboDocxException(message, code, ...)` with no fallback, and Python's base TurboDocxError has DEFAULT_CODE = None. Qualified all three. - index.md's Java Error Handling tab imported `com.turbodocx.sdk.*` (wrong package; the SDK's actual package is `com.turbodocx`, no `.sdk`), used a response type SigningResult that doesn't exist, and called `turboSign.sendSignature(...)` on a bare variable instead of `client.turboSign().sendSignature(...)`. All three didn't match java.md's own (correct) examples. Fixed to match. - Five deliverable-*.md pages claimed ValidationError fires when a variable is missing "placeholder or mimeType". Checked RapidDocxBackend's actual generate-deliverable handler (DeliverableGenerationHandlers.ts): the Variable interface has `placeholder: string` (required) but `mimeType?: string` (optional). Dropped the incorrect mimeType half of the claim. --- docs/SDKs/deliverable-go.md | 2 +- docs/SDKs/deliverable-javascript.md | 2 +- docs/SDKs/deliverable-php.md | 2 +- docs/SDKs/deliverable-python.md | 2 +- docs/SDKs/go.md | 2 +- docs/SDKs/index.md | 7 +++---- docs/SDKs/java.md | 2 +- docs/SDKs/python.md | 2 +- 8 files changed, 10 insertions(+), 11 deletions(-) diff --git a/docs/SDKs/deliverable-go.md b/docs/SDKs/deliverable-go.md index 39102ca..5ac8813 100644 --- a/docs/SDKs/deliverable-go.md +++ b/docs/SDKs/deliverable-go.md @@ -422,7 +422,7 @@ if err != nil { ## Error Handling -`GenerateDeliverable` returns `NotFoundError` when `TemplateID` doesn't match a template in the org, and `ValidationError` when a `DeliverableVariable` is missing `Placeholder` or `MimeType`. Match on the concrete type with `errors.As`, same as every other Go SDK call: +`GenerateDeliverable` returns `NotFoundError` when `TemplateID` doesn't match a template in the org, and `ValidationError` when a `DeliverableVariable` is missing its required `Placeholder`. Match on the concrete type with `errors.As`, same as every other Go SDK call: ### Handling Errors diff --git a/docs/SDKs/deliverable-javascript.md b/docs/SDKs/deliverable-javascript.md index 5adaf34..3222040 100644 --- a/docs/SDKs/deliverable-javascript.md +++ b/docs/SDKs/deliverable-javascript.md @@ -602,7 +602,7 @@ writeFileSync("report.pdf", Buffer.from(buffer)); ## Error Handling -`Deliverable.generateDeliverable()` rejects with `NotFoundError` when `templateId` doesn't match a template in the org, and `ValidationError` when an entry in `variables` is missing `placeholder` or `mimeType`. Both extend the base `TurboDocxError` class: +`Deliverable.generateDeliverable()` rejects with `NotFoundError` when `templateId` doesn't match a template in the org, and `ValidationError` when an entry in `variables` is missing its required `placeholder`. Both extend the base `TurboDocxError` class: ### Handling Errors diff --git a/docs/SDKs/deliverable-php.md b/docs/SDKs/deliverable-php.md index 3a8f43a..3811f61 100644 --- a/docs/SDKs/deliverable-php.md +++ b/docs/SDKs/deliverable-php.md @@ -361,7 +361,7 @@ echo $pdfFile; ## Error Handling -`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 `placeholder` or `mimeType`: +`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 its required `placeholder`: ### Handling Errors diff --git a/docs/SDKs/deliverable-python.md b/docs/SDKs/deliverable-python.md index c79a785..9f1e48a 100644 --- a/docs/SDKs/deliverable-python.md +++ b/docs/SDKs/deliverable-python.md @@ -349,7 +349,7 @@ with open("report.pdf", "wb") as f: ## Error Handling -`Deliverable.generate_deliverable()` raises `NotFoundError` when `template_id` doesn't match a template in the org, and `ValidationError` when a variable dict is missing `placeholder` or `mimeType`. Both extend the base `TurboDocxError`: +`Deliverable.generate_deliverable()` raises `NotFoundError` when `template_id` doesn't match a template in the org, and `ValidationError` when a variable dict is missing its required `placeholder`. Both extend the base `TurboDocxError`: ### Handling Errors diff --git a/docs/SDKs/go.md b/docs/SDKs/go.md index ebdc672..65f41cf 100644 --- a/docs/SDKs/go.md +++ b/docs/SDKs/go.md @@ -518,7 +518,7 @@ Every typed error embeds `TurboDocxError` by value, which promotes its `Message | ------------ | -------- | ----------------------------- | | `Message` | `string` | Human-readable error message, also returned by the `Error()` method | | `StatusCode` | `int` | HTTP status code | -| `Code` | `string` | Machine-readable code; always populated, the API's code wins when present, otherwise the SDK fills in a per-status default | +| `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 diff --git a/docs/SDKs/index.md b/docs/SDKs/index.md index 2e11eee..cac400d 100644 --- a/docs/SDKs/index.md +++ b/docs/SDKs/index.md @@ -641,12 +641,11 @@ 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.*; try { - SigningResult result = turboSign.sendSignature(/* ... */); + SendSignatureResponse result = client.turboSign().sendSignature(/* ... */); } catch (AuthenticationException e) { System.err.println("Invalid API key: " + e.getMessage()); } catch (ValidationException e) { diff --git a/docs/SDKs/java.md b/docs/SDKs/java.md index 42e8ec0..4ce0bec 100644 --- a/docs/SDKs/java.md +++ b/docs/SDKs/java.md @@ -581,7 +581,7 @@ Every typed exception is a nested static class of `TurboDocxException` (`TurboDo | ----------------- | -------- | ---------------------------- | | `getMessage()` | `String` | Human-readable error message | | `getStatusCode()` | `int` | HTTP status code | -| `getCode()` | `String` | Machine-readable code; always populated, since each subclass falls back to its own default (e.g. `AuthenticationException`'s `AUTHENTICATION_ERROR`) whenever the API response carries none | +| `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 diff --git a/docs/SDKs/python.md b/docs/SDKs/python.md index bd1e780..084043b 100644 --- a/docs/SDKs/python.md +++ b/docs/SDKs/python.md @@ -522,7 +522,7 @@ print("Result:", json.dumps(result, indent=2)) ## Error Handling -Every error is a plain `Exception` subclass; catch the most specific one first, since `except TurboDocxError` also matches every subclass below it. Each subclass sets its own `DEFAULT_CODE` class attribute, so `e.code` is always populated even when the API response itself carries none. +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 From 6d4c5abac0b4680aac3d113c9333505215e92374 Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 08:38:24 -0400 Subject: [PATCH 09/17] [Trace] Template de-dup: fix broken code samples in index.md, unverified field claim Third review pass on index.md's Error Handling tabs (the same code block already touched for the PHP getCode()/Java package fixes): - Go tab: errors.As(err, &turboErr) targeted *sdk.TurboDocxError only. Go's errors.As requires the target's concrete type to match; the 6 named error types (ValidationError, AuthenticationError, ...) are distinct types from TurboDocxError even though they embed it, and none implement Unwrap/As, so this silently matched nothing except the generic unmapped-status case. The VALIDATION_ERROR branch shown was dead code. Fixed to match *sdk.ValidationError directly. - Python tab: printed e.message, but TurboDocxError.__init__ never sets self.message and Python 3's Exception doesn't have one either, so this raises AttributeError at runtime. Fixed to {e} (str(e)), matching python.md's own examples. - Java tab: missing the com.turbodocx.models.* import that SendSignatureResponse needs (follow-up to the package-name fix in the previous commit). - The "code is always populated" line above these tabs had the same gap already qualified on the language pages. Qualified it the same way. Also corrected the 5 deliverable-*.md pages' claim that ValidationError fires on a variable missing "placeholder or mimeType". Checked RapidDocxBackend's DeliverableGenerationHandlers.ts: the Variable interface has placeholder required, mimeType optional (the reverse of what was claimed), and I could not find where a missing placeholder is actually validated at the HTTP boundary (the handler doesn't appear to check it before using it). Rather than assert an unverified 400, all 5 now say "missing a required field" without naming one, matching deliverable-java.md's already-safe phrasing. --- docs/SDKs/deliverable-go.md | 2 +- docs/SDKs/deliverable-javascript.md | 2 +- docs/SDKs/deliverable-php.md | 2 +- docs/SDKs/deliverable-python.md | 2 +- docs/SDKs/index.md | 23 +++++++++++++---------- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/docs/SDKs/deliverable-go.md b/docs/SDKs/deliverable-go.md index 5ac8813..5128617 100644 --- a/docs/SDKs/deliverable-go.md +++ b/docs/SDKs/deliverable-go.md @@ -422,7 +422,7 @@ if err != nil { ## Error Handling -`GenerateDeliverable` returns `NotFoundError` when `TemplateID` doesn't match a template in the org, and `ValidationError` when a `DeliverableVariable` is missing its required `Placeholder`. Match on the concrete type with `errors.As`, same as every other Go SDK call: +`GenerateDeliverable` returns `NotFoundError` when `TemplateID` doesn't match a template in the org, and `ValidationError` when a `DeliverableVariable` is missing a required field. Match on the concrete type with `errors.As`, same as every other Go SDK call: ### Handling Errors diff --git a/docs/SDKs/deliverable-javascript.md b/docs/SDKs/deliverable-javascript.md index 3222040..11a8b5d 100644 --- a/docs/SDKs/deliverable-javascript.md +++ b/docs/SDKs/deliverable-javascript.md @@ -602,7 +602,7 @@ writeFileSync("report.pdf", Buffer.from(buffer)); ## Error Handling -`Deliverable.generateDeliverable()` rejects with `NotFoundError` when `templateId` doesn't match a template in the org, and `ValidationError` when an entry in `variables` is missing its required `placeholder`. Both extend the base `TurboDocxError` class: +`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 diff --git a/docs/SDKs/deliverable-php.md b/docs/SDKs/deliverable-php.md index 3811f61..9fa8eb7 100644 --- a/docs/SDKs/deliverable-php.md +++ b/docs/SDKs/deliverable-php.md @@ -361,7 +361,7 @@ echo $pdfFile; ## Error Handling -`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 its required `placeholder`: +`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 diff --git a/docs/SDKs/deliverable-python.md b/docs/SDKs/deliverable-python.md index 9f1e48a..e90ef97 100644 --- a/docs/SDKs/deliverable-python.md +++ b/docs/SDKs/deliverable-python.md @@ -349,7 +349,7 @@ with open("report.pdf", "wb") as f: ## Error Handling -`Deliverable.generate_deliverable()` raises `NotFoundError` when `template_id` doesn't match a template in the org, and `ValidationError` when a variable dict is missing its required `placeholder`. Both extend the base `TurboDocxError`: +`Deliverable.generate_deliverable()` raises `NotFoundError` when `template_id` doesn't match a template in the org, and `ValidationError` when a variable dict is missing a required field. Both extend the base `TurboDocxError`: ### Handling Errors diff --git a/docs/SDKs/index.md b/docs/SDKs/index.md index cac400d..8a020fd 100644 --- a/docs/SDKs/index.md +++ b/docs/SDKs/index.md @@ -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 @@ -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) } } ``` @@ -643,6 +644,7 @@ if err != nil { ```java import com.turbodocx.TurboDocxException; import com.turbodocx.TurboDocxException.*; +import com.turbodocx.models.*; try { SendSignatureResponse result = client.turboSign().sendSignature(/* ... */); @@ -674,9 +676,10 @@ 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 From 662cc0029da3f30281798d7cfd9e5d02322e8824 Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 11:42:20 -0400 Subject: [PATCH 10/17] [Trace] Accuracy fixes from SDK-main review --- docs/SDKs/deliverable-go.md | 2 +- docs/SDKs/deliverable-java.md | 6 ++-- docs/SDKs/deliverable-python.md | 2 +- docs/SDKs/go.md | 2 +- docs/SDKs/index.md | 12 ++++---- docs/SDKs/java.md | 50 ++------------------------------- docs/SDKs/javascript.md | 11 +++++--- docs/SDKs/partner-go.md | 6 +++- docs/SDKs/partner-java.md | 10 +++---- docs/SDKs/partner-php.md | 6 ++-- docs/SDKs/php.md | 4 +-- docs/SDKs/quote-java.md | 6 ++-- docs/SDKs/quote-javascript.md | 3 +- docs/SDKs/webhooks-java.md | 6 ++-- 14 files changed, 43 insertions(+), 83 deletions(-) diff --git a/docs/SDKs/deliverable-go.md b/docs/SDKs/deliverable-go.md index 5128617..ea99a08 100644 --- a/docs/SDKs/deliverable-go.md +++ b/docs/SDKs/deliverable-go.md @@ -422,7 +422,7 @@ if err != nil { ## Error Handling -`GenerateDeliverable` returns `NotFoundError` when `TemplateID` doesn't match a template in the org, and `ValidationError` when a `DeliverableVariable` is missing a required field. Match on the concrete type with `errors.As`, same as every other Go SDK call: +`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 diff --git a/docs/SDKs/deliverable-java.md b/docs/SDKs/deliverable-java.md index 75d4773..9a0bbf3 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' ``` diff --git a/docs/SDKs/deliverable-python.md b/docs/SDKs/deliverable-python.md index e90ef97..e21c413 100644 --- a/docs/SDKs/deliverable-python.md +++ b/docs/SDKs/deliverable-python.md @@ -349,7 +349,7 @@ with open("report.pdf", "wb") as f: ## Error Handling -`Deliverable.generate_deliverable()` raises `NotFoundError` when `template_id` doesn't match a template in the org, and `ValidationError` when a variable dict is missing a required field. Both extend the base `TurboDocxError`: +`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 diff --git a/docs/SDKs/go.md b/docs/SDKs/go.md index 65f41cf..82e06fe 100644 --- a/docs/SDKs/go.md +++ b/docs/SDKs/go.md @@ -516,7 +516,7 @@ Every typed error embeds `TurboDocxError` by value, which promotes its `Message | Property | Type | Description | | ------------ | -------- | ----------------------------- | -| `Message` | `string` | Human-readable error message, also returned by the `Error()` method | +| `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` | 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 | diff --git a/docs/SDKs/index.md b/docs/SDKs/index.md index 8a020fd..94238cd 100644 --- a/docs/SDKs/index.md +++ b/docs/SDKs/index.md @@ -111,19 +111,19 @@ 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) | +| **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** (no per-request sender field exists) | +| **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 @@ -688,8 +688,6 @@ 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. | diff --git a/docs/SDKs/java.md b/docs/SDKs/java.md index 4ce0bec..2db1cd7 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' ``` @@ -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: diff --git a/docs/SDKs/javascript.md b/docs/SDKs/javascript.md index 54485c6..7cacc92 100644 --- a/docs/SDKs/javascript.md +++ b/docs/SDKs/javascript.md @@ -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 0a6a3a8..2440a5d 100644 --- a/docs/SDKs/partner-go.md +++ b/docs/SDKs/partner-go.md @@ -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,7 +884,7 @@ if err != nil { } ``` -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`/`RateLimitError`/`NetworkError` types. +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). --- diff --git a/docs/SDKs/partner-java.md b/docs/SDKs/partner-java.md index f8b6fd0..3531996 100644 --- a/docs/SDKs/partner-java.md +++ b/docs/SDKs/partner-java.md @@ -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' ``` @@ -885,8 +885,8 @@ The full typed-exception table and HTTP status mapping is documented once in the 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. ::: --- diff --git a/docs/SDKs/partner-php.md b/docs/SDKs/partner-php.md index 5eea3ad..1c84249 100644 --- a/docs/SDKs/partner-php.md +++ b/docs/SDKs/partner-php.md @@ -863,7 +863,7 @@ $permissions = new PartnerPermissions( ## Error Handling -`TurboPartner::createOrganization()` and the other partner calls throw `AuthenticationException` when the partner API key or partner ID is wrong, since partner credentials are validated separately from organization API keys: +`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 diff --git a/docs/SDKs/php.md b/docs/SDKs/php.md index 146d77e..fb637aa 100644 --- a/docs/SDKs/php.md +++ b/docs/SDKs/php.md @@ -879,8 +879,8 @@ try { All exceptions extend `TurboDocxException` and include: - `getMessage()` - Human-readable error message -- `statusCode` - HTTP status code (if applicable), a public readonly int -- `errorCode` - Error code string (e.g., `'AUTHENTICATION_ERROR'`), a public readonly string +- `statusCode` - HTTP status code, a public readonly `?int` (null for `NetworkException`) +- `errorCode` - Error code string (e.g., `'AUTHENTICATION_ERROR'`), a public readonly `?string` --- diff --git a/docs/SDKs/quote-java.md b/docs/SDKs/quote-java.md index 38257b0..23757bb 100644 --- a/docs/SDKs/quote-java.md +++ b/docs/SDKs/quote-java.md @@ -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 a8ebdc2..b21e753 100644 --- a/docs/SDKs/quote-javascript.md +++ b/docs/SDKs/quote-javascript.md @@ -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/webhooks-java.md b/docs/SDKs/webhooks-java.md index 5488d56..a121c70 100644 --- a/docs/SDKs/webhooks-java.md +++ b/docs/SDKs/webhooks-java.md @@ -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") ``` From f2d438ea36bc2c60fa4334b88e4e66da3c184ecc Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 11:48:54 -0400 Subject: [PATCH 11/17] [Trace] Quote frontmatter descriptions containing ': ' (YAML parse errors broke the build) 11 SDK pages (agent-skills, quote-*, webhooks-*) had unquoted description values like 'TurboQuote Go SDK: ...'; YAML reads the second ': ' as a mapping and Docusaurus fails to build. Quote them. --- docs/SDKs/agent-skills.md | 2 +- docs/SDKs/quote-go.md | 2 +- docs/SDKs/quote-java.md | 2 +- docs/SDKs/quote-javascript.md | 2 +- docs/SDKs/quote-php.md | 2 +- docs/SDKs/quote-python.md | 2 +- docs/SDKs/webhooks-go.md | 2 +- docs/SDKs/webhooks-java.md | 2 +- docs/SDKs/webhooks-javascript.md | 2 +- docs/SDKs/webhooks-php.md | 2 +- docs/SDKs/webhooks-python.md | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/SDKs/agent-skills.md b/docs/SDKs/agent-skills.md index a336459..8b844f1 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: TurboDocx Agent Skill: install the SDK and html-to-docx in one prompt via Claude Code, Copilot, Cursor, or Codex 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/quote-go.md b/docs/SDKs/quote-go.md index 0bb177d..4560bd7 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: Go TurboQuote SDK: create and send quotes, manage line items, products, bundles, price books, companies, and contacts. +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 23757bb..7368912 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: Java TurboQuote SDK: create and send quotes, manage line items, products, bundles, and price books with full CPQ 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 diff --git a/docs/SDKs/quote-javascript.md b/docs/SDKs/quote-javascript.md index b21e753..20d5af2 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: JavaScript/TypeScript TurboQuote SDK: create quotes, manage line items, products, bundles, price books, companies, contacts. +description: "JavaScript/TypeScript TurboQuote SDK: create quotes, manage line items, products, bundles, price books, companies, contacts." keywords: - turboquote javascript - turboquote typescript diff --git a/docs/SDKs/quote-php.md b/docs/SDKs/quote-php.md index bf88961..162c824 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: PHP TurboQuote SDK: create, manage, and send quotes with line items, products, bundles, price books, companies, and contacts. +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 3a73770..9b298eb 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: Python TurboQuote SDK: create, manage, and send quotes with line items, products, bundles, and price books. 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 a9c6421..2e27bbb 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: Go TurboWebhooks SDK: subscribe to all seven TurboSign events, verify HMAC-SHA256 signatures, manage delivery history. +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 a121c70..2691ff9 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: Java TurboWebhooks SDK: subscribe to all seven TurboSign events, verify HMAC-SHA256 signatures, manage delivery history. +description: "Java TurboWebhooks SDK: subscribe to all seven TurboSign events, verify HMAC-SHA256 signatures, manage delivery history." keywords: - turbodocx webhooks - turbowebhooks java diff --git a/docs/SDKs/webhooks-javascript.md b/docs/SDKs/webhooks-javascript.md index 1e01d7a..f54ca6d 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: JavaScript/TypeScript TurboWebhooks SDK: subscribe to TurboSign events, verify HMAC-SHA256 signatures, manage delivery history. +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 39832b4..d728f72 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: PHP TurboWebhooks SDK: subscribe to all seven TurboSign events, verify HMAC-SHA256 signatures, manage delivery history. +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 7e2b9fa..a96c1d6 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: Python TurboWebhooks SDK: subscribe to all seven TurboSign events, verify HMAC-SHA256 signatures, manage delivery history. +description: "Python TurboWebhooks SDK: subscribe to all seven TurboSign events, verify HMAC-SHA256 signatures, manage delivery history." keywords: - turbodocx webhooks - turbowebhooks python From 20d527926a8d79d3abd5c765f45496bc750c7118 Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 06:58:27 -0400 Subject: [PATCH 12/17] [Trace] Meta length: shorten over-long docs meta descriptions Playbook task: meta-length-checker (Google truncates descriptions over ~160 chars). Rewrites 26 frontmatter descriptions to <= 155 chars, keeping the main keyword first. Frontmatter description lines only. docs/SDKs/* and docs/API/* are left to their own Trace PRs. Three embedded-signing pages that exist only on feature/turbosign-embedded-identity are not included here. --- docs/Integrations/ConnectWise PSA.md | 2 +- docs/Integrations/Fireflies.md | 2 +- docs/Integrations/Hubspot.md | 2 +- docs/Integrations/OneDrive and SharePoint.md | 2 +- docs/Integrations/SalesForce.md | 2 +- docs/Integrations/Teams.md | 2 +- docs/Integrations/Wrike/convert-to-pdf.md | 2 +- docs/Integrations/Wrike/document-packages.md | 2 +- docs/Integrations/Wrike/index.md | 2 +- docs/Integrations/Wrike/signature-workflow.md | 2 +- docs/Integrations/Zapier.md | 2 +- docs/Integrations/Zoom.md | 2 +- docs/Pipelines/Cloud Connectors.md | 2 +- docs/Pipelines/Creating an E-Signature Pipeline.md | 2 +- docs/Pipelines/Field Extraction.md | 2 +- docs/Pipelines/Field Placement.md | 2 +- docs/Pipelines/TurboDocx Pipelines.md | 2 +- docs/TurboDocx Templating/API Templates.md | 2 +- docs/TurboDocx Templating/How to Create a Document Template.md | 2 +- .../How to Create a Presentation Template.md | 2 +- docs/TurboQuote/Bulk Importing from a Spreadsheet.md | 2 +- docs/TurboQuote/Prepared By and Sender Identity.md | 2 +- docs/TurboSign/API Bulk Signatures.md | 2 +- docs/TurboSign/API Signatures.md | 2 +- docs/TurboSign/Email Deliverability and DKIM DMARC.md | 2 +- docs/TurboSign/Webhooks.md | 2 +- 26 files changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/Integrations/ConnectWise PSA.md b/docs/Integrations/ConnectWise PSA.md index 0b0d429..75fbc37 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 046ad4a..ba54e31 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 f228120..ed93dbb 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 fcd5aa1..3039cf3 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 1ad1705..327dc64 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 11159c8..520cc87 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: Transform Teams meetings into professional documents and presentations. Automate 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 a73f9aa..40e74f7 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 2cd3700..2a0ee40 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 e88ecd8..956fcb9 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 9851d60..1b77ad9 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 d29505b..64a4f7b 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 47b3b33..e8adaed 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 2edda73..325a991 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 696e2f8..8374cfa 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 05debc7..1e41d7a 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 f0447f0..98268fd 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 25e4d62..e414a63 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/TurboDocx Templating/API Templates.md b/docs/TurboDocx Templating/API Templates.md index 270f141..6147bf0 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 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 fc56d1d..6b456d3 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 63d1d34..fbcfca0 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/TurboQuote/Bulk Importing from a Spreadsheet.md b/docs/TurboQuote/Bulk Importing from a Spreadsheet.md index 27ba53f..03af209 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 85863b8..3b84ed8 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 ccdef36..c5b72cf 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 12eaa01..057dcc9 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 diff --git a/docs/TurboSign/Email Deliverability and DKIM DMARC.md b/docs/TurboSign/Email Deliverability and DKIM DMARC.md index 50e796a..e65f97f 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 a505c09..abfa3de 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 From a2c44aa1cc25ac05a22bc8b51d95345c356a536b Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 11:13:12 -0400 Subject: [PATCH 13/17] [Trace] Accuracy fixes from SDK-main review --- docs/Integrations/Teams.md | 2 +- docs/TurboSign/Webhooks.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Integrations/Teams.md b/docs/Integrations/Teams.md index 520cc87..dd5763b 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. Automate 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/TurboSign/Webhooks.md b/docs/TurboSign/Webhooks.md index abfa3de..e0e4ed8 100644 --- a/docs/TurboSign/Webhooks.md +++ b/docs/TurboSign/Webhooks.md @@ -1,7 +1,7 @@ --- title: TurboSign Webhooks sidebar_position: 6 -description: Configure TurboSign webhooks to receive notifications for signature events: sent, viewed, signed, completed, voided, and finalization failures. +description: "Configure TurboSign webhooks to receive notifications for signature events: sent, viewed, signed, completed, voided, and finalization failures." keywords: - webhook configuration - signature webhooks From b3ee6f10c399e41780ce76f6074a53aff1dc8c2c Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 06:52:35 -0400 Subject: [PATCH 14/17] [Trace] Broken links: fix dead links in the docs site Fixed broken internal links across docs site: - 25 Wrike integration links (converted relative paths to absolute /docs/ paths) - 6 Pipelines links (converted relative paths to absolute /docs/ paths) - 5 TurboDocx Templating links (converted relative paths, removed non-existent page links) - 3 TurboQuote links (converted relative paths) - 2 Dashboard links (converted relative paths) - 2 TurboSign links (converted relative/absolute paths) Reduced broken links from 56 to 19 (13 in SDK files owned by other PR, 2 commented-out images, 1 directory link in Webhooks). Excluded from fixes: - Links within docs/SDKs/ and docs/API/ (owned by SDK/API enrichment PRs) - Redirected external links that resolve to current URLs - Rate-limited or auth-gated external URLs (false positives) Test plan: - Before: 56 broken links found - After: 19 broken links (all in SDK files or commented content) - Internal link fixes: ./path -> /docs/path conversion - Removed broken links to non-existent pages, keeping text --- docs/Dashboard.md | 8 +++--- docs/Integrations/Wrike/ai-variable.md | 4 +-- docs/Integrations/Wrike/convert-to-pdf.md | 10 +++---- .../Wrike/document-generation-automation.md | 8 +++--- docs/Integrations/Wrike/document-packages.md | 10 +++---- docs/Integrations/Wrike/field-mapping.md | 2 +- docs/Integrations/Wrike/image-variable.md | 12 ++++---- docs/Integrations/Wrike/index.md | 28 +++++++++---------- .../Wrike/setting-up-automation.md | 6 ++-- docs/Integrations/Wrike/signature-anchors.md | 4 +-- .../Wrike/signature-automation.md | 12 ++++---- docs/Integrations/Wrike/signature-workflow.md | 22 +++++++-------- docs/Integrations/Wrike/slide-automation.md | 10 +++---- docs/Integrations/Wrike/table-variable.md | 12 ++++---- docs/Integrations/Wrike/troubleshooting.md | 2 +- docs/Pipelines/Cloud Connectors.md | 2 +- .../Creating an E-Signature Pipeline.md | 18 ++++++------ docs/Pipelines/Field Extraction.md | 4 +-- docs/Pipelines/Field Placement.md | 4 +-- docs/Pipelines/Pipeline Notifications.md | 8 +++--- docs/Pipelines/TurboDocx Pipelines.md | 2 +- docs/TurboDocx Templating/API Templates.md | 12 ++++---- docs/TurboDocx Templating/Brand Identity.md | 10 +++---- .../Template Troubleshooting.md | 14 +++++----- .../ai-variable-generation.md | 12 ++++---- .../Bulk Importing from a Spreadsheet.md | 4 +-- .../Prepared By and Sender Identity.md | 4 +-- docs/TurboSign/API Signatures.md | 2 +- 28 files changed, 123 insertions(+), 123 deletions(-) diff --git a/docs/Dashboard.md b/docs/Dashboard.md index fb3df5c..c06cc22 100644 --- a/docs/Dashboard.md +++ b/docs/Dashboard.md @@ -118,7 +118,7 @@ If **Send Reminder** is greyed out, that document is not waiting on a signer any ::: :::tip -**Send Reminder** works on its own, separately from any automatic reminder schedule you have set up. You can use it even if automatic reminders are switched off, and even if a document has already had all the automatic reminders it was allowed. For the full set of things you can do to a document after sending it, including resending the original email and voiding a document, see [Managing Your Signatures](./TurboSign/Managing%20Your%20Signatures.md). +**Send Reminder** works on its own, separately from any automatic reminder schedule you have set up. You can use it even if automatic reminders are switched off, and even if a document has already had all the automatic reminders it was allowed. For the full set of things you can do to a document after sending it, including resending the original email and voiding a document, see [Managing Your Signatures](/docs/TurboSign/Managing%20Your%20Signatures). ::: ## Step 6: See where your documents are being signed @@ -191,6 +191,6 @@ Scroll down and you will find four more panels. ## What's Next -- [Managing Your Signatures](./TurboSign/Managing%20Your%20Signatures.md): resend, remind, void and download signed documents. -- [Setting up TurboSign](./TurboSign/Setting%20up%20TurboSign.md): send your first document for signature. -- [How to Create a Deliverable](./TurboDocx%20Templating/How%20to%20Create%20a%20Deliverable.md): generate a document from one of your templates. +- [Managing Your Signatures](/docs/TurboSign/Managing%20Your%20Signatures): resend, remind, void and download signed documents. +- [Setting up TurboSign](/docs/TurboSign/Setting%20up%20TurboSign): send your first document for signature. +- [How to Create a Deliverable](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Deliverable): generate a document from one of your templates. diff --git a/docs/Integrations/Wrike/ai-variable.md b/docs/Integrations/Wrike/ai-variable.md index 5c82796..05dae66 100644 --- a/docs/Integrations/Wrike/ai-variable.md +++ b/docs/Integrations/Wrike/ai-variable.md @@ -19,7 +19,7 @@ AI variables let you define a prompt that TurboDocx uses to generate content aut ## Prerequisites - A template uploaded to TurboDocx with at least one variable -- A connected Wrike account (see [Setting Up a Wrike Automation](./setting-up-automation.md)) +- A connected Wrike account (see [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation))
@@ -73,7 +73,7 @@ When a Wrike automation triggers document generation, TurboDocx sends the AI pro
-This is different from [static field mapping](./field-mapping.md), which inserts exact Wrike field values with no interpretation. AI variables are ideal for generating summaries, descriptions, recommendations, and other narrative content that benefits from intelligent synthesis of project data. +This is different from [static field mapping](/docs/Integrations/Wrike/field-mapping), which inserts exact Wrike field values with no interpretation. AI variables are ideal for generating summaries, descriptions, recommendations, and other narrative content that benefits from intelligent synthesis of project data. :::tip You can mix AI variables and static field mappings in the same template. Use static mappings for structured data (dates, amounts, codes) and AI variables for narrative content (summaries, descriptions, recommendations). diff --git a/docs/Integrations/Wrike/convert-to-pdf.md b/docs/Integrations/Wrike/convert-to-pdf.md index 40e74f7..269089c 100644 --- a/docs/Integrations/Wrike/convert-to-pdf.md +++ b/docs/Integrations/Wrike/convert-to-pdf.md @@ -20,11 +20,11 @@ This action now fires not only when a **task** changes status, but also when a * ## Prerequisites -- A connected Wrike account (see [Setting Up a Wrike Automation](./setting-up-automation.md)) +- A connected Wrike account (see [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation)) - A Wrike workflow status you want to use as the trigger, and the folder or project you want to monitor :::tip Start with the base setup -This guide picks up at the automation's action step. If you have not connected Wrike or chosen a trigger status and folder yet, follow [Setting Up a Wrike Automation](./setting-up-automation.md) first. +This guide picks up at the automation's action step. If you have not connected Wrike or chosen a trigger status and folder yet, follow [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) first. :::
@@ -105,6 +105,6 @@ Update the source attachment and move the item back through the trigger status t ## Related -- [Setting Up a Wrike Automation](./setting-up-automation.md) -- [How to Set Up Document Packages (Combined PDF)](./document-packages.md) -- [Troubleshooting and FAQ](./troubleshooting.md) +- [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) +- [How to Set Up Document Packages (Combined PDF)](/docs/Integrations/Wrike/document-packages) +- [Troubleshooting and FAQ](/docs/Integrations/Wrike/troubleshooting) diff --git a/docs/Integrations/Wrike/document-generation-automation.md b/docs/Integrations/Wrike/document-generation-automation.md index 5213464..85887a1 100644 --- a/docs/Integrations/Wrike/document-generation-automation.md +++ b/docs/Integrations/Wrike/document-generation-automation.md @@ -11,7 +11,7 @@ keywords: # How to Setup Document Generation Automation -After [setting up your Wrike automation](./setting-up-automation.md) with a trigger status and folder, follow these steps to configure it to automatically generate documents from a template. +After [setting up your Wrike automation](/docs/Integrations/Wrike/setting-up-automation) with a trigger status and folder, follow these steps to configure it to automatically generate documents from a template.
@@ -87,7 +87,7 @@ Now that your automation is active, test it end-to-end: ## What's Next? -- **[How to Setup Static Field Mapping](./field-mapping.md)** to template variables for static data like revenue and dates -- **[How to Add Signature Anchors](./signature-anchors.md)** to your template for digital signing +- **[How to Setup Static Field Mapping](/docs/Integrations/Wrike/field-mapping)** to template variables for static data like revenue and dates +- **[How to Add Signature Anchors](/docs/Integrations/Wrike/signature-anchors)** to your template for digital signing - **Create multiple automations** for different project types, templates, or trigger statuses -- If something isn't working, see [Troubleshooting and FAQ](./troubleshooting.md) +- If something isn't working, see [Troubleshooting and FAQ](/docs/Integrations/Wrike/troubleshooting) diff --git a/docs/Integrations/Wrike/document-packages.md b/docs/Integrations/Wrike/document-packages.md index 2a0ee40..e1184f6 100644 --- a/docs/Integrations/Wrike/document-packages.md +++ b/docs/Integrations/Wrike/document-packages.md @@ -19,11 +19,11 @@ This is the **Create Document Package** automation action. Use it to roll loose ## Prerequisites -- A connected Wrike account (see [Setting Up a Wrike Automation](./setting-up-automation.md)) +- A connected Wrike account (see [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation)) - A Wrike workflow status you want to use as the trigger, and the folder or project you want to monitor :::tip Start with the base setup -This guide picks up at the automation's action step. If you have not connected Wrike or chosen a trigger status and folder yet, follow [Setting Up a Wrike Automation](./setting-up-automation.md) first. +This guide picks up at the automation's action step. If you have not connected Wrike or chosen a trigger status and folder yet, follow [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) first. :::
@@ -118,6 +118,6 @@ If the automation runs again on the same item, the new Document Package **replac ## Related -- [Setting Up a Wrike Automation](./setting-up-automation.md) -- [How to Convert Documents to PDF (Task, Project & Folder Triggers)](./convert-to-pdf.md) -- [Troubleshooting and FAQ](./troubleshooting.md) +- [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) +- [How to Convert Documents to PDF (Task, Project & Folder Triggers)](/docs/Integrations/Wrike/convert-to-pdf) +- [Troubleshooting and FAQ](/docs/Integrations/Wrike/troubleshooting) diff --git a/docs/Integrations/Wrike/field-mapping.md b/docs/Integrations/Wrike/field-mapping.md index b1fc2c4..dd9c0aa 100644 --- a/docs/Integrations/Wrike/field-mapping.md +++ b/docs/Integrations/Wrike/field-mapping.md @@ -18,7 +18,7 @@ Static field mapping lets you map Wrike custom fields directly to TurboDocx temp ## Prerequisites - A template uploaded to TurboDocx with at least one variable -- A connected Wrike account (see [Setting Up a Wrike Automation](./setting-up-automation.md)) +- A connected Wrike account (see [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation))
diff --git a/docs/Integrations/Wrike/image-variable.md b/docs/Integrations/Wrike/image-variable.md index caaf105..c2f76ca 100644 --- a/docs/Integrations/Wrike/image-variable.md +++ b/docs/Integrations/Wrike/image-variable.md @@ -14,12 +14,12 @@ keywords: A **Wrike Image** variable pulls image attachments from the triggering Wrike task or folder into your document. When the Wrike automation runs, TurboDocx attaches the matching images into that variable's place in the template. You can attach all images, or filter them by file name. -This is the image counterpart to the [Wrike Table](./table-variable.md) variable, and it reuses the same configuration flow. +This is the image counterpart to the [Wrike Table](/docs/Integrations/Wrike/table-variable) variable, and it reuses the same configuration flow. ## Prerequisites - A template uploaded to TurboDocx with at least one variable that is on its own line (a rich-text variable, so injected images have room to render) -- A connected Wrike account (see [Setting Up a Wrike Automation](./setting-up-automation.md)) +- A connected Wrike account (see [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation))
@@ -68,7 +68,7 @@ Images are injected by the Wrike automation when a document is generated, so a W ## Related -- [How to Add a Wrike Table](./table-variable.md) -- [How to Setup Static Field Mapping](./field-mapping.md) -- [Setting Up a Wrike Automation](./setting-up-automation.md) -- [Troubleshooting and FAQ](./troubleshooting.md) +- [How to Add a Wrike Table](/docs/Integrations/Wrike/table-variable) +- [How to Setup Static Field Mapping](/docs/Integrations/Wrike/field-mapping) +- [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) +- [Troubleshooting and FAQ](/docs/Integrations/Wrike/troubleshooting) diff --git a/docs/Integrations/Wrike/index.md b/docs/Integrations/Wrike/index.md index 956fcb9..8cab082 100644 --- a/docs/Integrations/Wrike/index.md +++ b/docs/Integrations/Wrike/index.md @@ -23,7 +23,7 @@ keywords: TurboDocx integrates with Wrike to automatically generate professional documents, proposals, and presentations directly from your project management data. When a task status changes in Wrike, TurboDocx can automatically create and attach documents to your projects. :::tip See It in Action -Want to see the full workflow before diving into setup? Check out the [End-to-End Example](./signature-workflow.md) — generate a proposal and send it for signature, all from Wrike. +Want to see the full workflow before diving into setup? Check out the [End-to-End Example](/docs/Integrations/Wrike/signature-workflow) — generate a proposal and send it for signature, all from Wrike. ::: ## What You Can Create @@ -47,7 +47,7 @@ You'll need: - Admin access to your Wrike workspace - Admin access to your TurboDocx organization -- A template ready in TurboDocx (see [How to Create a Template](../../TurboDocx%20Templating/How%20to%20Create%20a%20Template.md)) +- A template ready in TurboDocx (see [How to Create a Template](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Template)) - About 5 minutes
@@ -67,18 +67,18 @@ The Wrike integration uses a **status-triggered automation workflow** that you c | Guide | Description | |-------|-------------| -| [End-to-End Example](./signature-workflow.md) | Watch the full workflow in action — generate a proposal and send it for signature | -| [Setting Up a Wrike Automation](./setting-up-automation.md) | Connect Wrike and create an automation with a trigger status and folder | -| [How to Setup Document Generation Automation](./document-generation-automation.md) | Configure an automation to generate documents from a template | -| [How to Setup E-Signature Automation](./signature-automation.md) | Generate documents and send them for e-signature automatically | -| [How to Setup Static Field Mapping](./field-mapping.md) | Map Wrike custom fields (revenue, dates, etc.) directly to template variables | -| [How to Setup AI Variable Configuration](./ai-variable.md) | Configure AI-driven variables that generate content from prompts during automation | -| [How to Add a Wrike Table](./table-variable.md) | Turn a variable into a table of a folder or project's sub-items, with nesting and filtering | -| [How to Add a Wrike Image](./image-variable.md) | Pull image attachments from the triggering task or folder into your document | -| [How to Convert Documents to PDF](./convert-to-pdf.md) | Convert the first attachment to PDF when a task, project, or folder changes status, with in-place versioning | -| [How to Set Up Document Packages (Combined PDF)](./document-packages.md) | Merge every attachment on a task or project into one combined PDF and attach it back to Wrike | -| [How to Add Signature Anchors](./signature-anchors.md) | Configure signature anchor fields in your template for TurboSign | -| [Troubleshooting and FAQ](./troubleshooting.md) | Common issues, solutions, and frequently asked questions | +| [End-to-End Example](/docs/Integrations/Wrike/signature-workflow) | Watch the full workflow in action — generate a proposal and send it for signature | +| [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) | Connect Wrike and create an automation with a trigger status and folder | +| [How to Setup Document Generation Automation](/docs/Integrations/Wrike/document-generation-automation) | Configure an automation to generate documents from a template | +| [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation) | Generate documents and send them for e-signature automatically | +| [How to Setup Static Field Mapping](/docs/Integrations/Wrike/field-mapping) | Map Wrike custom fields (revenue, dates, etc.) directly to template variables | +| [How to Setup AI Variable Configuration](/docs/Integrations/Wrike/ai-variable) | Configure AI-driven variables that generate content from prompts during automation | +| [How to Add a Wrike Table](/docs/Integrations/Wrike/table-variable) | Turn a variable into a table of a folder or project's sub-items, with nesting and filtering | +| [How to Add a Wrike Image](/docs/Integrations/Wrike/image-variable) | Pull image attachments from the triggering task or folder into your document | +| [How to Convert Documents to PDF](/docs/Integrations/Wrike/convert-to-pdf) | Convert the first attachment to PDF when a task, project, or folder changes status, with in-place versioning | +| [How to Set Up Document Packages (Combined PDF)](/docs/Integrations/Wrike/document-packages) | Merge every attachment on a task or project into one combined PDF and attach it back to Wrike | +| [How to Add Signature Anchors](/docs/Integrations/Wrike/signature-anchors) | Configure signature anchor fields in your template for TurboSign | +| [Troubleshooting and FAQ](/docs/Integrations/Wrike/troubleshooting) | Common issues, solutions, and frequently asked questions |
diff --git a/docs/Integrations/Wrike/setting-up-automation.md b/docs/Integrations/Wrike/setting-up-automation.md index b46f706..fe3e2c9 100644 --- a/docs/Integrations/Wrike/setting-up-automation.md +++ b/docs/Integrations/Wrike/setting-up-automation.md @@ -20,7 +20,7 @@ This guide walks you through connecting your Wrike account to TurboDocx and crea Before starting, make sure you have: - A **Wrike API access token** (see [Get Your Wrike Access Token](#get-your-wrike-access-token) below) -- A **template** in TurboDocx ready for document generation (see [How to Create a Template](../../TurboDocx%20Templating/How%20to%20Create%20a%20Template.md)) +- A **template** in TurboDocx ready for document generation (see [How to Create a Template](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Template)) - The **Wrike folder permalink** for the folder you want to monitor
@@ -110,5 +110,5 @@ Click the **Next** button at the bottom-right corner of the setup modal to conti After completing the base automation setup above, choose which type of automation to configure: -- **[How to Setup Document Generation Automation](./document-generation-automation.md)** — automatically generate documents from a template when the trigger fires -- **[How to Setup E-Signature Automation](./signature-automation.md)** — generate documents and send them for digital signature via TurboSign +- **[How to Setup Document Generation Automation](/docs/Integrations/Wrike/document-generation-automation)** — automatically generate documents from a template when the trigger fires +- **[How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation)** — generate documents and send them for digital signature via TurboSign diff --git a/docs/Integrations/Wrike/signature-anchors.md b/docs/Integrations/Wrike/signature-anchors.md index 80ff7e1..d2562bd 100644 --- a/docs/Integrations/Wrike/signature-anchors.md +++ b/docs/Integrations/Wrike/signature-anchors.md @@ -17,7 +17,7 @@ Signature anchors are special template variables that tell TurboSign where to pl ## Prerequisites - A template uploaded to TurboDocx with signature variables (e.g., `{SalesSigner}`) -- An e-signature automation configured (see [How to Setup E-Signature Automation](./signature-automation.md)) +- An e-signature automation configured (see [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation))
@@ -68,5 +68,5 @@ Repeat steps 3–6 for each signature variable in your template (e.g., `{SalesSi ::: :::caution Anchor Names Must Match Your E-Signature Automation -The signature anchor variable names you configure here **must exactly match** the anchor tags in your [How to Setup E-Signature Automation](./signature-automation.md). For example, if you set up `{SalesSignerSignature}` as an anchor here, the anchor tag in your e-signature automation must also be `{SalesSignerSignature}`. If they don't match, TurboSign won't be able to place the signature fields. See [How to Setup E-Signature Automation](./signature-automation.md) for how to configure the anchor tags on the automation side. +The signature anchor variable names you configure here **must exactly match** the anchor tags in your [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation). For example, if you set up `{SalesSignerSignature}` as an anchor here, the anchor tag in your e-signature automation must also be `{SalesSignerSignature}`. If they don't match, TurboSign won't be able to place the signature fields. See [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation) for how to configure the anchor tags on the automation side. ::: diff --git a/docs/Integrations/Wrike/signature-automation.md b/docs/Integrations/Wrike/signature-automation.md index 6545c9b..1a85ead 100644 --- a/docs/Integrations/Wrike/signature-automation.md +++ b/docs/Integrations/Wrike/signature-automation.md @@ -12,7 +12,7 @@ keywords: # How to Setup E-Signature Automation -After [setting up your Wrike automation](./setting-up-automation.md) with a trigger status and folder, follow these steps to configure it to generate documents and automatically send them for e-signature. +After [setting up your Wrike automation](/docs/Integrations/Wrike/setting-up-automation) with a trigger status and folder, follow these steps to configure it to generate documents and automatically send them for e-signature.
@@ -117,7 +117,7 @@ Change the anchor tag to match the placeholder in your template (e.g., `{SalesSi ![Set Anchor Tag](/img/wrike-integration/SigAuto09-ChangeAnchorTag.jpeg) :::caution Anchor Tags Must Match Your Template -The anchor tag you set here **must exactly match** the corresponding variable in your document template. If they don't match, TurboSign won't be able to place the signature field. See [How to Add Signature Anchors](./signature-anchors.md) for how to configure these in your template. +The anchor tag you set here **must exactly match** the corresponding variable in your document template. If they don't match, TurboSign won't be able to place the signature field. See [How to Add Signature Anchors](/docs/Integrations/Wrike/signature-anchors) for how to configure these in your template. ::: ### Step 10: Map Additional Document Fields (Optional) @@ -178,7 +178,7 @@ In the **Wrike activity updates** section of the signature action step, you'll s | **Finalization failed** | The signed PDF could not be finalized (e.g. a signing error) | The document is **not** marked Completed | | **Voided** | The signature request is voided or cancelled | e.g. `Document voided` | -These rows map to the same signature lifecycle events surfaced by [TurboSign webhooks](../../TurboSign/Webhooks.md) — see that page if you also want these events pushed to your own endpoints. +These rows map to the same signature lifecycle events surfaced by [TurboSign webhooks](/docs/TurboSign/Webhooks) — see that page if you also want these events pushed to your own endpoints. :::info The Completed row The table also shows a **Completed** row, but it is not configured here — it reuses the post-signature status you set in **Step 12–13** above and posts automatically once all recipients have signed. Set the "all recipients signed" status there, not in this section. @@ -215,6 +215,6 @@ Click **Create Automation** to save and activate your e-signature automation wor ## What's Next? -- **[How to Add Signature Anchors](./signature-anchors.md)** to your template if you haven't already -- **[How to Setup Static Field Mapping](./field-mapping.md)** to template variables for static data -- If something isn't working, see [Troubleshooting and FAQ](./troubleshooting.md) +- **[How to Add Signature Anchors](/docs/Integrations/Wrike/signature-anchors)** to your template if you haven't already +- **[How to Setup Static Field Mapping](/docs/Integrations/Wrike/field-mapping)** to template variables for static data +- If something isn't working, see [Troubleshooting and FAQ](/docs/Integrations/Wrike/troubleshooting) diff --git a/docs/Integrations/Wrike/signature-workflow.md b/docs/Integrations/Wrike/signature-workflow.md index 1b77ad9..ce869b6 100644 --- a/docs/Integrations/Wrike/signature-workflow.md +++ b/docs/Integrations/Wrike/signature-workflow.md @@ -38,7 +38,7 @@ Navigate to the task you want to generate a document for. In this example, we're ## Step 2: Trigger Document Generation :::info How to set this up -See [How to Setup Document Generation Automation](./document-generation-automation.md) to configure the trigger status and template for your automation. +See [How to Setup Document Generation Automation](/docs/Integrations/Wrike/document-generation-automation) to configure the trigger status and template for your automation. ::: Change the task status to **"Generate Document"**. This is the trigger status configured in the TurboDocx automation — as soon as the status changes, TurboDocx picks it up. @@ -58,7 +58,7 @@ Within moments, the **TurboDocx Document Bot** generates the document and attach ## Step 4: Review the Generated Document :::info How to set this up -See [How to Setup Static Field Mapping](./field-mapping.md) to map Wrike custom fields to template variables, and [How to Setup AI Variable Configuration](./ai-variable.md) to configure AI-generated content. +See [How to Setup Static Field Mapping](/docs/Integrations/Wrike/field-mapping) to map Wrike custom fields to template variables, and [How to Setup AI Variable Configuration](/docs/Integrations/Wrike/ai-variable) to configure AI-generated content. ::: Click the attachment to open and review the proposal. Notice two things: @@ -84,7 +84,7 @@ In the TurboDocx template settings, each of these variables is marked as a **Wri ![Anchor configuration in template settings](/img/wrike-integration/EndToEnd06-AnchorConfig.jpeg) -For the full setup guide, see [How to Add Signature Anchors](./signature-anchors.md). +For the full setup guide, see [How to Add Signature Anchors](/docs/Integrations/Wrike/signature-anchors). @@ -101,7 +101,7 @@ In the e-signature automation configuration, each anchor tag is mapped to a spec ![Date and Full Name anchor fields](/img/wrike-integration/EndToEnd08-DateAnchorField.jpeg) -For the full setup guide, see [How to Setup E-Signature Automation](./signature-automation.md). +For the full setup guide, see [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation). @@ -112,7 +112,7 @@ The signing request is sent to the email address in the **"Customer email"** cus ![Customer email field in Wrike task](/img/wrike-integration/EndToEnd09-RecipientEmail.jpeg) -For details on mapping recipient fields, see [How to Setup E-Signature Automation](./signature-automation.md). +For details on mapping recipient fields, see [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation). @@ -125,7 +125,7 @@ Here's what it looks like once TurboSign places the interactive signature fields ## Step 6: Send for Signature :::info How to set this up -See [How to Setup E-Signature Automation](./signature-automation.md) to configure the signature trigger, recipients, and anchor tag mapping. +See [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation) to configure the signature trigger, recipients, and anchor tag mapping. ::: Back in Wrike, change the task status to **"Send for Signature"**. This triggers the TurboSign signing workflow. @@ -156,8 +156,8 @@ Ready to configure this workflow for your team? Follow these guides in order: | Step | Guide | What You'll Do | |------|-------|---------------| -| 1 | [Setting Up a Wrike Automation](./setting-up-automation.md) | Connect Wrike and create your first automation | -| 2 | [How to Setup Static Field Mapping](./field-mapping.md) | Map Wrike custom fields (revenue, dates) to template variables | -| 3 | [How to Setup AI Variable Configuration](./ai-variable.md) | Set up AI-generated content like project timelines | -| 4 | [How to Add Signature Anchors](./signature-anchors.md) | Mark template variables as signature anchor fields | -| 5 | [How to Setup E-Signature Automation](./signature-automation.md) | Configure recipients, anchor tags, and post-signature actions | +| 1 | [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) | Connect Wrike and create your first automation | +| 2 | [How to Setup Static Field Mapping](/docs/Integrations/Wrike/field-mapping) | Map Wrike custom fields (revenue, dates) to template variables | +| 3 | [How to Setup AI Variable Configuration](/docs/Integrations/Wrike/ai-variable) | Set up AI-generated content like project timelines | +| 4 | [How to Add Signature Anchors](/docs/Integrations/Wrike/signature-anchors) | Mark template variables as signature anchor fields | +| 5 | [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation) | Configure recipients, anchor tags, and post-signature actions | diff --git a/docs/Integrations/Wrike/slide-automation.md b/docs/Integrations/Wrike/slide-automation.md index abcb06f..2630d8d 100644 --- a/docs/Integrations/Wrike/slide-automation.md +++ b/docs/Integrations/Wrike/slide-automation.md @@ -21,17 +21,17 @@ keywords: So a two-slide template can produce a fifteen-slide deck, without anyone copying and pasting a slide per project. -This page covers the PowerPoint-specific setup. For the basics of connecting Wrike and creating an automation, start with [Setting Up a Wrike Automation](./setting-up-automation.md). +This page covers the PowerPoint-specific setup. For the basics of connecting Wrike and creating an automation, start with [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation). ## Prerequisites - A **PowerPoint (.pptx)** template uploaded to TurboDocx -- A connected Wrike account (see [Setting Up a Wrike Automation](./setting-up-automation.md)) +- A connected Wrike account (see [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation)) - A Wrike folder that contains the projects you want in the deck -- Variables on your template mapped to Wrike fields (see [Static Field Mapping](./field-mapping.md)) +- Variables on your template mapped to Wrike fields (see [Static Field Mapping](/docs/Integrations/Wrike/field-mapping)) :::note -Slide automation only applies to PowerPoint templates. Word templates use [document generation](./document-generation-automation.md) instead. +Slide automation only applies to PowerPoint templates. Word templates use [document generation](/docs/Integrations/Wrike/document-generation-automation) instead. :::
@@ -186,4 +186,4 @@ The **Table tag** doesn't match the table on the slide. Check the table's alt-te **The looping slide didn't repeat.** Check the slide is still marked as a **Looping slide** in Part 1, and that **Slide Automation** is switched on in Step 5. -For anything else, see [Wrike Integration Troubleshooting & FAQ](./troubleshooting.md). +For anything else, see [Wrike Integration Troubleshooting & FAQ](/docs/Integrations/Wrike/troubleshooting). diff --git a/docs/Integrations/Wrike/table-variable.md b/docs/Integrations/Wrike/table-variable.md index 227bcfd..611fc77 100644 --- a/docs/Integrations/Wrike/table-variable.md +++ b/docs/Integrations/Wrike/table-variable.md @@ -17,12 +17,12 @@ keywords: A **Wrike Table** variable turns a single template variable into a table. When the Wrike automation runs, TurboDocx fills that table with the triggering folder or project's **sub-items** (its tasks, and its subfolders or subprojects), one row each. You choose which Wrike fields become the columns, how the rows are laid out, whether nested sub-items are expanded, and an optional filter that limits which sub-items appear. -This is different from [Static Field Mapping](./field-mapping.md), which maps one Wrike field to one variable. A Wrike Table maps one variable to many rows. +This is different from [Static Field Mapping](/docs/Integrations/Wrike/field-mapping), which maps one Wrike field to one variable. A Wrike Table maps one variable to many rows. ## Prerequisites - A template uploaded to TurboDocx with at least one variable that is on its own line (a rich-text variable, so the generated table has room to render) -- A connected Wrike account (see [Setting Up a Wrike Automation](./setting-up-automation.md)) +- A connected Wrike account (see [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation))
@@ -141,7 +141,7 @@ The table is built by the Wrike automation when a document is generated, so a Wr ## Related -- [How to Add a Wrike Image](./image-variable.md) -- [How to Setup Static Field Mapping](./field-mapping.md) -- [Setting Up a Wrike Automation](./setting-up-automation.md) -- [Troubleshooting and FAQ](./troubleshooting.md) +- [How to Add a Wrike Image](/docs/Integrations/Wrike/image-variable) +- [How to Setup Static Field Mapping](/docs/Integrations/Wrike/field-mapping) +- [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) +- [Troubleshooting and FAQ](/docs/Integrations/Wrike/troubleshooting) diff --git a/docs/Integrations/Wrike/troubleshooting.md b/docs/Integrations/Wrike/troubleshooting.md index f538d2c..360d2e2 100644 --- a/docs/Integrations/Wrike/troubleshooting.md +++ b/docs/Integrations/Wrike/troubleshooting.md @@ -57,7 +57,7 @@ keywords: - Ensure `Seller email` and `Customer email` custom fields exist and are populated on the Wrike task - Verify the document template contains all required signature anchor fields - Check that TurboSign is configured in your organization -- See the [End-to-End Example](./signature-workflow.md) for full requirements +- See the [End-to-End Example](/docs/Integrations/Wrike/signature-workflow) for full requirements
diff --git a/docs/Pipelines/Cloud Connectors.md b/docs/Pipelines/Cloud Connectors.md index 325a991..4b80eaa 100644 --- a/docs/Pipelines/Cloud Connectors.md +++ b/docs/Pipelines/Cloud Connectors.md @@ -72,7 +72,7 @@ Reach for a Cloud connector when the signer for a document can't be determined f - The right recipient comes from an **internal API** or directory service. - Signer assignment depends on business logic that lives in **your own systems**. -For simpler cases, such as a single fixed signer or a signer whose email is printed on the document, you can use a static signer or an extracted field instead. See **[Creating an E-Signature Pipeline](./Creating%20an%20E-Signature%20Pipeline)** for those options. +For simpler cases, such as a single fixed signer or a signer whose email is printed on the document, you can use a static signer or an extracted field instead. See **[Creating an E-Signature Pipeline](/docs/Pipelines/Creating%20an%20E-Signature%20Pipeline)** for those options.
diff --git a/docs/Pipelines/Creating an E-Signature Pipeline.md b/docs/Pipelines/Creating an E-Signature Pipeline.md index 8374cfa..6a2714f 100644 --- a/docs/Pipelines/Creating an E-Signature Pipeline.md +++ b/docs/Pipelines/Creating an E-Signature Pipeline.md @@ -37,7 +37,7 @@ Pipelines are an **Enterprise** feature. If you don't see the option to create o You'll need: -- **SharePoint connected to TurboDocx *for Pipelines*.** Pipelines run unattended, so they use their own SharePoint connection. An administrator registers an Azure AD app in the Azure portal (app-only and delegated permissions, admin consent, and a client secret), then pastes its credentials into the **Connect SharePoint** dialog reached from the **Pipelines** settings gear. This is a one-time admin task, and you can't create a pipeline until it's done. If you're not an administrator, have IT complete the **[Connect SharePoint for Pipelines setup](./SharePoint%20Pipelines%20Troubleshooting%20and%20FAQ#setup-checklist)** first. (This is a *separate* connection from **[Configuring SharePoint or OneDrive](../Advanced%20Configuration/Configuring%20Sharepoint%20or%20OneDrive)**, which covers template import and export, not Pipelines.) +- **SharePoint connected to TurboDocx *for Pipelines*.** Pipelines run unattended, so they use their own SharePoint connection. An administrator registers an Azure AD app in the Azure portal (app-only and delegated permissions, admin consent, and a client secret), then pastes its credentials into the **Connect SharePoint** dialog reached from the **Pipelines** settings gear. This is a one-time admin task, and you can't create a pipeline until it's done. If you're not an administrator, have IT complete the **[Connect SharePoint for Pipelines setup](/docs/Pipelines/SharePoint%20Pipelines%20Troubleshooting%20and%20FAQ#setup-checklist)** first. (This is a *separate* connection from **[Configuring SharePoint or OneDrive](/docs/Advanced%20Configuration/Configuring%20Sharepoint%20or%20OneDrive)**, which covers template import and export, not Pipelines.) - A **SharePoint document library** to use as your intake folder. - A **representative sample PDF**, meaning a real example of the kind of document this pipeline will process. - The details of who should sign these documents. @@ -104,8 +104,8 @@ The Sent folder must be a different folder from the intake library. If they were This step has three sections, matching the wizard: **Route each Document**, **Also extract**, and **Signature Placement**. The first two are optional; signature placement is required. 1. **Route each Document (optional)**: send documents that match certain text to different destination folders. For example, route anything containing "West Region" to one folder and "East Region" to another, each with its own **Pick Folder**. Anything that matches no rule lands in the default destination folder you'll choose in Step 5. Turn on **Required, fail if nothing matches** only if a document that matches no rule should be treated as an error instead. -2. **Also extract (optional)**: pull additional values out of each PDF, such as a customer code, a date, an email, or an amount. Extracted values can drive filenames, signer lookup, and routing. See **[Field Extraction](./Field%20Extraction)** for the details and examples. -3. **Signature Placement (required)**: click **Place Fields** to open the placement tool, then pick a field type and click on the sample to drop signature, date, initial, and other fields. You must place **at least one signature field** before you can continue. TurboDocx pins each field to the same spot on every document the pipeline processes. See **[Field Placement](./Field%20Placement)** for all the field types and details. +2. **Also extract (optional)**: pull additional values out of each PDF, such as a customer code, a date, an email, or an amount. Extracted values can drive filenames, signer lookup, and routing. See **[Field Extraction](/docs/Pipelines/Field%20Extraction)** for the details and examples. +3. **Signature Placement (required)**: click **Place Fields** to open the placement tool, then pick a field type and click on the sample to drop signature, date, initial, and other fields. You must place **at least one signature field** before you can continue. TurboDocx pins each field to the same spot on every document the pipeline processes. See **[Field Placement](/docs/Pipelines/Field%20Placement)** for all the field types and details. ![The Extract & Route step, showing its Route each Document, Also extract, and Signature Placement sections](/img/creating-an-e-signature-pipeline/step3-extract-route.png) @@ -123,7 +123,7 @@ Tell the pipeline who should sign each document. Choose how the signer is resolv - **Static signer**: the same person signs every document that flows through this pipeline. - **An extracted field**: use a value the pipeline read from the document itself (for example, an email address found in the PDF) to determine the signer per document. -- **A Cloud connector (Enterprise)**: look the signer up in one of your own systems, such as an internal database or API. See **[Cloud Connectors](./Cloud%20Connectors)** for how this works. +- **A Cloud connector (Enterprise)**: look the signer up in one of your own systems, such as an internal database or API. See **[Cloud Connectors](/docs/Pipelines/Cloud%20Connectors)** for how this works. Then set the sender identity recipients will see on the signature email: @@ -161,7 +161,7 @@ The final step decides where finished documents go and lets you review everythin 2. **Filename pattern**: how each signed file is named. You can build the name from extracted values (for example, a customer code or date) so files are easy to find later. 3. **Audit-trail upload**: toggle on to file the signing audit trail (a separate PDF documenting the signing chain of custody) alongside each signed PDF. 4. **Deliver as a single ZIP file**: toggle on to bundle the signed PDF (and the audit trail, if enabled) into one `.zip` in the destination folder, instead of filing them as separate files. -5. **Notifications**: set who is emailed when a document is signed and delivered, and who is alerted when one fails. A failure recipient is required, so problems never go unnoticed. See **[Pipeline Notifications](./Pipeline%20Notifications)** for default recipients, per-store overrides (a "store" is one routing rule), and how to customize the completion email. +5. **Notifications**: set who is emailed when a document is signed and delivered, and who is alerted when one fails. A failure recipient is required, so problems never go unnoticed. See **[Pipeline Notifications](/docs/Pipelines/Pipeline%20Notifications)** for default recipients, per-store overrides (a "store" is one routing rule), and how to customize the completion email. 6. **Review and save**: confirm the source, extraction, signer, and destination settings, then save to activate the pipeline. ![The Destination step, showing the destination picker, the default destination folder, and the filename pattern builder](/img/creating-an-e-signature-pipeline/step5-destination-review.png) @@ -182,7 +182,7 @@ Once saved, the pipeline starts watching its intake library. From now on, every ## What's Next? -- **[Pipeline Notifications](./Pipeline%20Notifications)**: choose who is alerted on success and failure, and customize the completion email. -- **[Field Extraction](./Field%20Extraction)**: pull data out of each document with patterns. -- **[Field Placement](./Field%20Placement)**: position signature and form fields on the sample. -- **[Cloud Connectors](./Cloud%20Connectors)**: resolve signers from your own internal systems. +- **[Pipeline Notifications](/docs/Pipelines/Pipeline%20Notifications)**: choose who is alerted on success and failure, and customize the completion email. +- **[Field Extraction](/docs/Pipelines/Field%20Extraction)**: pull data out of each document with patterns. +- **[Field Placement](/docs/Pipelines/Field%20Placement)**: position signature and form fields on the sample. +- **[Cloud Connectors](/docs/Pipelines/Cloud%20Connectors)**: resolve signers from your own internal systems. diff --git a/docs/Pipelines/Field Extraction.md b/docs/Pipelines/Field Extraction.md index 1e41d7a..3ad9ace 100644 --- a/docs/Pipelines/Field Extraction.md +++ b/docs/Pipelines/Field Extraction.md @@ -97,5 +97,5 @@ A scanned, image-only PDF can still be signed by the pipeline. The *extraction-d ## What's Next? -- **[Field Placement](./Field%20Placement)**: position signature and form fields on the sample. -- **[Creating an E-Signature Pipeline](./Creating%20an%20E-Signature%20Pipeline)**: see where extraction fits in the wizard. +- **[Field Placement](/docs/Pipelines/Field%20Placement)**: position signature and form fields on the sample. +- **[Creating an E-Signature Pipeline](/docs/Pipelines/Creating%20an%20E-Signature%20Pipeline)**: see where extraction fits in the wizard. diff --git a/docs/Pipelines/Field Placement.md b/docs/Pipelines/Field Placement.md index 98268fd..76b1618 100644 --- a/docs/Pipelines/Field Placement.md +++ b/docs/Pipelines/Field Placement.md @@ -79,5 +79,5 @@ Because placement is relative to the page, the closer your sample matches your r ## What's Next? -- **[Field Extraction](./Field%20Extraction)**: pull data out of each document with patterns. -- **[Creating an E-Signature Pipeline](./Creating%20an%20E-Signature%20Pipeline)**: see the full wizard from start to finish. +- **[Field Extraction](/docs/Pipelines/Field%20Extraction)**: pull data out of each document with patterns. +- **[Creating an E-Signature Pipeline](/docs/Pipelines/Creating%20an%20E-Signature%20Pipeline)**: see the full wizard from start to finish. diff --git a/docs/Pipelines/Pipeline Notifications.md b/docs/Pipelines/Pipeline Notifications.md index 0f86edf..443e000 100644 --- a/docs/Pipelines/Pipeline Notifications.md +++ b/docs/Pipelines/Pipeline Notifications.md @@ -27,7 +27,7 @@ Pipelines are an **Enterprise** feature. If you don't see the option to create o
-You set **default notifications** on the **Destination** step (labeled **Deliver** in the wizard's progress rail), and **per-store overrides** on the **Extract & Route** step. If you haven't built a pipeline yet, start with **[Creating an E-Signature Pipeline](./Creating%20an%20E-Signature%20Pipeline)** and come back here to fine-tune the alerts. +You set **default notifications** on the **Destination** step (labeled **Deliver** in the wizard's progress rail), and **per-store overrides** on the **Extract & Route** step. If you haven't built a pipeline yet, start with **[Creating an E-Signature Pipeline](/docs/Pipelines/Creating%20an%20E-Signature%20Pipeline)** and come back here to fine-tune the alerts.
@@ -101,6 +101,6 @@ Per-store notifications are useful when different regions, branches, or departme ## What's Next? -- **[Creating an E-Signature Pipeline](./Creating%20an%20E-Signature%20Pipeline)**: build the pipeline these notifications belong to. -- **[Field Extraction](./Field%20Extraction)**: define the routing fields that create per-store rules. -- **[Cloud Connectors](./Cloud%20Connectors)**: resolve signers from your own internal systems. +- **[Creating an E-Signature Pipeline](/docs/Pipelines/Creating%20an%20E-Signature%20Pipeline)**: build the pipeline these notifications belong to. +- **[Field Extraction](/docs/Pipelines/Field%20Extraction)**: define the routing fields that create per-store rules. +- **[Cloud Connectors](/docs/Pipelines/Cloud%20Connectors)**: resolve signers from your own internal systems. diff --git a/docs/Pipelines/TurboDocx Pipelines.md b/docs/Pipelines/TurboDocx Pipelines.md index e414a63..4f14871 100644 --- a/docs/Pipelines/TurboDocx Pipelines.md +++ b/docs/Pipelines/TurboDocx Pipelines.md @@ -89,7 +89,7 @@ If your team is manually downloading, signing, and re-filing the same kind of do ## Get Started -Ready to set one up? See **[Creating an E-Signature Pipeline](./Creating%20an%20E-Signature%20Pipeline)** for the step-by-step walkthrough. +Ready to set one up? See **[Creating an E-Signature Pipeline](/docs/Pipelines/Creating%20an%20E-Signature%20Pipeline)** for the step-by-step walkthrough.
diff --git a/docs/TurboDocx Templating/API Templates.md b/docs/TurboDocx Templating/API Templates.md index 6147bf0..190483d 100644 --- a/docs/TurboDocx Templating/API Templates.md +++ b/docs/TurboDocx Templating/API Templates.md @@ -853,16 +853,16 @@ 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** (coming soon) +📖 **Bulk Document Generation** (coming soon) +📖 **Template Version Management** (coming soon) ### Related Documentation -- [Template Management Guide](/docs/Templates/template-management) +- **Template Management Guide** (coming soon) - [Variable Types and Formatting](/docs/API/Deliverable%20API#variable-object-structure) -- [API Authentication](/docs/API/turbodocx-api-documentation) -- [Integration Examples](/docs/Integrations) +- [API Authentication](/docs/API/Deliverable%20API) +- Integration Examples ## Support diff --git a/docs/TurboDocx Templating/Brand Identity.md b/docs/TurboDocx Templating/Brand Identity.md index 09a05a2..6a8599c 100644 --- a/docs/TurboDocx Templating/Brand Identity.md +++ b/docs/TurboDocx Templating/Brand Identity.md @@ -74,7 +74,7 @@ Brand Identity configuration includes: - **Real-time Preview**: See changes instantly as you configure :::info Key Difference -**Brand Identity** sets organization-wide styling standards, while **[Working with Fonts](./Working%20with%20Fonts.md)** covers embedding specific desktop fonts in individual templates. +**Brand Identity** sets organization-wide styling standards, while **[Working with Fonts](/docs/TurboDocx%20Templating/Working%20with%20Fonts)** covers embedding specific desktop fonts in individual templates. ::: ## Detailed Configuration (Optional) @@ -274,13 +274,13 @@ Now that your Brand Identity is configured, here's how to put it to work: ### Immediate Next Steps 1. **Test with existing templates** - Generate a document from an existing template to see your branding applied -2. **Create your first branded template** - Follow our [How to Create a Template](./How%20to%20Create%20a%20Template.md) guide +2. **Create your first branded template** - Follow our [How to Create a Template](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Template) guide 3. **Set up team access** - Ensure team members have appropriate permissions to use templates ### Building Your Document Workflow - **Templates**: Your brand settings automatically apply to all new and existing templates - **Deliverables**: Every generated document will use your brand identity consistently -- **Knowledge Base**: Combine with [knowledge base entries](./How%20to%20Create%20a%20Knowledgebase%20Entry.md) for fully automated, branded documents +- **Knowledge Base**: Combine with [knowledge base entries](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Knowledgebase%20Entry) for fully automated, branded documents ### Integration Opportunities - **Salesforce Integration**: Branded proposals generated directly from CRM data @@ -332,7 +332,7 @@ Start with 2-3 core templates (proposal, report, letter) to see immediate value, **Font Conflicts:** - TurboDocx by default uses the font found in the template -- For custom fonts, use [Working with Fonts](./Working%20with%20Fonts.md) embedding +- For custom fonts, use [Working with Fonts](/docs/TurboDocx%20Templating/Working%20with%20Fonts) embedding ## Getting Help @@ -343,7 +343,7 @@ If you encounter issues with Brand Identity configuration: 3. **Test with Sample Documents**: Generate test documents to verify settings 4. **Contact Support**: Provide specific details about configuration issues and document types -For technical font embedding questions, refer to [Working with Fonts](./Working%20with%20Fonts.md). +For technical font embedding questions, refer to [Working with Fonts](/docs/TurboDocx%20Templating/Working%20with%20Fonts). :::info Next Steps After configuring your Brand Identity, create new templates or update existing ones to see your branding applied consistently across all generated documents. diff --git a/docs/TurboDocx Templating/Template Troubleshooting.md b/docs/TurboDocx Templating/Template Troubleshooting.md index 0e9c957..1affe95 100644 --- a/docs/TurboDocx Templating/Template Troubleshooting.md +++ b/docs/TurboDocx Templating/Template Troubleshooting.md @@ -216,10 +216,10 @@ Turn on ¶ symbols to see hidden formatting issues Only PNG and JPEG can go into a deliverable — convert SVG, GIF, WebP, BMP, TIFF, HEIC, AVIF and ICO first ### 5. For Presentation Templates -Use invisible rectangle shapes, not text boxes → [See presentation setup guide](./How%20to%20Create%20a%20Presentation%20Template) +Use invisible rectangle shapes, not text boxes → [See presentation setup guide](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Presentation%20Template) ### 6. Test Your Template -Create a simple deliverable to verify everything works → [Learn how to create deliverables](./How%20to%20Create%20a%20Deliverable) +Create a simple deliverable to verify everything works → [Learn how to create deliverables](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Deliverable)
:::tip Advanced Troubleshooting & Best Practices @@ -230,9 +230,9 @@ Create a simple deliverable to verify everything works → [Learn how to create - **For presentations:** Ensure shapes are truly invisible (no fill, no outline) **Best practices for success:** -- **Test your template** by creating a deliverable before finalizing → [See how](./How%20to%20Create%20a%20Deliverable) +- **Test your template** by creating a deliverable before finalizing → [See how](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Deliverable) - **Keep variable names descriptive** but concise -- **Use consistent formatting** across all templates → [Document templates](./How%20to%20Create%20a%20Document%20Template) | [Presentation templates](./How%20to%20Create%20a%20Presentation%20Template) +- **Use consistent formatting** across all templates → [Document templates](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Document%20Template) | [Presentation templates](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Presentation%20Template) ::: @@ -240,9 +240,9 @@ Create a simple deliverable to verify everything works → [Learn how to create Still stuck? We're here to help! Check out our comprehensive guides: -- [📄 Document Templates](./How%20to%20Create%20a%20Document%20Template) - Learn to create Word/Google Doc templates -- [📊 Presentation Templates](./How%20to%20Create%20a%20Presentation%20Template) - Learn to create PowerPoint templates -- [🎯 Create Deliverables](./How%20to%20Create%20a%20Deliverable) - Learn to generate documents from templates +- [📄 Document Templates](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Document%20Template) - Learn to create Word/Google Doc templates +- [📊 Presentation Templates](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Presentation%20Template) - Learn to create PowerPoint templates +- [🎯 Create Deliverables](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Deliverable) - Learn to generate documents from templates - [📚 Full Documentation](https://docs.turbodocx.com) - Complete TurboDocx documentation If you need additional help, don't hesitate to reach out to our support team. diff --git a/docs/TurboDocx Templating/ai-variable-generation.md b/docs/TurboDocx Templating/ai-variable-generation.md index a91d71f..9d7dfec 100644 --- a/docs/TurboDocx Templating/ai-variable-generation.md +++ b/docs/TurboDocx Templating/ai-variable-generation.md @@ -629,16 +629,16 @@ 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)** -📖 **[API Authentication →](/docs/API/turbodocx-api-documentation)** +📖 **Webhook Integration** (coming soon) +📖 **Bulk Processing** (coming soon) +📖 **[API Authentication →](/docs/API/Deliverable%20API)** ### Related Documentation -- [Template Management Guide](/docs/Templates/template-management) +- **Template Management Guide** (coming soon) - [Variable Types and Formatting](/docs/API/Deliverable%20API#variable-object-structure) -- [Integration Examples](/docs/Integrations) -- [Best Practices Guide](/docs/Templates/best-practices) +- Integration Examples +- **Best Practices Guide** (coming soon) ## Support diff --git a/docs/TurboQuote/Bulk Importing from a Spreadsheet.md b/docs/TurboQuote/Bulk Importing from a Spreadsheet.md index 03af209..9b4d95a 100644 --- a/docs/TurboQuote/Bulk Importing from a Spreadsheet.md +++ b/docs/TurboQuote/Bulk Importing from a Spreadsheet.md @@ -284,5 +284,5 @@ Import your **products first**, then reference them by SKU in your bundle and pr ## Related -- [Adding a New Product](./Adding%20a%20New%20Product.md) -- [Creating a New Quote](./Creating%20a%20New%20Quote.md) +- [Adding a New Product](/docs/TurboQuote/Adding%20a%20New%20Product) +- [Creating a New Quote](/docs/TurboQuote/Creating%20a%20New%20Quote) diff --git a/docs/TurboQuote/Prepared By and Sender Identity.md b/docs/TurboQuote/Prepared By and Sender Identity.md index 3b84ed8..b734fda 100644 --- a/docs/TurboQuote/Prepared By and Sender Identity.md +++ b/docs/TurboQuote/Prepared By and Sender Identity.md @@ -44,7 +44,7 @@ for the step-by-step walkthrough. ## Quotes created through the API, SDKs, or n8n When a quote is created by an **API key** — whether directly via the API, through one of the -[SDKs](../SDKs/index.md), or from an n8n workflow — there is an important difference: **an API key +[SDKs](/docs/SDKs), or from an n8n workflow — there is an important difference: **an API key has no mailbox of its own.** - The **"Prepared by" name** for an API-created quote resolves to the **name of the API key** @@ -110,7 +110,7 @@ returned as a **`preparedBy`** object alongside the quote: ``` Each SDK's `getQuote` folds `preparedBy` onto the returned quote for you (see the -[SDK guides](../SDKs/index.md)). Both fields are optional — `email` may be absent for an +[SDK guides](/docs/SDKs)). Both fields are optional — `email` may be absent for an API-created quote whose template has no sender email — so render a placeholder for a missing value. :::caution `preparedBy` is only on the single-quote fetch diff --git a/docs/TurboSign/API Signatures.md b/docs/TurboSign/API Signatures.md index 057dcc9..4a45773 100644 --- a/docs/TurboSign/API Signatures.md +++ b/docs/TurboSign/API Signatures.md @@ -1844,7 +1844,7 @@ 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) +- Integration Examples ## Support From 781a31b7dd1b28cdd5bb05ff0723cc17b7b26068 Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 07:04:27 -0400 Subject: [PATCH 15/17] [Trace] Broken links: revert false positives, fix real dead links The broken-link checker resolved Docusaurus file-relative links (./setting-up-automation.md, ../../TurboSign/Webhooks.md) against the site root instead of the source file's directory, so it flagged many working links as broken. This reverts those 25 files back to their original relative links, which resolve correctly on the live site. It also removes the '(coming soon)' text the previous commit added for genuinely dead links, since that publicly promises features that may not exist (one of them, Webhook Integration, already has a real page). The three files with real dead links now either point to the correct existing page or have the dead bullet removed: - Webhook Integration / Webhook Configuration -> /docs/TurboSign/Webhooks - Bulk Document Generation / Bulk Processing -> removed (no matching page) - Template Version Management -> removed (no matching page) - Template Management Guide -> removed (no matching page) - Integration Examples -> removed (/docs/Integrations 404s live; no index page exists for it) - API Authentication -> reverted to /docs/API/turbodocx-api-documentation (the original target, confirmed live 200; the previous commit had pointed it at /docs/API/Deliverable%20API instead) --- docs/Dashboard.md | 8 +++--- docs/Integrations/Wrike/ai-variable.md | 4 +-- docs/Integrations/Wrike/convert-to-pdf.md | 10 +++---- .../Wrike/document-generation-automation.md | 8 +++--- docs/Integrations/Wrike/document-packages.md | 10 +++---- docs/Integrations/Wrike/field-mapping.md | 2 +- docs/Integrations/Wrike/image-variable.md | 12 ++++---- docs/Integrations/Wrike/index.md | 28 +++++++++---------- .../Wrike/setting-up-automation.md | 6 ++-- docs/Integrations/Wrike/signature-anchors.md | 4 +-- .../Wrike/signature-automation.md | 12 ++++---- docs/Integrations/Wrike/signature-workflow.md | 22 +++++++-------- docs/Integrations/Wrike/slide-automation.md | 10 +++---- docs/Integrations/Wrike/table-variable.md | 12 ++++---- docs/Integrations/Wrike/troubleshooting.md | 2 +- docs/Pipelines/Cloud Connectors.md | 2 +- .../Creating an E-Signature Pipeline.md | 18 ++++++------ docs/Pipelines/Field Extraction.md | 4 +-- docs/Pipelines/Field Placement.md | 4 +-- docs/Pipelines/Pipeline Notifications.md | 8 +++--- docs/Pipelines/TurboDocx Pipelines.md | 2 +- docs/TurboDocx Templating/API Templates.md | 8 ++---- docs/TurboDocx Templating/Brand Identity.md | 10 +++---- .../Template Troubleshooting.md | 14 +++++----- .../ai-variable-generation.md | 8 ++---- .../Bulk Importing from a Spreadsheet.md | 4 +-- .../Prepared By and Sender Identity.md | 4 +-- docs/TurboSign/API Signatures.md | 1 - 28 files changed, 114 insertions(+), 123 deletions(-) diff --git a/docs/Dashboard.md b/docs/Dashboard.md index c06cc22..fb3df5c 100644 --- a/docs/Dashboard.md +++ b/docs/Dashboard.md @@ -118,7 +118,7 @@ If **Send Reminder** is greyed out, that document is not waiting on a signer any ::: :::tip -**Send Reminder** works on its own, separately from any automatic reminder schedule you have set up. You can use it even if automatic reminders are switched off, and even if a document has already had all the automatic reminders it was allowed. For the full set of things you can do to a document after sending it, including resending the original email and voiding a document, see [Managing Your Signatures](/docs/TurboSign/Managing%20Your%20Signatures). +**Send Reminder** works on its own, separately from any automatic reminder schedule you have set up. You can use it even if automatic reminders are switched off, and even if a document has already had all the automatic reminders it was allowed. For the full set of things you can do to a document after sending it, including resending the original email and voiding a document, see [Managing Your Signatures](./TurboSign/Managing%20Your%20Signatures.md). ::: ## Step 6: See where your documents are being signed @@ -191,6 +191,6 @@ Scroll down and you will find four more panels. ## What's Next -- [Managing Your Signatures](/docs/TurboSign/Managing%20Your%20Signatures): resend, remind, void and download signed documents. -- [Setting up TurboSign](/docs/TurboSign/Setting%20up%20TurboSign): send your first document for signature. -- [How to Create a Deliverable](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Deliverable): generate a document from one of your templates. +- [Managing Your Signatures](./TurboSign/Managing%20Your%20Signatures.md): resend, remind, void and download signed documents. +- [Setting up TurboSign](./TurboSign/Setting%20up%20TurboSign.md): send your first document for signature. +- [How to Create a Deliverable](./TurboDocx%20Templating/How%20to%20Create%20a%20Deliverable.md): generate a document from one of your templates. diff --git a/docs/Integrations/Wrike/ai-variable.md b/docs/Integrations/Wrike/ai-variable.md index 05dae66..5c82796 100644 --- a/docs/Integrations/Wrike/ai-variable.md +++ b/docs/Integrations/Wrike/ai-variable.md @@ -19,7 +19,7 @@ AI variables let you define a prompt that TurboDocx uses to generate content aut ## Prerequisites - A template uploaded to TurboDocx with at least one variable -- A connected Wrike account (see [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation)) +- A connected Wrike account (see [Setting Up a Wrike Automation](./setting-up-automation.md))
@@ -73,7 +73,7 @@ When a Wrike automation triggers document generation, TurboDocx sends the AI pro
-This is different from [static field mapping](/docs/Integrations/Wrike/field-mapping), which inserts exact Wrike field values with no interpretation. AI variables are ideal for generating summaries, descriptions, recommendations, and other narrative content that benefits from intelligent synthesis of project data. +This is different from [static field mapping](./field-mapping.md), which inserts exact Wrike field values with no interpretation. AI variables are ideal for generating summaries, descriptions, recommendations, and other narrative content that benefits from intelligent synthesis of project data. :::tip You can mix AI variables and static field mappings in the same template. Use static mappings for structured data (dates, amounts, codes) and AI variables for narrative content (summaries, descriptions, recommendations). diff --git a/docs/Integrations/Wrike/convert-to-pdf.md b/docs/Integrations/Wrike/convert-to-pdf.md index 269089c..40e74f7 100644 --- a/docs/Integrations/Wrike/convert-to-pdf.md +++ b/docs/Integrations/Wrike/convert-to-pdf.md @@ -20,11 +20,11 @@ This action now fires not only when a **task** changes status, but also when a * ## Prerequisites -- A connected Wrike account (see [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation)) +- A connected Wrike account (see [Setting Up a Wrike Automation](./setting-up-automation.md)) - A Wrike workflow status you want to use as the trigger, and the folder or project you want to monitor :::tip Start with the base setup -This guide picks up at the automation's action step. If you have not connected Wrike or chosen a trigger status and folder yet, follow [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) first. +This guide picks up at the automation's action step. If you have not connected Wrike or chosen a trigger status and folder yet, follow [Setting Up a Wrike Automation](./setting-up-automation.md) first. :::
@@ -105,6 +105,6 @@ Update the source attachment and move the item back through the trigger status t ## Related -- [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) -- [How to Set Up Document Packages (Combined PDF)](/docs/Integrations/Wrike/document-packages) -- [Troubleshooting and FAQ](/docs/Integrations/Wrike/troubleshooting) +- [Setting Up a Wrike Automation](./setting-up-automation.md) +- [How to Set Up Document Packages (Combined PDF)](./document-packages.md) +- [Troubleshooting and FAQ](./troubleshooting.md) diff --git a/docs/Integrations/Wrike/document-generation-automation.md b/docs/Integrations/Wrike/document-generation-automation.md index 85887a1..5213464 100644 --- a/docs/Integrations/Wrike/document-generation-automation.md +++ b/docs/Integrations/Wrike/document-generation-automation.md @@ -11,7 +11,7 @@ keywords: # How to Setup Document Generation Automation -After [setting up your Wrike automation](/docs/Integrations/Wrike/setting-up-automation) with a trigger status and folder, follow these steps to configure it to automatically generate documents from a template. +After [setting up your Wrike automation](./setting-up-automation.md) with a trigger status and folder, follow these steps to configure it to automatically generate documents from a template.
@@ -87,7 +87,7 @@ Now that your automation is active, test it end-to-end: ## What's Next? -- **[How to Setup Static Field Mapping](/docs/Integrations/Wrike/field-mapping)** to template variables for static data like revenue and dates -- **[How to Add Signature Anchors](/docs/Integrations/Wrike/signature-anchors)** to your template for digital signing +- **[How to Setup Static Field Mapping](./field-mapping.md)** to template variables for static data like revenue and dates +- **[How to Add Signature Anchors](./signature-anchors.md)** to your template for digital signing - **Create multiple automations** for different project types, templates, or trigger statuses -- If something isn't working, see [Troubleshooting and FAQ](/docs/Integrations/Wrike/troubleshooting) +- If something isn't working, see [Troubleshooting and FAQ](./troubleshooting.md) diff --git a/docs/Integrations/Wrike/document-packages.md b/docs/Integrations/Wrike/document-packages.md index e1184f6..2a0ee40 100644 --- a/docs/Integrations/Wrike/document-packages.md +++ b/docs/Integrations/Wrike/document-packages.md @@ -19,11 +19,11 @@ This is the **Create Document Package** automation action. Use it to roll loose ## Prerequisites -- A connected Wrike account (see [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation)) +- A connected Wrike account (see [Setting Up a Wrike Automation](./setting-up-automation.md)) - A Wrike workflow status you want to use as the trigger, and the folder or project you want to monitor :::tip Start with the base setup -This guide picks up at the automation's action step. If you have not connected Wrike or chosen a trigger status and folder yet, follow [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) first. +This guide picks up at the automation's action step. If you have not connected Wrike or chosen a trigger status and folder yet, follow [Setting Up a Wrike Automation](./setting-up-automation.md) first. :::
@@ -118,6 +118,6 @@ If the automation runs again on the same item, the new Document Package **replac ## Related -- [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) -- [How to Convert Documents to PDF (Task, Project & Folder Triggers)](/docs/Integrations/Wrike/convert-to-pdf) -- [Troubleshooting and FAQ](/docs/Integrations/Wrike/troubleshooting) +- [Setting Up a Wrike Automation](./setting-up-automation.md) +- [How to Convert Documents to PDF (Task, Project & Folder Triggers)](./convert-to-pdf.md) +- [Troubleshooting and FAQ](./troubleshooting.md) diff --git a/docs/Integrations/Wrike/field-mapping.md b/docs/Integrations/Wrike/field-mapping.md index dd9c0aa..b1fc2c4 100644 --- a/docs/Integrations/Wrike/field-mapping.md +++ b/docs/Integrations/Wrike/field-mapping.md @@ -18,7 +18,7 @@ Static field mapping lets you map Wrike custom fields directly to TurboDocx temp ## Prerequisites - A template uploaded to TurboDocx with at least one variable -- A connected Wrike account (see [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation)) +- A connected Wrike account (see [Setting Up a Wrike Automation](./setting-up-automation.md))
diff --git a/docs/Integrations/Wrike/image-variable.md b/docs/Integrations/Wrike/image-variable.md index c2f76ca..caaf105 100644 --- a/docs/Integrations/Wrike/image-variable.md +++ b/docs/Integrations/Wrike/image-variable.md @@ -14,12 +14,12 @@ keywords: A **Wrike Image** variable pulls image attachments from the triggering Wrike task or folder into your document. When the Wrike automation runs, TurboDocx attaches the matching images into that variable's place in the template. You can attach all images, or filter them by file name. -This is the image counterpart to the [Wrike Table](/docs/Integrations/Wrike/table-variable) variable, and it reuses the same configuration flow. +This is the image counterpart to the [Wrike Table](./table-variable.md) variable, and it reuses the same configuration flow. ## Prerequisites - A template uploaded to TurboDocx with at least one variable that is on its own line (a rich-text variable, so injected images have room to render) -- A connected Wrike account (see [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation)) +- A connected Wrike account (see [Setting Up a Wrike Automation](./setting-up-automation.md))
@@ -68,7 +68,7 @@ Images are injected by the Wrike automation when a document is generated, so a W ## Related -- [How to Add a Wrike Table](/docs/Integrations/Wrike/table-variable) -- [How to Setup Static Field Mapping](/docs/Integrations/Wrike/field-mapping) -- [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) -- [Troubleshooting and FAQ](/docs/Integrations/Wrike/troubleshooting) +- [How to Add a Wrike Table](./table-variable.md) +- [How to Setup Static Field Mapping](./field-mapping.md) +- [Setting Up a Wrike Automation](./setting-up-automation.md) +- [Troubleshooting and FAQ](./troubleshooting.md) diff --git a/docs/Integrations/Wrike/index.md b/docs/Integrations/Wrike/index.md index 8cab082..956fcb9 100644 --- a/docs/Integrations/Wrike/index.md +++ b/docs/Integrations/Wrike/index.md @@ -23,7 +23,7 @@ keywords: TurboDocx integrates with Wrike to automatically generate professional documents, proposals, and presentations directly from your project management data. When a task status changes in Wrike, TurboDocx can automatically create and attach documents to your projects. :::tip See It in Action -Want to see the full workflow before diving into setup? Check out the [End-to-End Example](/docs/Integrations/Wrike/signature-workflow) — generate a proposal and send it for signature, all from Wrike. +Want to see the full workflow before diving into setup? Check out the [End-to-End Example](./signature-workflow.md) — generate a proposal and send it for signature, all from Wrike. ::: ## What You Can Create @@ -47,7 +47,7 @@ You'll need: - Admin access to your Wrike workspace - Admin access to your TurboDocx organization -- A template ready in TurboDocx (see [How to Create a Template](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Template)) +- A template ready in TurboDocx (see [How to Create a Template](../../TurboDocx%20Templating/How%20to%20Create%20a%20Template.md)) - About 5 minutes
@@ -67,18 +67,18 @@ The Wrike integration uses a **status-triggered automation workflow** that you c | Guide | Description | |-------|-------------| -| [End-to-End Example](/docs/Integrations/Wrike/signature-workflow) | Watch the full workflow in action — generate a proposal and send it for signature | -| [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) | Connect Wrike and create an automation with a trigger status and folder | -| [How to Setup Document Generation Automation](/docs/Integrations/Wrike/document-generation-automation) | Configure an automation to generate documents from a template | -| [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation) | Generate documents and send them for e-signature automatically | -| [How to Setup Static Field Mapping](/docs/Integrations/Wrike/field-mapping) | Map Wrike custom fields (revenue, dates, etc.) directly to template variables | -| [How to Setup AI Variable Configuration](/docs/Integrations/Wrike/ai-variable) | Configure AI-driven variables that generate content from prompts during automation | -| [How to Add a Wrike Table](/docs/Integrations/Wrike/table-variable) | Turn a variable into a table of a folder or project's sub-items, with nesting and filtering | -| [How to Add a Wrike Image](/docs/Integrations/Wrike/image-variable) | Pull image attachments from the triggering task or folder into your document | -| [How to Convert Documents to PDF](/docs/Integrations/Wrike/convert-to-pdf) | Convert the first attachment to PDF when a task, project, or folder changes status, with in-place versioning | -| [How to Set Up Document Packages (Combined PDF)](/docs/Integrations/Wrike/document-packages) | Merge every attachment on a task or project into one combined PDF and attach it back to Wrike | -| [How to Add Signature Anchors](/docs/Integrations/Wrike/signature-anchors) | Configure signature anchor fields in your template for TurboSign | -| [Troubleshooting and FAQ](/docs/Integrations/Wrike/troubleshooting) | Common issues, solutions, and frequently asked questions | +| [End-to-End Example](./signature-workflow.md) | Watch the full workflow in action — generate a proposal and send it for signature | +| [Setting Up a Wrike Automation](./setting-up-automation.md) | Connect Wrike and create an automation with a trigger status and folder | +| [How to Setup Document Generation Automation](./document-generation-automation.md) | Configure an automation to generate documents from a template | +| [How to Setup E-Signature Automation](./signature-automation.md) | Generate documents and send them for e-signature automatically | +| [How to Setup Static Field Mapping](./field-mapping.md) | Map Wrike custom fields (revenue, dates, etc.) directly to template variables | +| [How to Setup AI Variable Configuration](./ai-variable.md) | Configure AI-driven variables that generate content from prompts during automation | +| [How to Add a Wrike Table](./table-variable.md) | Turn a variable into a table of a folder or project's sub-items, with nesting and filtering | +| [How to Add a Wrike Image](./image-variable.md) | Pull image attachments from the triggering task or folder into your document | +| [How to Convert Documents to PDF](./convert-to-pdf.md) | Convert the first attachment to PDF when a task, project, or folder changes status, with in-place versioning | +| [How to Set Up Document Packages (Combined PDF)](./document-packages.md) | Merge every attachment on a task or project into one combined PDF and attach it back to Wrike | +| [How to Add Signature Anchors](./signature-anchors.md) | Configure signature anchor fields in your template for TurboSign | +| [Troubleshooting and FAQ](./troubleshooting.md) | Common issues, solutions, and frequently asked questions |
diff --git a/docs/Integrations/Wrike/setting-up-automation.md b/docs/Integrations/Wrike/setting-up-automation.md index fe3e2c9..b46f706 100644 --- a/docs/Integrations/Wrike/setting-up-automation.md +++ b/docs/Integrations/Wrike/setting-up-automation.md @@ -20,7 +20,7 @@ This guide walks you through connecting your Wrike account to TurboDocx and crea Before starting, make sure you have: - A **Wrike API access token** (see [Get Your Wrike Access Token](#get-your-wrike-access-token) below) -- A **template** in TurboDocx ready for document generation (see [How to Create a Template](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Template)) +- A **template** in TurboDocx ready for document generation (see [How to Create a Template](../../TurboDocx%20Templating/How%20to%20Create%20a%20Template.md)) - The **Wrike folder permalink** for the folder you want to monitor
@@ -110,5 +110,5 @@ Click the **Next** button at the bottom-right corner of the setup modal to conti After completing the base automation setup above, choose which type of automation to configure: -- **[How to Setup Document Generation Automation](/docs/Integrations/Wrike/document-generation-automation)** — automatically generate documents from a template when the trigger fires -- **[How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation)** — generate documents and send them for digital signature via TurboSign +- **[How to Setup Document Generation Automation](./document-generation-automation.md)** — automatically generate documents from a template when the trigger fires +- **[How to Setup E-Signature Automation](./signature-automation.md)** — generate documents and send them for digital signature via TurboSign diff --git a/docs/Integrations/Wrike/signature-anchors.md b/docs/Integrations/Wrike/signature-anchors.md index d2562bd..80ff7e1 100644 --- a/docs/Integrations/Wrike/signature-anchors.md +++ b/docs/Integrations/Wrike/signature-anchors.md @@ -17,7 +17,7 @@ Signature anchors are special template variables that tell TurboSign where to pl ## Prerequisites - A template uploaded to TurboDocx with signature variables (e.g., `{SalesSigner}`) -- An e-signature automation configured (see [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation)) +- An e-signature automation configured (see [How to Setup E-Signature Automation](./signature-automation.md))
@@ -68,5 +68,5 @@ Repeat steps 3–6 for each signature variable in your template (e.g., `{SalesSi ::: :::caution Anchor Names Must Match Your E-Signature Automation -The signature anchor variable names you configure here **must exactly match** the anchor tags in your [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation). For example, if you set up `{SalesSignerSignature}` as an anchor here, the anchor tag in your e-signature automation must also be `{SalesSignerSignature}`. If they don't match, TurboSign won't be able to place the signature fields. See [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation) for how to configure the anchor tags on the automation side. +The signature anchor variable names you configure here **must exactly match** the anchor tags in your [How to Setup E-Signature Automation](./signature-automation.md). For example, if you set up `{SalesSignerSignature}` as an anchor here, the anchor tag in your e-signature automation must also be `{SalesSignerSignature}`. If they don't match, TurboSign won't be able to place the signature fields. See [How to Setup E-Signature Automation](./signature-automation.md) for how to configure the anchor tags on the automation side. ::: diff --git a/docs/Integrations/Wrike/signature-automation.md b/docs/Integrations/Wrike/signature-automation.md index 1a85ead..6545c9b 100644 --- a/docs/Integrations/Wrike/signature-automation.md +++ b/docs/Integrations/Wrike/signature-automation.md @@ -12,7 +12,7 @@ keywords: # How to Setup E-Signature Automation -After [setting up your Wrike automation](/docs/Integrations/Wrike/setting-up-automation) with a trigger status and folder, follow these steps to configure it to generate documents and automatically send them for e-signature. +After [setting up your Wrike automation](./setting-up-automation.md) with a trigger status and folder, follow these steps to configure it to generate documents and automatically send them for e-signature.
@@ -117,7 +117,7 @@ Change the anchor tag to match the placeholder in your template (e.g., `{SalesSi ![Set Anchor Tag](/img/wrike-integration/SigAuto09-ChangeAnchorTag.jpeg) :::caution Anchor Tags Must Match Your Template -The anchor tag you set here **must exactly match** the corresponding variable in your document template. If they don't match, TurboSign won't be able to place the signature field. See [How to Add Signature Anchors](/docs/Integrations/Wrike/signature-anchors) for how to configure these in your template. +The anchor tag you set here **must exactly match** the corresponding variable in your document template. If they don't match, TurboSign won't be able to place the signature field. See [How to Add Signature Anchors](./signature-anchors.md) for how to configure these in your template. ::: ### Step 10: Map Additional Document Fields (Optional) @@ -178,7 +178,7 @@ In the **Wrike activity updates** section of the signature action step, you'll s | **Finalization failed** | The signed PDF could not be finalized (e.g. a signing error) | The document is **not** marked Completed | | **Voided** | The signature request is voided or cancelled | e.g. `Document voided` | -These rows map to the same signature lifecycle events surfaced by [TurboSign webhooks](/docs/TurboSign/Webhooks) — see that page if you also want these events pushed to your own endpoints. +These rows map to the same signature lifecycle events surfaced by [TurboSign webhooks](../../TurboSign/Webhooks.md) — see that page if you also want these events pushed to your own endpoints. :::info The Completed row The table also shows a **Completed** row, but it is not configured here — it reuses the post-signature status you set in **Step 12–13** above and posts automatically once all recipients have signed. Set the "all recipients signed" status there, not in this section. @@ -215,6 +215,6 @@ Click **Create Automation** to save and activate your e-signature automation wor ## What's Next? -- **[How to Add Signature Anchors](/docs/Integrations/Wrike/signature-anchors)** to your template if you haven't already -- **[How to Setup Static Field Mapping](/docs/Integrations/Wrike/field-mapping)** to template variables for static data -- If something isn't working, see [Troubleshooting and FAQ](/docs/Integrations/Wrike/troubleshooting) +- **[How to Add Signature Anchors](./signature-anchors.md)** to your template if you haven't already +- **[How to Setup Static Field Mapping](./field-mapping.md)** to template variables for static data +- If something isn't working, see [Troubleshooting and FAQ](./troubleshooting.md) diff --git a/docs/Integrations/Wrike/signature-workflow.md b/docs/Integrations/Wrike/signature-workflow.md index ce869b6..1b77ad9 100644 --- a/docs/Integrations/Wrike/signature-workflow.md +++ b/docs/Integrations/Wrike/signature-workflow.md @@ -38,7 +38,7 @@ Navigate to the task you want to generate a document for. In this example, we're ## Step 2: Trigger Document Generation :::info How to set this up -See [How to Setup Document Generation Automation](/docs/Integrations/Wrike/document-generation-automation) to configure the trigger status and template for your automation. +See [How to Setup Document Generation Automation](./document-generation-automation.md) to configure the trigger status and template for your automation. ::: Change the task status to **"Generate Document"**. This is the trigger status configured in the TurboDocx automation — as soon as the status changes, TurboDocx picks it up. @@ -58,7 +58,7 @@ Within moments, the **TurboDocx Document Bot** generates the document and attach ## Step 4: Review the Generated Document :::info How to set this up -See [How to Setup Static Field Mapping](/docs/Integrations/Wrike/field-mapping) to map Wrike custom fields to template variables, and [How to Setup AI Variable Configuration](/docs/Integrations/Wrike/ai-variable) to configure AI-generated content. +See [How to Setup Static Field Mapping](./field-mapping.md) to map Wrike custom fields to template variables, and [How to Setup AI Variable Configuration](./ai-variable.md) to configure AI-generated content. ::: Click the attachment to open and review the proposal. Notice two things: @@ -84,7 +84,7 @@ In the TurboDocx template settings, each of these variables is marked as a **Wri ![Anchor configuration in template settings](/img/wrike-integration/EndToEnd06-AnchorConfig.jpeg) -For the full setup guide, see [How to Add Signature Anchors](/docs/Integrations/Wrike/signature-anchors). +For the full setup guide, see [How to Add Signature Anchors](./signature-anchors.md). @@ -101,7 +101,7 @@ In the e-signature automation configuration, each anchor tag is mapped to a spec ![Date and Full Name anchor fields](/img/wrike-integration/EndToEnd08-DateAnchorField.jpeg) -For the full setup guide, see [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation). +For the full setup guide, see [How to Setup E-Signature Automation](./signature-automation.md). @@ -112,7 +112,7 @@ The signing request is sent to the email address in the **"Customer email"** cus ![Customer email field in Wrike task](/img/wrike-integration/EndToEnd09-RecipientEmail.jpeg) -For details on mapping recipient fields, see [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation). +For details on mapping recipient fields, see [How to Setup E-Signature Automation](./signature-automation.md). @@ -125,7 +125,7 @@ Here's what it looks like once TurboSign places the interactive signature fields ## Step 6: Send for Signature :::info How to set this up -See [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation) to configure the signature trigger, recipients, and anchor tag mapping. +See [How to Setup E-Signature Automation](./signature-automation.md) to configure the signature trigger, recipients, and anchor tag mapping. ::: Back in Wrike, change the task status to **"Send for Signature"**. This triggers the TurboSign signing workflow. @@ -156,8 +156,8 @@ Ready to configure this workflow for your team? Follow these guides in order: | Step | Guide | What You'll Do | |------|-------|---------------| -| 1 | [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) | Connect Wrike and create your first automation | -| 2 | [How to Setup Static Field Mapping](/docs/Integrations/Wrike/field-mapping) | Map Wrike custom fields (revenue, dates) to template variables | -| 3 | [How to Setup AI Variable Configuration](/docs/Integrations/Wrike/ai-variable) | Set up AI-generated content like project timelines | -| 4 | [How to Add Signature Anchors](/docs/Integrations/Wrike/signature-anchors) | Mark template variables as signature anchor fields | -| 5 | [How to Setup E-Signature Automation](/docs/Integrations/Wrike/signature-automation) | Configure recipients, anchor tags, and post-signature actions | +| 1 | [Setting Up a Wrike Automation](./setting-up-automation.md) | Connect Wrike and create your first automation | +| 2 | [How to Setup Static Field Mapping](./field-mapping.md) | Map Wrike custom fields (revenue, dates) to template variables | +| 3 | [How to Setup AI Variable Configuration](./ai-variable.md) | Set up AI-generated content like project timelines | +| 4 | [How to Add Signature Anchors](./signature-anchors.md) | Mark template variables as signature anchor fields | +| 5 | [How to Setup E-Signature Automation](./signature-automation.md) | Configure recipients, anchor tags, and post-signature actions | diff --git a/docs/Integrations/Wrike/slide-automation.md b/docs/Integrations/Wrike/slide-automation.md index 2630d8d..abcb06f 100644 --- a/docs/Integrations/Wrike/slide-automation.md +++ b/docs/Integrations/Wrike/slide-automation.md @@ -21,17 +21,17 @@ keywords: So a two-slide template can produce a fifteen-slide deck, without anyone copying and pasting a slide per project. -This page covers the PowerPoint-specific setup. For the basics of connecting Wrike and creating an automation, start with [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation). +This page covers the PowerPoint-specific setup. For the basics of connecting Wrike and creating an automation, start with [Setting Up a Wrike Automation](./setting-up-automation.md). ## Prerequisites - A **PowerPoint (.pptx)** template uploaded to TurboDocx -- A connected Wrike account (see [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation)) +- A connected Wrike account (see [Setting Up a Wrike Automation](./setting-up-automation.md)) - A Wrike folder that contains the projects you want in the deck -- Variables on your template mapped to Wrike fields (see [Static Field Mapping](/docs/Integrations/Wrike/field-mapping)) +- Variables on your template mapped to Wrike fields (see [Static Field Mapping](./field-mapping.md)) :::note -Slide automation only applies to PowerPoint templates. Word templates use [document generation](/docs/Integrations/Wrike/document-generation-automation) instead. +Slide automation only applies to PowerPoint templates. Word templates use [document generation](./document-generation-automation.md) instead. :::
@@ -186,4 +186,4 @@ The **Table tag** doesn't match the table on the slide. Check the table's alt-te **The looping slide didn't repeat.** Check the slide is still marked as a **Looping slide** in Part 1, and that **Slide Automation** is switched on in Step 5. -For anything else, see [Wrike Integration Troubleshooting & FAQ](/docs/Integrations/Wrike/troubleshooting). +For anything else, see [Wrike Integration Troubleshooting & FAQ](./troubleshooting.md). diff --git a/docs/Integrations/Wrike/table-variable.md b/docs/Integrations/Wrike/table-variable.md index 611fc77..227bcfd 100644 --- a/docs/Integrations/Wrike/table-variable.md +++ b/docs/Integrations/Wrike/table-variable.md @@ -17,12 +17,12 @@ keywords: A **Wrike Table** variable turns a single template variable into a table. When the Wrike automation runs, TurboDocx fills that table with the triggering folder or project's **sub-items** (its tasks, and its subfolders or subprojects), one row each. You choose which Wrike fields become the columns, how the rows are laid out, whether nested sub-items are expanded, and an optional filter that limits which sub-items appear. -This is different from [Static Field Mapping](/docs/Integrations/Wrike/field-mapping), which maps one Wrike field to one variable. A Wrike Table maps one variable to many rows. +This is different from [Static Field Mapping](./field-mapping.md), which maps one Wrike field to one variable. A Wrike Table maps one variable to many rows. ## Prerequisites - A template uploaded to TurboDocx with at least one variable that is on its own line (a rich-text variable, so the generated table has room to render) -- A connected Wrike account (see [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation)) +- A connected Wrike account (see [Setting Up a Wrike Automation](./setting-up-automation.md))
@@ -141,7 +141,7 @@ The table is built by the Wrike automation when a document is generated, so a Wr ## Related -- [How to Add a Wrike Image](/docs/Integrations/Wrike/image-variable) -- [How to Setup Static Field Mapping](/docs/Integrations/Wrike/field-mapping) -- [Setting Up a Wrike Automation](/docs/Integrations/Wrike/setting-up-automation) -- [Troubleshooting and FAQ](/docs/Integrations/Wrike/troubleshooting) +- [How to Add a Wrike Image](./image-variable.md) +- [How to Setup Static Field Mapping](./field-mapping.md) +- [Setting Up a Wrike Automation](./setting-up-automation.md) +- [Troubleshooting and FAQ](./troubleshooting.md) diff --git a/docs/Integrations/Wrike/troubleshooting.md b/docs/Integrations/Wrike/troubleshooting.md index 360d2e2..f538d2c 100644 --- a/docs/Integrations/Wrike/troubleshooting.md +++ b/docs/Integrations/Wrike/troubleshooting.md @@ -57,7 +57,7 @@ keywords: - Ensure `Seller email` and `Customer email` custom fields exist and are populated on the Wrike task - Verify the document template contains all required signature anchor fields - Check that TurboSign is configured in your organization -- See the [End-to-End Example](/docs/Integrations/Wrike/signature-workflow) for full requirements +- See the [End-to-End Example](./signature-workflow.md) for full requirements
diff --git a/docs/Pipelines/Cloud Connectors.md b/docs/Pipelines/Cloud Connectors.md index 4b80eaa..325a991 100644 --- a/docs/Pipelines/Cloud Connectors.md +++ b/docs/Pipelines/Cloud Connectors.md @@ -72,7 +72,7 @@ Reach for a Cloud connector when the signer for a document can't be determined f - The right recipient comes from an **internal API** or directory service. - Signer assignment depends on business logic that lives in **your own systems**. -For simpler cases, such as a single fixed signer or a signer whose email is printed on the document, you can use a static signer or an extracted field instead. See **[Creating an E-Signature Pipeline](/docs/Pipelines/Creating%20an%20E-Signature%20Pipeline)** for those options. +For simpler cases, such as a single fixed signer or a signer whose email is printed on the document, you can use a static signer or an extracted field instead. See **[Creating an E-Signature Pipeline](./Creating%20an%20E-Signature%20Pipeline)** for those options.
diff --git a/docs/Pipelines/Creating an E-Signature Pipeline.md b/docs/Pipelines/Creating an E-Signature Pipeline.md index 6a2714f..8374cfa 100644 --- a/docs/Pipelines/Creating an E-Signature Pipeline.md +++ b/docs/Pipelines/Creating an E-Signature Pipeline.md @@ -37,7 +37,7 @@ Pipelines are an **Enterprise** feature. If you don't see the option to create o You'll need: -- **SharePoint connected to TurboDocx *for Pipelines*.** Pipelines run unattended, so they use their own SharePoint connection. An administrator registers an Azure AD app in the Azure portal (app-only and delegated permissions, admin consent, and a client secret), then pastes its credentials into the **Connect SharePoint** dialog reached from the **Pipelines** settings gear. This is a one-time admin task, and you can't create a pipeline until it's done. If you're not an administrator, have IT complete the **[Connect SharePoint for Pipelines setup](/docs/Pipelines/SharePoint%20Pipelines%20Troubleshooting%20and%20FAQ#setup-checklist)** first. (This is a *separate* connection from **[Configuring SharePoint or OneDrive](/docs/Advanced%20Configuration/Configuring%20Sharepoint%20or%20OneDrive)**, which covers template import and export, not Pipelines.) +- **SharePoint connected to TurboDocx *for Pipelines*.** Pipelines run unattended, so they use their own SharePoint connection. An administrator registers an Azure AD app in the Azure portal (app-only and delegated permissions, admin consent, and a client secret), then pastes its credentials into the **Connect SharePoint** dialog reached from the **Pipelines** settings gear. This is a one-time admin task, and you can't create a pipeline until it's done. If you're not an administrator, have IT complete the **[Connect SharePoint for Pipelines setup](./SharePoint%20Pipelines%20Troubleshooting%20and%20FAQ#setup-checklist)** first. (This is a *separate* connection from **[Configuring SharePoint or OneDrive](../Advanced%20Configuration/Configuring%20Sharepoint%20or%20OneDrive)**, which covers template import and export, not Pipelines.) - A **SharePoint document library** to use as your intake folder. - A **representative sample PDF**, meaning a real example of the kind of document this pipeline will process. - The details of who should sign these documents. @@ -104,8 +104,8 @@ The Sent folder must be a different folder from the intake library. If they were This step has three sections, matching the wizard: **Route each Document**, **Also extract**, and **Signature Placement**. The first two are optional; signature placement is required. 1. **Route each Document (optional)**: send documents that match certain text to different destination folders. For example, route anything containing "West Region" to one folder and "East Region" to another, each with its own **Pick Folder**. Anything that matches no rule lands in the default destination folder you'll choose in Step 5. Turn on **Required, fail if nothing matches** only if a document that matches no rule should be treated as an error instead. -2. **Also extract (optional)**: pull additional values out of each PDF, such as a customer code, a date, an email, or an amount. Extracted values can drive filenames, signer lookup, and routing. See **[Field Extraction](/docs/Pipelines/Field%20Extraction)** for the details and examples. -3. **Signature Placement (required)**: click **Place Fields** to open the placement tool, then pick a field type and click on the sample to drop signature, date, initial, and other fields. You must place **at least one signature field** before you can continue. TurboDocx pins each field to the same spot on every document the pipeline processes. See **[Field Placement](/docs/Pipelines/Field%20Placement)** for all the field types and details. +2. **Also extract (optional)**: pull additional values out of each PDF, such as a customer code, a date, an email, or an amount. Extracted values can drive filenames, signer lookup, and routing. See **[Field Extraction](./Field%20Extraction)** for the details and examples. +3. **Signature Placement (required)**: click **Place Fields** to open the placement tool, then pick a field type and click on the sample to drop signature, date, initial, and other fields. You must place **at least one signature field** before you can continue. TurboDocx pins each field to the same spot on every document the pipeline processes. See **[Field Placement](./Field%20Placement)** for all the field types and details. ![The Extract & Route step, showing its Route each Document, Also extract, and Signature Placement sections](/img/creating-an-e-signature-pipeline/step3-extract-route.png) @@ -123,7 +123,7 @@ Tell the pipeline who should sign each document. Choose how the signer is resolv - **Static signer**: the same person signs every document that flows through this pipeline. - **An extracted field**: use a value the pipeline read from the document itself (for example, an email address found in the PDF) to determine the signer per document. -- **A Cloud connector (Enterprise)**: look the signer up in one of your own systems, such as an internal database or API. See **[Cloud Connectors](/docs/Pipelines/Cloud%20Connectors)** for how this works. +- **A Cloud connector (Enterprise)**: look the signer up in one of your own systems, such as an internal database or API. See **[Cloud Connectors](./Cloud%20Connectors)** for how this works. Then set the sender identity recipients will see on the signature email: @@ -161,7 +161,7 @@ The final step decides where finished documents go and lets you review everythin 2. **Filename pattern**: how each signed file is named. You can build the name from extracted values (for example, a customer code or date) so files are easy to find later. 3. **Audit-trail upload**: toggle on to file the signing audit trail (a separate PDF documenting the signing chain of custody) alongside each signed PDF. 4. **Deliver as a single ZIP file**: toggle on to bundle the signed PDF (and the audit trail, if enabled) into one `.zip` in the destination folder, instead of filing them as separate files. -5. **Notifications**: set who is emailed when a document is signed and delivered, and who is alerted when one fails. A failure recipient is required, so problems never go unnoticed. See **[Pipeline Notifications](/docs/Pipelines/Pipeline%20Notifications)** for default recipients, per-store overrides (a "store" is one routing rule), and how to customize the completion email. +5. **Notifications**: set who is emailed when a document is signed and delivered, and who is alerted when one fails. A failure recipient is required, so problems never go unnoticed. See **[Pipeline Notifications](./Pipeline%20Notifications)** for default recipients, per-store overrides (a "store" is one routing rule), and how to customize the completion email. 6. **Review and save**: confirm the source, extraction, signer, and destination settings, then save to activate the pipeline. ![The Destination step, showing the destination picker, the default destination folder, and the filename pattern builder](/img/creating-an-e-signature-pipeline/step5-destination-review.png) @@ -182,7 +182,7 @@ Once saved, the pipeline starts watching its intake library. From now on, every ## What's Next? -- **[Pipeline Notifications](/docs/Pipelines/Pipeline%20Notifications)**: choose who is alerted on success and failure, and customize the completion email. -- **[Field Extraction](/docs/Pipelines/Field%20Extraction)**: pull data out of each document with patterns. -- **[Field Placement](/docs/Pipelines/Field%20Placement)**: position signature and form fields on the sample. -- **[Cloud Connectors](/docs/Pipelines/Cloud%20Connectors)**: resolve signers from your own internal systems. +- **[Pipeline Notifications](./Pipeline%20Notifications)**: choose who is alerted on success and failure, and customize the completion email. +- **[Field Extraction](./Field%20Extraction)**: pull data out of each document with patterns. +- **[Field Placement](./Field%20Placement)**: position signature and form fields on the sample. +- **[Cloud Connectors](./Cloud%20Connectors)**: resolve signers from your own internal systems. diff --git a/docs/Pipelines/Field Extraction.md b/docs/Pipelines/Field Extraction.md index 3ad9ace..1e41d7a 100644 --- a/docs/Pipelines/Field Extraction.md +++ b/docs/Pipelines/Field Extraction.md @@ -97,5 +97,5 @@ A scanned, image-only PDF can still be signed by the pipeline. The *extraction-d ## What's Next? -- **[Field Placement](/docs/Pipelines/Field%20Placement)**: position signature and form fields on the sample. -- **[Creating an E-Signature Pipeline](/docs/Pipelines/Creating%20an%20E-Signature%20Pipeline)**: see where extraction fits in the wizard. +- **[Field Placement](./Field%20Placement)**: position signature and form fields on the sample. +- **[Creating an E-Signature Pipeline](./Creating%20an%20E-Signature%20Pipeline)**: see where extraction fits in the wizard. diff --git a/docs/Pipelines/Field Placement.md b/docs/Pipelines/Field Placement.md index 76b1618..98268fd 100644 --- a/docs/Pipelines/Field Placement.md +++ b/docs/Pipelines/Field Placement.md @@ -79,5 +79,5 @@ Because placement is relative to the page, the closer your sample matches your r ## What's Next? -- **[Field Extraction](/docs/Pipelines/Field%20Extraction)**: pull data out of each document with patterns. -- **[Creating an E-Signature Pipeline](/docs/Pipelines/Creating%20an%20E-Signature%20Pipeline)**: see the full wizard from start to finish. +- **[Field Extraction](./Field%20Extraction)**: pull data out of each document with patterns. +- **[Creating an E-Signature Pipeline](./Creating%20an%20E-Signature%20Pipeline)**: see the full wizard from start to finish. diff --git a/docs/Pipelines/Pipeline Notifications.md b/docs/Pipelines/Pipeline Notifications.md index 443e000..0f86edf 100644 --- a/docs/Pipelines/Pipeline Notifications.md +++ b/docs/Pipelines/Pipeline Notifications.md @@ -27,7 +27,7 @@ Pipelines are an **Enterprise** feature. If you don't see the option to create o
-You set **default notifications** on the **Destination** step (labeled **Deliver** in the wizard's progress rail), and **per-store overrides** on the **Extract & Route** step. If you haven't built a pipeline yet, start with **[Creating an E-Signature Pipeline](/docs/Pipelines/Creating%20an%20E-Signature%20Pipeline)** and come back here to fine-tune the alerts. +You set **default notifications** on the **Destination** step (labeled **Deliver** in the wizard's progress rail), and **per-store overrides** on the **Extract & Route** step. If you haven't built a pipeline yet, start with **[Creating an E-Signature Pipeline](./Creating%20an%20E-Signature%20Pipeline)** and come back here to fine-tune the alerts.
@@ -101,6 +101,6 @@ Per-store notifications are useful when different regions, branches, or departme ## What's Next? -- **[Creating an E-Signature Pipeline](/docs/Pipelines/Creating%20an%20E-Signature%20Pipeline)**: build the pipeline these notifications belong to. -- **[Field Extraction](/docs/Pipelines/Field%20Extraction)**: define the routing fields that create per-store rules. -- **[Cloud Connectors](/docs/Pipelines/Cloud%20Connectors)**: resolve signers from your own internal systems. +- **[Creating an E-Signature Pipeline](./Creating%20an%20E-Signature%20Pipeline)**: build the pipeline these notifications belong to. +- **[Field Extraction](./Field%20Extraction)**: define the routing fields that create per-store rules. +- **[Cloud Connectors](./Cloud%20Connectors)**: resolve signers from your own internal systems. diff --git a/docs/Pipelines/TurboDocx Pipelines.md b/docs/Pipelines/TurboDocx Pipelines.md index 4f14871..e414a63 100644 --- a/docs/Pipelines/TurboDocx Pipelines.md +++ b/docs/Pipelines/TurboDocx Pipelines.md @@ -89,7 +89,7 @@ If your team is manually downloading, signing, and re-filing the same kind of do ## Get Started -Ready to set one up? See **[Creating an E-Signature Pipeline](/docs/Pipelines/Creating%20an%20E-Signature%20Pipeline)** for the step-by-step walkthrough. +Ready to set one up? See **[Creating an E-Signature Pipeline](./Creating%20an%20E-Signature%20Pipeline)** for the step-by-step walkthrough.
diff --git a/docs/TurboDocx Templating/API Templates.md b/docs/TurboDocx Templating/API Templates.md index 190483d..6a32160 100644 --- a/docs/TurboDocx Templating/API Templates.md +++ b/docs/TurboDocx Templating/API Templates.md @@ -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** (coming soon) -📖 **Bulk Document Generation** (coming soon) -📖 **Template Version Management** (coming soon) +📖 **[Webhook Integration for Status Updates →](/docs/TurboSign/Webhooks)** ### Related Documentation -- **Template Management Guide** (coming soon) - [Variable Types and Formatting](/docs/API/Deliverable%20API#variable-object-structure) -- [API Authentication](/docs/API/Deliverable%20API) -- Integration Examples +- [API Authentication](/docs/API/turbodocx-api-documentation) ## Support diff --git a/docs/TurboDocx Templating/Brand Identity.md b/docs/TurboDocx Templating/Brand Identity.md index 6a8599c..09a05a2 100644 --- a/docs/TurboDocx Templating/Brand Identity.md +++ b/docs/TurboDocx Templating/Brand Identity.md @@ -74,7 +74,7 @@ Brand Identity configuration includes: - **Real-time Preview**: See changes instantly as you configure :::info Key Difference -**Brand Identity** sets organization-wide styling standards, while **[Working with Fonts](/docs/TurboDocx%20Templating/Working%20with%20Fonts)** covers embedding specific desktop fonts in individual templates. +**Brand Identity** sets organization-wide styling standards, while **[Working with Fonts](./Working%20with%20Fonts.md)** covers embedding specific desktop fonts in individual templates. ::: ## Detailed Configuration (Optional) @@ -274,13 +274,13 @@ Now that your Brand Identity is configured, here's how to put it to work: ### Immediate Next Steps 1. **Test with existing templates** - Generate a document from an existing template to see your branding applied -2. **Create your first branded template** - Follow our [How to Create a Template](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Template) guide +2. **Create your first branded template** - Follow our [How to Create a Template](./How%20to%20Create%20a%20Template.md) guide 3. **Set up team access** - Ensure team members have appropriate permissions to use templates ### Building Your Document Workflow - **Templates**: Your brand settings automatically apply to all new and existing templates - **Deliverables**: Every generated document will use your brand identity consistently -- **Knowledge Base**: Combine with [knowledge base entries](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Knowledgebase%20Entry) for fully automated, branded documents +- **Knowledge Base**: Combine with [knowledge base entries](./How%20to%20Create%20a%20Knowledgebase%20Entry.md) for fully automated, branded documents ### Integration Opportunities - **Salesforce Integration**: Branded proposals generated directly from CRM data @@ -332,7 +332,7 @@ Start with 2-3 core templates (proposal, report, letter) to see immediate value, **Font Conflicts:** - TurboDocx by default uses the font found in the template -- For custom fonts, use [Working with Fonts](/docs/TurboDocx%20Templating/Working%20with%20Fonts) embedding +- For custom fonts, use [Working with Fonts](./Working%20with%20Fonts.md) embedding ## Getting Help @@ -343,7 +343,7 @@ If you encounter issues with Brand Identity configuration: 3. **Test with Sample Documents**: Generate test documents to verify settings 4. **Contact Support**: Provide specific details about configuration issues and document types -For technical font embedding questions, refer to [Working with Fonts](/docs/TurboDocx%20Templating/Working%20with%20Fonts). +For technical font embedding questions, refer to [Working with Fonts](./Working%20with%20Fonts.md). :::info Next Steps After configuring your Brand Identity, create new templates or update existing ones to see your branding applied consistently across all generated documents. diff --git a/docs/TurboDocx Templating/Template Troubleshooting.md b/docs/TurboDocx Templating/Template Troubleshooting.md index 1affe95..0e9c957 100644 --- a/docs/TurboDocx Templating/Template Troubleshooting.md +++ b/docs/TurboDocx Templating/Template Troubleshooting.md @@ -216,10 +216,10 @@ Turn on ¶ symbols to see hidden formatting issues Only PNG and JPEG can go into a deliverable — convert SVG, GIF, WebP, BMP, TIFF, HEIC, AVIF and ICO first ### 5. For Presentation Templates -Use invisible rectangle shapes, not text boxes → [See presentation setup guide](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Presentation%20Template) +Use invisible rectangle shapes, not text boxes → [See presentation setup guide](./How%20to%20Create%20a%20Presentation%20Template) ### 6. Test Your Template -Create a simple deliverable to verify everything works → [Learn how to create deliverables](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Deliverable) +Create a simple deliverable to verify everything works → [Learn how to create deliverables](./How%20to%20Create%20a%20Deliverable)
:::tip Advanced Troubleshooting & Best Practices @@ -230,9 +230,9 @@ Create a simple deliverable to verify everything works → [Learn how to create - **For presentations:** Ensure shapes are truly invisible (no fill, no outline) **Best practices for success:** -- **Test your template** by creating a deliverable before finalizing → [See how](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Deliverable) +- **Test your template** by creating a deliverable before finalizing → [See how](./How%20to%20Create%20a%20Deliverable) - **Keep variable names descriptive** but concise -- **Use consistent formatting** across all templates → [Document templates](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Document%20Template) | [Presentation templates](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Presentation%20Template) +- **Use consistent formatting** across all templates → [Document templates](./How%20to%20Create%20a%20Document%20Template) | [Presentation templates](./How%20to%20Create%20a%20Presentation%20Template) ::: @@ -240,9 +240,9 @@ Create a simple deliverable to verify everything works → [Learn how to create Still stuck? We're here to help! Check out our comprehensive guides: -- [📄 Document Templates](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Document%20Template) - Learn to create Word/Google Doc templates -- [📊 Presentation Templates](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Presentation%20Template) - Learn to create PowerPoint templates -- [🎯 Create Deliverables](/docs/TurboDocx%20Templating/How%20to%20Create%20a%20Deliverable) - Learn to generate documents from templates +- [📄 Document Templates](./How%20to%20Create%20a%20Document%20Template) - Learn to create Word/Google Doc templates +- [📊 Presentation Templates](./How%20to%20Create%20a%20Presentation%20Template) - Learn to create PowerPoint templates +- [🎯 Create Deliverables](./How%20to%20Create%20a%20Deliverable) - Learn to generate documents from templates - [📚 Full Documentation](https://docs.turbodocx.com) - Complete TurboDocx documentation If you need additional help, don't hesitate to reach out to our support team. diff --git a/docs/TurboDocx Templating/ai-variable-generation.md b/docs/TurboDocx Templating/ai-variable-generation.md index 9d7dfec..64a0862 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** (coming soon) -📖 **Bulk Processing** (coming soon) -📖 **[API Authentication →](/docs/API/Deliverable%20API)** +📖 **[Webhook Integration →](/docs/TurboSign/Webhooks)** +📖 **[API Authentication →](/docs/API/turbodocx-api-documentation)** ### Related Documentation -- **Template Management Guide** (coming soon) - [Variable Types and Formatting](/docs/API/Deliverable%20API#variable-object-structure) -- Integration Examples -- **Best Practices Guide** (coming soon) ## Support diff --git a/docs/TurboQuote/Bulk Importing from a Spreadsheet.md b/docs/TurboQuote/Bulk Importing from a Spreadsheet.md index 9b4d95a..03af209 100644 --- a/docs/TurboQuote/Bulk Importing from a Spreadsheet.md +++ b/docs/TurboQuote/Bulk Importing from a Spreadsheet.md @@ -284,5 +284,5 @@ Import your **products first**, then reference them by SKU in your bundle and pr ## Related -- [Adding a New Product](/docs/TurboQuote/Adding%20a%20New%20Product) -- [Creating a New Quote](/docs/TurboQuote/Creating%20a%20New%20Quote) +- [Adding a New Product](./Adding%20a%20New%20Product.md) +- [Creating a New Quote](./Creating%20a%20New%20Quote.md) diff --git a/docs/TurboQuote/Prepared By and Sender Identity.md b/docs/TurboQuote/Prepared By and Sender Identity.md index b734fda..3b84ed8 100644 --- a/docs/TurboQuote/Prepared By and Sender Identity.md +++ b/docs/TurboQuote/Prepared By and Sender Identity.md @@ -44,7 +44,7 @@ for the step-by-step walkthrough. ## Quotes created through the API, SDKs, or n8n When a quote is created by an **API key** — whether directly via the API, through one of the -[SDKs](/docs/SDKs), or from an n8n workflow — there is an important difference: **an API key +[SDKs](../SDKs/index.md), or from an n8n workflow — there is an important difference: **an API key has no mailbox of its own.** - The **"Prepared by" name** for an API-created quote resolves to the **name of the API key** @@ -110,7 +110,7 @@ returned as a **`preparedBy`** object alongside the quote: ``` Each SDK's `getQuote` folds `preparedBy` onto the returned quote for you (see the -[SDK guides](/docs/SDKs)). Both fields are optional — `email` may be absent for an +[SDK guides](../SDKs/index.md)). Both fields are optional — `email` may be absent for an API-created quote whose template has no sender email — so render a placeholder for a missing value. :::caution `preparedBy` is only on the single-quote fetch diff --git a/docs/TurboSign/API Signatures.md b/docs/TurboSign/API Signatures.md index 4a45773..0ae2d32 100644 --- a/docs/TurboSign/API Signatures.md +++ b/docs/TurboSign/API Signatures.md @@ -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 ## Support From f14a442ca178e59639f39e936c838cb48dcc0208 Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 07:53:03 -0400 Subject: [PATCH 16/17] [Trace] Noindex the empty docs.turbodocx.com root page / renders ~1 word to a first-pass crawler: it's a client-side redirect ( from @docusaurus/router) to the real hub at /docs. Per config/noindex-strategy.json (auto-noindex under 100 words), add a noindex,follow meta tag via @docusaurus/Head and exclude / from the sitemap plugin's ignorePatterns so the two signals agree. A server-side redirect (e.g. a Cloudflare Pages static/_redirects entry) would be the long-term fix so crawlers and users never hit the client-rendered stub at all, but that's out of scope here. --- docusaurus.config.js | 6 ++++++ src/pages/index.tsx | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index babe49c..49c74a9 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/src/pages/index.tsx b/src/pages/index.tsx index 3ccbe50..3407e79 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 From 1706bbf0711b33494dc7e79f8a4e53b660fd4006 Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 23 Sep 2026 13:57:04 -0400 Subject: [PATCH 17/17] fix(docs): use a placeholder for example webhook secrets The Create Webhook and Regenerate Webhook Secret response examples used realistic-looking whsec_ values (TurboDocx format: whsec_ + 64 hex), which secret scanners report as a Stripe webhook secret. Replace them with an obvious placeholder. --- docs/API/create-webhook.api.mdx | 2 +- docs/API/regenerate-webhook-secret.api.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/API/create-webhook.api.mdx b/docs/API/create-webhook.api.mdx index 7091f14..0ebb963 100644 --- a/docs/API/create-webhook.api.mdx +++ b/docs/API/create-webhook.api.mdx @@ -51,7 +51,7 @@ On success the endpoint returns `201 Created`: "name": "signature", "urls": ["https://example.com/webhooks/turbodocx"], "events": ["signature.document.completed", "signature.document.voided"], - "secret": "whsec_9f1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f8", + "secret": "whsec_REPLACE_WITH_YOUR_WEBHOOK_SECRET", "isActive": true, "createdBy": "f5e6d7c8-9a0b-4c1d-2e3f-4a5b6c7d8e9f", "createdOn": "2026-05-01T14:22:10.000Z", diff --git a/docs/API/regenerate-webhook-secret.api.mdx b/docs/API/regenerate-webhook-secret.api.mdx index 9329032..8e448c0 100644 --- a/docs/API/regenerate-webhook-secret.api.mdx +++ b/docs/API/regenerate-webhook-secret.api.mdx @@ -38,7 +38,7 @@ curl -X POST "https://api.turbodocx.com/api/webhooks/signature/regenerate" \ { "data": { "id": "b7e2c4a1-3f9d-4e6a-8c1b-5d0f7a2e9c34", - "secret": "whsec_1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f809", + "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."