Makes a secret to sign the context of your embeds with, and returns it in secret: keep it now, it is
shown once and cannot be read again. Keep it on your server only: whoever holds it can write contexts your
compositions accept. Call this again to make a new secret; the one it replaces is still accepted for a day, so
that your server can switch without an entry being refused (making another within that day ends the overlap
with the first).
What signing is for.<widgetic composition-id="..." context='{"customerId":"c_42"}'> hands attribution to
a widget, which sends it with every entry it saves. The page is yours but the browser is the visitor’s:
anybody can change that attribute and file an entry under another customer’s id. When your server signs the
context, the gateway refuses an entry whose context was changed, and the entries you keep hold attribution
your server wrote.
How to sign (on your server, for each page you render):
Take the context to give the widget. It may hold text and whole numbers only (within ±2^53, written without
a fraction or an exponent).
Choose when the signature stops being good: widgetic_exp, in seconds since 1970 (UTC), no more than
seven days from now. A minute of difference between clocks is forgiven.
Write the text to sign, with no spaces except those inside values:
widgetic-context.v1.<compositionId>.<widgetic_exp>.<json>. <compositionId> is the id of the composition
in lower case. <json> is the context as JSON with the keys in character-code order (so Z comes before
a, and 10 before 9), no spaces, strings escaped as JSON escapes them, and the two keys of the
signature left out.
Sign that text: HMAC-SHA256 with the 32 bytes the secret stands for (the base64 text after ctxsec_), and
write the result as base64url without padding.
Give the widget the context with two keys added: widgetic_exp and widgetic_sig (the signature). The whole
attribute, the two keys included, stays within the limits of any context: at most 20 keys, 2048 bytes of
JSON, strings up to 500 characters. The two keys take two of the 20 keys and 87 bytes of the 2048.
A test vector, to check your code against before you rely on it. Secret
ctxsec_AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8= (the bytes 0 to 31), composition
7c9e6679-7425-40de-944b-e07fc1f90ae7, widgetic_exp 1792000000 and context
{"customerId":"c_42","plan":"pro","seats":3} sign the text
widgetic-context.v1.7c9e6679-7425-40de-944b-e07fc1f90ae7.1792000000.{"customerId":"c_42","plan":"pro","seats":3}
and give the signature j6g7151F54tl9C8oEY9levaYSppHME4fAPZ7WPwL8C8. (The secret is the example’s, not a
real one.)
What the gateway does with an entry. When you have a secret, an entry whose context carries a signature is
checked: a signature that does not match is refused with 403 CONTEXT_SIGNATURE_INVALID, and one that is past
widgetic_exp with 403 CONTEXT_SIGNATURE_EXPIRED. When you also require signatures
(updatePartnerEntryContextSigning) an entry whose context carries none is refused with 403
CONTEXT_SIGNATURE_REQUIRED. The two keys are taken out before the entry is stored or announced: your entries
and your entry.created events hold the context you wrote. A change you make reaches every part of the
gateway within a minute.
What it does not do. A signed context that has been seen (a page’s source is public) can be sent again by
anyone until widgetic_exp; when you must not accept the same context twice, put a value that is new for each
page view in it (a submissionId you made up) and keep the ones you have seen. The signature covers the
entries that reach Widgetic’s gateway: a row that gets into a table another way (your own code writing
straight into a database you brought, or the record calls of the composition’s owner) does not pass
through it, and carries no context.
Retry this call with the same Idempotency-Key if its answer was lost: the answer, secret included, is then
given again, and no second secret is made. This needs an API key with full access. The caller must be the
person who administers the partner, or a Widgetic administrator.
POST
/
partners
/
{partnerId}
/
entry-context-signing
/
secret
import { randomUUID } from 'node:crypto';
import { Configuration, PartnersApi } from '@widgetic/api-sdk-ts';
const partnersApi = new PartnersApi(new Configuration({ apiKey: 'YOUR_API_KEY' }));
const { data: made } = await partnersApi.rotatePartnerEntryContextSecret({ partnerId, idempotencyKey: randomUUID() });
// Shown once: keep it on your server now.
console.log(made.secret);
Required: a call without it is refused with 400. A key of your own that names this one request; a UUID is ideal. It is 8 to 50 characters of letters, digits, - and _. Send the same key again when you retry (after a timeout, a dropped connection or a 5xx) and the call is carried out once: the retry gets the first answer back, marked X-Idempotency-Cached: true. The same key with a different body is refused with 422, and a retry that arrives while the first call is still running with 409 (see Retry-After).
Extra information about the answer: where a page sits in a list, the cursor of the next page, or warnings about a call that succeeded with a caveat.
Show child attributes
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Widgetic","colors":{"primary":"#324E30","light":"#75A568","dark":"#0F210F"},"logo":{"light":"https://mintcdn.com/widgetic/Od-pD6ChvIzhY_fR/brand/logo-light.svg?fit=max\u0026auto=format\u0026n=Od-pD6ChvIzhY_fR\u0026q=85\u0026s=c80ce649cc12d9f206a4ea5d3d2d9d31","dark":"https://mintcdn.com/widgetic/Od-pD6ChvIzhY_fR/brand/logo-dark.svg?fit=max\u0026auto=format\u0026n=Od-pD6ChvIzhY_fR\u0026q=85\u0026s=46708e0c7194a1fa0844613fc8492364"},"favicon":"https://mintcdn.com/widgetic/Od-pD6ChvIzhY_fR/brand/favicon.svg?fit=max\u0026auto=format\u0026n=Od-pD6ChvIzhY_fR\u0026q=85\u0026s=94d26e3e8e9ecd316386c38057803c62","api":{},"footer":{"socials":{"x":"https://x.com/widgetic","github":"https://github.com/widgetic"}},"errors":{"404":{"redirect":false,"title":"Page not found","description":"We couldn't find the page you were looking for.\n\n\u003cCardGroup cols={2}>\n \u003cCard title=\"Documentation\" icon=\"book\" href=\"/docs/introduction\">\n Return to the home page\n \u003c/Card>\n \u003cCard title=\"Quickstart\" icon=\"rocket\" href=\"/docs/quickstart\">\n Get started in minutes\n \u003c/Card>\n \u003cCard title=\"API Reference\" icon=\"code\" href=\"/api-reference/introduction\">\n Explore API endpoints\n \u003c/Card>\n \u003cCard title=\"SDKs\" icon=\"cube\" href=\"/resources/sdks\">\n Explore our SDKs\n \u003c/Card>\n\u003c/CardGroup>\n\n\u003cInfo>\n Think this is a broken link? Email us at [support@widgetic.com](mailto:support@widgetic.com).\n\u003c/Info>"}},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"widgetic","hasAudioNarration":false,"actualSubdomain":"widgetic","customDomains":["widgetic.com"],"gitSource":{"type":"github","owner":"widgetic","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"entitlements":{},"buildId":"6af081e42ab4a0cc3d7f236c","clientVersion":"0.0.4111","searchFilterCounts":[{"language":"default","tag":"API Reference","count":177},{"language":"default","tag":"Documentation","count":42},{"language":"default","tag":"Partners","count":41},{"language":"default","tag":"Compositions","count":39},{"language":"default","tag":"Workflows","count":19},{"language":"default","tag":"Managed Users","count":18},{"language":"default","tag":"CLI","count":16},{"language":"default","tag":"Partner Integration","count":13},{"language":"default","tag":"Users","count":13},{"language":"default","tag":"Resources","count":10}]},"assistantConfig":{},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds","slug":"/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds","pageMetadata":{"title":"Make a secret to sign the context of your embeds","description":"Makes a secret to sign the `context` of your embeds with, and returns it in `secret`: **keep it now, it is\nshown once** and cannot be read again. Keep it on your server only: whoever holds it can write contexts your\ncompositions accept. Call this again to make a new secret; the one it replaces is still accepted for a day, so\nthat your server can switch without an entry being refused (making another within that day ends the overlap\nwith the first).\n\n**What signing is for.** `\u003cwidgetic composition-id=\"...\" context='{\"customerId\":\"c_42\"}'>` hands attribution to\na widget, which sends it with every entry it saves. The page is yours but the browser is the visitor's:\nanybody can change that attribute and file an entry under another customer's id. When your server signs the\ncontext, the gateway refuses an entry whose context was changed, and the entries you keep hold attribution\nyour server wrote.\n\n**How to sign** (on your server, for each page you render):\n\n1. Take the context to give the widget. It may hold text and whole numbers only (within ±2^53, written without\n a fraction or an exponent).\n2. Choose when the signature stops being good: `widgetic_exp`, in seconds since 1970 (UTC), no more than\n seven days from now. A minute of difference between clocks is forgiven.\n3. Write the text to sign, with no spaces except those inside values:\n `widgetic-context.v1.\u003ccompositionId>.\u003cwidgetic_exp>.\u003cjson>`. `\u003ccompositionId>` is the id of the composition\n in lower case. `\u003cjson>` is the context as JSON with the keys in character-code order (so `Z` comes before\n `a`, and `10` before `9`), no spaces, strings escaped as JSON escapes them, and the two keys of the\n signature left out.\n4. Sign that text: HMAC-SHA256 with the 32 bytes the secret stands for (the base64 text after `ctxsec_`), and\n write the result as base64url without padding.\n5. Give the widget the context with two keys added: `widgetic_exp` and `widgetic_sig` (the signature). The whole\n attribute, the two keys included, stays within the limits of any context: at most 20 keys, 2048 bytes of\n JSON, strings up to 500 characters. The two keys take two of the 20 keys and 87 bytes of the 2048.\n\nA test vector, to check your code against before you rely on it. Secret\n`ctxsec_AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=` (the bytes 0 to 31), composition\n`7c9e6679-7425-40de-944b-e07fc1f90ae7`, `widgetic_exp` 1792000000 and context\n`{\"customerId\":\"c_42\",\"plan\":\"pro\",\"seats\":3}` sign the text\n`widgetic-context.v1.7c9e6679-7425-40de-944b-e07fc1f90ae7.1792000000.{\"customerId\":\"c_42\",\"plan\":\"pro\",\"seats\":3}`\nand give the signature `j6g7151F54tl9C8oEY9levaYSppHME4fAPZ7WPwL8C8`. (The secret is the example's, not a\nreal one.)\n\n**What the gateway does with an entry.** When you have a secret, an entry whose context carries a signature is\nchecked: a signature that does not match is refused with 403 `CONTEXT_SIGNATURE_INVALID`, and one that is past\n`widgetic_exp` with 403 `CONTEXT_SIGNATURE_EXPIRED`. When you also require signatures\n(`updatePartnerEntryContextSigning`) an entry whose context carries none is refused with 403\n`CONTEXT_SIGNATURE_REQUIRED`. The two keys are taken out before the entry is stored or announced: your entries\nand your `entry.created` events hold the context you wrote. A change you make reaches every part of the\ngateway within a minute.\n\n**What it does not do.** A signed context that has been seen (a page's source is public) can be sent again by\nanyone until `widgetic_exp`; when you must not accept the same context twice, put a value that is new for each\npage view in it (a `submissionId` you made up) and keep the ones you have seen. The signature covers the\nentries that reach Widgetic's gateway: a row that gets into a table another way (your own code writing\nstraight into a database you brought, or the record calls of the composition's owner) does not pass\nthrough it, and carries no context.\n\nRetry this call with the same `Idempotency-Key` if its answer was lost: the answer, secret included, is then\ngiven again, and no second secret is made. This needs an API key with full access. The caller must be the\nperson who administers the partner, or a Widgetic administrator.\n","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /partners/{partnerId}/entry-context-signing/secret","href":"/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n li: \"li\",\n ol: \"ol\",\n p: \"p\",\n strong: \"strong\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_Fragment, {\n children: [_jsxs(_components.p, {\n children: [\"Makes a secret to sign the \", _jsx(_components.code, {\n children: \"context\"\n }), \" of your embeds with, and returns it in \", _jsx(_components.code, {\n children: \"secret\"\n }), \": \", _jsx(_components.strong, {\n children: \"keep it now, it is\\nshown once\"\n }), \" and cannot be read again. Keep it on your server only: whoever holds it can write contexts your\\ncompositions accept. Call this again to make a new secret; the one it replaces is still accepted for a day, so\\nthat your server can switch without an entry being refused (making another within that day ends the overlap\\nwith the first).\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [_jsx(_components.strong, {\n children: \"What signing is for.\"\n }), \" \", _jsx(_components.code, {\n children: \"\u003cwidgetic composition-id=\\\"...\\\" context='{\\\"customerId\\\":\\\"c_42\\\"}'>\"\n }), \" hands attribution to\\na widget, which sends it with every entry it saves. The page is yours but the browser is the visitor’s:\\nanybody can change that attribute and file an entry under another customer’s id. When your server signs the\\ncontext, the gateway refuses an entry whose context was changed, and the entries you keep hold attribution\\nyour server wrote.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [_jsx(_components.strong, {\n children: \"How to sign\"\n }), \" (on your server, for each page you render):\"]\n }), \"\\n\", _jsxs(_components.ol, {\n children: [\"\\n\", _jsx(_components.li, {\n children: \"Take the context to give the widget. It may hold text and whole numbers only (within ±2^53, written without\\na fraction or an exponent).\"\n }), \"\\n\", _jsxs(_components.li, {\n children: [\"Choose when the signature stops being good: \", _jsx(_components.code, {\n children: \"widgetic_exp\"\n }), \", in seconds since 1970 (UTC), no more than\\nseven days from now. A minute of difference between clocks is forgiven.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [\"Write the text to sign, with no spaces except those inside values:\\n\", _jsx(_components.code, {\n children: \"widgetic-context.v1.\u003ccompositionId>.\u003cwidgetic_exp>.\u003cjson>\"\n }), \". \", _jsx(_components.code, {\n children: \"\u003ccompositionId>\"\n }), \" is the id of the composition\\nin lower case. \", _jsx(_components.code, {\n children: \"\u003cjson>\"\n }), \" is the context as JSON with the keys in character-code order (so \", _jsx(_components.code, {\n children: \"Z\"\n }), \" comes before\\n\", _jsx(_components.code, {\n children: \"a\"\n }), \", and \", _jsx(_components.code, {\n children: \"10\"\n }), \" before \", _jsx(_components.code, {\n children: \"9\"\n }), \"), no spaces, strings escaped as JSON escapes them, and the two keys of the\\nsignature left out.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [\"Sign that text: HMAC-SHA256 with the 32 bytes the secret stands for (the base64 text after \", _jsx(_components.code, {\n children: \"ctxsec_\"\n }), \"), and\\nwrite the result as base64url without padding.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [\"Give the widget the context with two keys added: \", _jsx(_components.code, {\n children: \"widgetic_exp\"\n }), \" and \", _jsx(_components.code, {\n children: \"widgetic_sig\"\n }), \" (the signature). The whole\\nattribute, the two keys included, stays within the limits of any context: at most 20 keys, 2048 bytes of\\nJSON, strings up to 500 characters. The two keys take two of the 20 keys and 87 bytes of the 2048.\"]\n }), \"\\n\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"A test vector, to check your code against before you rely on it. Secret\\n\", _jsx(_components.code, {\n children: \"ctxsec_AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=\"\n }), \" (the bytes 0 to 31), composition\\n\", _jsx(_components.code, {\n children: \"7c9e6679-7425-40de-944b-e07fc1f90ae7\"\n }), \", \", _jsx(_components.code, {\n children: \"widgetic_exp\"\n }), \" 1792000000 and context\\n\", _jsx(_components.code, {\n children: \"{\\\"customerId\\\":\\\"c_42\\\",\\\"plan\\\":\\\"pro\\\",\\\"seats\\\":3}\"\n }), \" sign the text\\n\", _jsx(_components.code, {\n children: \"widgetic-context.v1.7c9e6679-7425-40de-944b-e07fc1f90ae7.1792000000.{\\\"customerId\\\":\\\"c_42\\\",\\\"plan\\\":\\\"pro\\\",\\\"seats\\\":3}\"\n }), \"\\nand give the signature \", _jsx(_components.code, {\n children: \"j6g7151F54tl9C8oEY9levaYSppHME4fAPZ7WPwL8C8\"\n }), \". (The secret is the example’s, not a\\nreal one.)\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [_jsx(_components.strong, {\n children: \"What the gateway does with an entry.\"\n }), \" When you have a secret, an entry whose context carries a signature is\\nchecked: a signature that does not match is refused with 403 \", _jsx(_components.code, {\n children: \"CONTEXT_SIGNATURE_INVALID\"\n }), \", and one that is past\\n\", _jsx(_components.code, {\n children: \"widgetic_exp\"\n }), \" with 403 \", _jsx(_components.code, {\n children: \"CONTEXT_SIGNATURE_EXPIRED\"\n }), \". When you also require signatures\\n(\", _jsx(_components.code, {\n children: \"updatePartnerEntryContextSigning\"\n }), \") an entry whose context carries none is refused with 403\\n\", _jsx(_components.code, {\n children: \"CONTEXT_SIGNATURE_REQUIRED\"\n }), \". The two keys are taken out before the entry is stored or announced: your entries\\nand your \", _jsx(_components.code, {\n children: \"entry.created\"\n }), \" events hold the context you wrote. A change you make reaches every part of the\\ngateway within a minute.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [_jsx(_components.strong, {\n children: \"What it does not do.\"\n }), \" A signed context that has been seen (a page’s source is public) can be sent again by\\nanyone until \", _jsx(_components.code, {\n children: \"widgetic_exp\"\n }), \"; when you must not accept the same context twice, put a value that is new for each\\npage view in it (a \", _jsx(_components.code, {\n children: \"submissionId\"\n }), \" you made up) and keep the ones you have seen. The signature covers the\\nentries that reach Widgetic’s gateway: a row that gets into a table another way (your own code writing\\nstraight into a database you brought, or the record calls of the composition’s owner) does not pass\\nthrough it, and carries no context.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Retry this call with the same \", _jsx(_components.code, {\n children: \"Idempotency-Key\"\n }), \" if its answer was lost: the answer, secret included, is then\\ngiven again, and no second secret is made. This needs an API key with full access. The caller must be the\\nperson who administers the partner, or a Widgetic administrator.\"]\n })]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){return _jsx(_Fragment,{})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Make a secret to sign the context of your embeds","description":"Makes a secret to sign the `context` of your embeds with, and returns it in `secret`: **keep it now, it is\nshown once** and cannot be read again. Keep it on your server only: whoever holds it can write contexts your\ncompositions accept. Call this again to make a new secret; the one it replaces is still accepted for a day, so\nthat your server can switch without an entry being refused (making another within that day ends the overlap\nwith the first).\n\n**What signing is for.** `\u003cwidgetic composition-id=\"...\" context='{\"customerId\":\"c_42\"}'>` hands attribution to\na widget, which sends it with every entry it saves. The page is yours but the browser is the visitor's:\nanybody can change that attribute and file an entry under another customer's id. When your server signs the\ncontext, the gateway refuses an entry whose context was changed, and the entries you keep hold attribution\nyour server wrote.\n\n**How to sign** (on your server, for each page you render):\n\n1. Take the context to give the widget. It may hold text and whole numbers only (within ±2^53, written without\n a fraction or an exponent).\n2. Choose when the signature stops being good: `widgetic_exp`, in seconds since 1970 (UTC), no more than\n seven days from now. A minute of difference between clocks is forgiven.\n3. Write the text to sign, with no spaces except those inside values:\n `widgetic-context.v1.\u003ccompositionId>.\u003cwidgetic_exp>.\u003cjson>`. `\u003ccompositionId>` is the id of the composition\n in lower case. `\u003cjson>` is the context as JSON with the keys in character-code order (so `Z` comes before\n `a`, and `10` before `9`), no spaces, strings escaped as JSON escapes them, and the two keys of the\n signature left out.\n4. Sign that text: HMAC-SHA256 with the 32 bytes the secret stands for (the base64 text after `ctxsec_`), and\n write the result as base64url without padding.\n5. Give the widget the context with two keys added: `widgetic_exp` and `widgetic_sig` (the signature). The whole\n attribute, the two keys included, stays within the limits of any context: at most 20 keys, 2048 bytes of\n JSON, strings up to 500 characters. The two keys take two of the 20 keys and 87 bytes of the 2048.\n\nA test vector, to check your code against before you rely on it. Secret\n`ctxsec_AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=` (the bytes 0 to 31), composition\n`7c9e6679-7425-40de-944b-e07fc1f90ae7`, `widgetic_exp` 1792000000 and context\n`{\"customerId\":\"c_42\",\"plan\":\"pro\",\"seats\":3}` sign the text\n`widgetic-context.v1.7c9e6679-7425-40de-944b-e07fc1f90ae7.1792000000.{\"customerId\":\"c_42\",\"plan\":\"pro\",\"seats\":3}`\nand give the signature `j6g7151F54tl9C8oEY9levaYSppHME4fAPZ7WPwL8C8`. (The secret is the example's, not a\nreal one.)\n\n**What the gateway does with an entry.** When you have a secret, an entry whose context carries a signature is\nchecked: a signature that does not match is refused with 403 `CONTEXT_SIGNATURE_INVALID`, and one that is past\n`widgetic_exp` with 403 `CONTEXT_SIGNATURE_EXPIRED`. When you also require signatures\n(`updatePartnerEntryContextSigning`) an entry whose context carries none is refused with 403\n`CONTEXT_SIGNATURE_REQUIRED`. The two keys are taken out before the entry is stored or announced: your entries\nand your `entry.created` events hold the context you wrote. A change you make reaches every part of the\ngateway within a minute.\n\n**What it does not do.** A signed context that has been seen (a page's source is public) can be sent again by\nanyone until `widgetic_exp`; when you must not accept the same context twice, put a value that is new for each\npage view in it (a `submissionId` you made up) and keep the ones you have seen. The signature covers the\nentries that reach Widgetic's gateway: a row that gets into a table another way (your own code writing\nstraight into a database you brought, or the record calls of the composition's owner) does not pass\nthrough it, and carries no context.\n\nRetry this call with the same `Idempotency-Key` if its answer was lost: the answer, secret included, is then\ngiven again, and no second secret is made. This needs an API key with full access. The caller must be the\nperson who administers the partner, or a Widgetic administrator.\n","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /partners/{partnerId}/entry-context-signing/secret","href":"/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":["/_mintlify/custom/widgetic/a06e02caee24c9e4/scripts/check-openapi-drift.js","/_mintlify/custom/widgetic/cfc959b865109f94/scripts/generate-code-samples.js","/_mintlify/custom/widgetic/4108e10153588825/scripts/sync-openapi.js","/_mintlify/custom/widgetic/0b8b2a5de38f31ba/scripts/validate-links.js","/_mintlify/custom/widgetic/f948d1cc9e974f48/scripts/__tests__/agentDocsDrift.test.js","/_mintlify/custom/widgetic/5e269cd2108b7191/scripts/check-agent-docs-drift.js","/_mintlify/custom/widgetic/5905b4748e7acd3e/scripts/lib/agentDocsDrift.js","/_mintlify/custom/widgetic/d772e7a3506ca340/scripts/__tests__/openApiServerAddress.test.js","/_mintlify/custom/widgetic/6a746d19cf42793e/scripts/lib/openApiServerAddress.js"],"openApiReferenceData":{"operation":{"operationId":"rotatePartnerEntryContextSecret","summary":"Make a secret to sign the context of your embeds","description":"Makes a secret to sign the `context` of your embeds with, and returns it in `secret`: **keep it now, it is\nshown once** and cannot be read again. Keep it on your server only: whoever holds it can write contexts your\ncompositions accept. Call this again to make a new secret; the one it replaces is still accepted for a day, so\nthat your server can switch without an entry being refused (making another within that day ends the overlap\nwith the first).\n\n**What signing is for.** `\u003cwidgetic composition-id=\"...\" context='{\"customerId\":\"c_42\"}'>` hands attribution to\na widget, which sends it with every entry it saves. The page is yours but the browser is the visitor's:\nanybody can change that attribute and file an entry under another customer's id. When your server signs the\ncontext, the gateway refuses an entry whose context was changed, and the entries you keep hold attribution\nyour server wrote.\n\n**How to sign** (on your server, for each page you render):\n\n1. Take the context to give the widget. It may hold text and whole numbers only (within ±2^53, written without\n a fraction or an exponent).\n2. Choose when the signature stops being good: `widgetic_exp`, in seconds since 1970 (UTC), no more than\n seven days from now. A minute of difference between clocks is forgiven.\n3. Write the text to sign, with no spaces except those inside values:\n `widgetic-context.v1.\u003ccompositionId>.\u003cwidgetic_exp>.\u003cjson>`. `\u003ccompositionId>` is the id of the composition\n in lower case. `\u003cjson>` is the context as JSON with the keys in character-code order (so `Z` comes before\n `a`, and `10` before `9`), no spaces, strings escaped as JSON escapes them, and the two keys of the\n signature left out.\n4. Sign that text: HMAC-SHA256 with the 32 bytes the secret stands for (the base64 text after `ctxsec_`), and\n write the result as base64url without padding.\n5. Give the widget the context with two keys added: `widgetic_exp` and `widgetic_sig` (the signature). The whole\n attribute, the two keys included, stays within the limits of any context: at most 20 keys, 2048 bytes of\n JSON, strings up to 500 characters. The two keys take two of the 20 keys and 87 bytes of the 2048.\n\nA test vector, to check your code against before you rely on it. Secret\n`ctxsec_AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=` (the bytes 0 to 31), composition\n`7c9e6679-7425-40de-944b-e07fc1f90ae7`, `widgetic_exp` 1792000000 and context\n`{\"customerId\":\"c_42\",\"plan\":\"pro\",\"seats\":3}` sign the text\n`widgetic-context.v1.7c9e6679-7425-40de-944b-e07fc1f90ae7.1792000000.{\"customerId\":\"c_42\",\"plan\":\"pro\",\"seats\":3}`\nand give the signature `j6g7151F54tl9C8oEY9levaYSppHME4fAPZ7WPwL8C8`. (The secret is the example's, not a\nreal one.)\n\n**What the gateway does with an entry.** When you have a secret, an entry whose context carries a signature is\nchecked: a signature that does not match is refused with 403 `CONTEXT_SIGNATURE_INVALID`, and one that is past\n`widgetic_exp` with 403 `CONTEXT_SIGNATURE_EXPIRED`. When you also require signatures\n(`updatePartnerEntryContextSigning`) an entry whose context carries none is refused with 403\n`CONTEXT_SIGNATURE_REQUIRED`. The two keys are taken out before the entry is stored or announced: your entries\nand your `entry.created` events hold the context you wrote. A change you make reaches every part of the\ngateway within a minute.\n\n**What it does not do.** A signed context that has been seen (a page's source is public) can be sent again by\nanyone until `widgetic_exp`; when you must not accept the same context twice, put a value that is new for each\npage view in it (a `submissionId` you made up) and keep the ones you have seen. The signature covers the\nentries that reach Widgetic's gateway: a row that gets into a table another way (your own code writing\nstraight into a database you brought, or the record calls of the composition's owner) does not pass\nthrough it, and carries no context.\n\nRetry this call with the same `Idempotency-Key` if its answer was lost: the answer, secret included, is then\ngiven again, and no second secret is made. This needs an API key with full access. The caller must be the\nperson who administers the partner, or a Widgetic administrator.\n","tags":["Partners"],"security":["1e559c4b-0d05-497c-be36-d4830b9d6fd8"],"x-access-level":"partner","x-visibility":"public","parameters":["19d7ac1c-3108-4468-a1fb-2c6f39e85835","71c35cd6-0edf-4ae3-94b8-f65817d4c1bc"],"responses":{"200":"3a21ef4a-c835-41e3-b587-e871ca46896e","400":"25a696b0-87d4-46bf-b422-c7cfe183075e","401":"421155dd-a9f1-4b0d-b2eb-fa976ff5cdb0","403":"a176b937-811e-407e-9151-3cd7044acd1a","404":"c6efaf31-a3ac-41de-97b6-c6108105d08b","429":"a5dd24fe-5df3-4148-8074-ec5ca14d45c5","503":"92516ec5-9646-4e94-ad9c-3a5c9c77f21b"},"x-code-samples":[{"lang":"TypeScript","label":"TypeScript SDK","source":"import { randomUUID } from 'node:crypto';\nimport { Configuration, PartnersApi } from '@widgetic/api-sdk-ts';\n\nconst partnersApi = new PartnersApi(new Configuration({ apiKey: 'YOUR_API_KEY' }));\n\nconst { data: made } = await partnersApi.rotatePartnerEntryContextSecret({ partnerId, idempotencyKey: randomUUID() });\n\n// Shown once: keep it on your server now.\nconsole.log(made.secret);\n"},{"lang":"TypeScript","label":"Sign a context (Node.js)","source":"import { createHmac } from 'node:crypto';\n\n// Returns the context to put in the `context` attribute: yours, plus widgetic_exp and widgetic_sig.\nfunction signContext(\n secret: string, // the ctxsec_ text you were shown\n compositionId: string,\n context: Record\u003cstring, string | number>, // text and whole numbers only\n lifetimeSeconds = 3600,\n) {\n const key = Buffer.from(secret.slice('ctxsec_'.length), 'base64');\n const widgeticExp = Math.floor(Date.now() / 1000) + lifetimeSeconds;\n const json =\n '{' +\n Object.keys(context)\n .sort()\n .map((name) => `${JSON.stringify(name)}:${JSON.stringify(context[name])}`)\n .join(',') +\n '}';\n const text = `widgetic-context.v1.${compositionId.toLowerCase()}.${widgeticExp}.${json}`;\n const widgeticSig = createHmac('sha256', key).update(text).digest('base64url');\n return { ...context, widgetic_exp: widgeticExp, widgetic_sig: widgeticSig };\n}\n\n// \u003cwidgetic composition-id=\"...\" context='${JSON.stringify(signContext(secret, id, { customerId: 'c_42' }))}'>\n"}],"method":"post","type":"path","servers":["8cdad7e2-72d7-448d-a767-c0ce9882d766"],"path":"/partners/{partnerId}/entry-context-signing/secret","baseUrlOptions":["https://api.widgetic.com/v1"],"title":"Make a secret to sign the context of your embeds","codeSamples":[{"label":"TypeScript SDK","lang":"TypeScript","source":"import { randomUUID } from 'node:crypto';\nimport { Configuration, PartnersApi } from '@widgetic/api-sdk-ts';\n\nconst partnersApi = new PartnersApi(new Configuration({ apiKey: 'YOUR_API_KEY' }));\n\nconst { data: made } = await partnersApi.rotatePartnerEntryContextSecret({ partnerId, idempotencyKey: randomUUID() });\n\n// Shown once: keep it on your server now.\nconsole.log(made.secret);\n"},{"label":"Sign a context (Node.js)","lang":"TypeScript","source":"import { createHmac } from 'node:crypto';\n\n// Returns the context to put in the `context` attribute: yours, plus widgetic_exp and widgetic_sig.\nfunction signContext(\n secret: string, // the ctxsec_ text you were shown\n compositionId: string,\n context: Record\u003cstring, string | number>, // text and whole numbers only\n lifetimeSeconds = 3600,\n) {\n const key = Buffer.from(secret.slice('ctxsec_'.length), 'base64');\n const widgeticExp = Math.floor(Date.now() / 1000) + lifetimeSeconds;\n const json =\n '{' +\n Object.keys(context)\n .sort()\n .map((name) => `${JSON.stringify(name)}:${JSON.stringify(context[name])}`)\n .join(',') +\n '}';\n const text = `widgetic-context.v1.${compositionId.toLowerCase()}.${widgeticExp}.${json}`;\n const widgeticSig = createHmac('sha256', key).update(text).digest('base64url');\n return { ...context, widgetic_exp: widgeticExp, widgetic_sig: widgeticSig };\n}\n\n// \u003cwidgetic composition-id=\"...\" context='${JSON.stringify(signContext(secret, id, { customerId: 'c_42' }))}'>\n"}],"requiredOnlyExamples":false,"requestExampleType":"codeSamples","responseExampleType":"generated"},"dependencies":{"parameters":{"19d7ac1c-3108-4468-a1fb-2c6f39e85835":{"in":"path","name":"partnerId","required":true,"schema":{"type":"string","format":"uuid","isRequired":true,"description":"The partner whose secret to make","uniqueKey":"","typeLabel":"string\u003cuuid>"},"description":"The partner whose secret to make"},"71c35cd6-0edf-4ae3-94b8-f65817d4c1bc":{"in":"header","name":"Idempotency-Key","required":true,"description":"Required: a call without it is refused with `400`. A key of your own that names this one request; a UUID is ideal. It is 8 to 50 characters of letters, digits, `-` and `_`. Send the same key again when you retry (after a timeout, a dropped connection or a `5xx`) and the call is carried out once: the retry gets the first answer back, marked `X-Idempotency-Cached: true`. The same key with a different body is refused with `422`, and a retry that arrives while the first call is still running with `409` (see `Retry-After`).","schema":{"type":"string","minLength":8,"maxLength":50,"pattern":"^[a-zA-Z0-9_-]{8,50}$","example":"9b2d6f0a-3c41-4e5a-8d77-1f2e3a4b5c6d","isRequired":true,"description":"Required: a call without it is refused with `400`. A key of your own that names this one request; a UUID is ideal. It is 8 to 50 characters of letters, digits, `-` and `_`. Send the same key again when you retry (after a timeout, a dropped connection or a `5xx`) and the call is carried out once: the retry gets the first answer back, marked `X-Idempotency-Cached: true`. The same key with a different body is refused with `422`, and a retry that arrives while the first call is still running with `409` (see `Retry-After`).","uniqueKey":"","typeLabel":"string"}}},"responses":{"3a21ef4a-c835-41e3-b587-e871ca46896e":{"description":"The new secret, and how your signing stands now","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always `true` on a success.","example":true,"isRequired":true,"uniqueKey":"success","typeLabel":"boolean"},"data":{"type":"object","description":"A new signing secret, and how your signing stands now.","required":["signing","secret"],"properties":{"signing":{"type":"object","description":"How the context of your embeds is signed. The secret that signs it is never part of this: it is shown once, when it is made.","required":["partnerId","required","secretSet","secretRotatedAt","previousSecretValidUntil","signingAvailable"],"properties":{"partnerId":{"type":"string","format":"uuid","isRequired":true,"uniqueKey":"data.signing.partnerId","typeLabel":"string\u003cuuid>"},"required":{"type":"boolean","description":"True: an entry whose context carries no valid signature is refused (403 `CONTEXT_SIGNATURE_REQUIRED`). False: an entry that carries a signature is checked, and one that carries none is accepted as before.","isRequired":true,"uniqueKey":"data.signing.required","typeLabel":"boolean"},"secretSet":{"type":"boolean","description":"Whether you have a signing secret. Until you have, no signature is checked and none can be required.","isRequired":true,"uniqueKey":"data.signing.secretSet","typeLabel":"boolean"},"secretRotatedAt":{"oneOf":[{"type":"string","format":"date-time","description":"When the current secret was made. Null while there is none.","isRequired":true,"uniqueKey":"data.signing.secretRotatedAt.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When the current secret was made. Null while there is none.","isRequired":true,"uniqueKey":"data.signing.secretRotatedAt.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.signing.secretRotatedAt","typeLabel":"string\u003cdate-time> | null"},"previousSecretValidUntil":{"oneOf":[{"type":"string","format":"date-time","description":"While you switch to a new secret, when the secret it replaced stops being accepted. Null when there is none to wait for.","isRequired":true,"uniqueKey":"data.signing.previousSecretValidUntil.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"While you switch to a new secret, when the secret it replaced stops being accepted. Null when there is none to wait for.","isRequired":true,"uniqueKey":"data.signing.previousSecretValidUntil.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.signing.previousSecretValidUntil","typeLabel":"string\u003cdate-time> | null"},"signingAvailable":{"type":"boolean","description":"False when this server cannot keep secrets, in which case none can be made yet.","isRequired":true,"uniqueKey":"data.signing.signingAvailable","typeLabel":"boolean"}},"example":{"partnerId":"3fa85f64-5717-4562-b3fc-2c963f66afa6","required":true,"secretSet":true,"secretRotatedAt":"2026-01-15T09:30:00.000Z","previousSecretValidUntil":"2026-01-15T09:30:00.000Z","signingAvailable":true},"isRequired":true,"uniqueKey":"data.signing","typeLabel":"object"},"secret":{"type":"string","description":"The secret: `ctxsec_` followed by the base64 of 32 random bytes. It is shown here, once, and cannot be read again.","isRequired":true,"uniqueKey":"data.secret","typeLabel":"string"}},"example":{"signing":null,"secret":"Example secret"},"isRequired":true,"uniqueKey":"data","typeLabel":"object"},"meta":{"type":"object","description":"Extra information about the answer: where a page sits in a list, the cursor of the next page, or warnings about a call that succeeded with a caveat.","additionalProperties":true,"properties":{"page":{"type":"integer","description":"The page that was read, counting from 1.","example":1,"uniqueKey":"meta.page","typeLabel":"integer"},"size":{"type":"integer","description":"How many items one page holds.","example":20,"uniqueKey":"meta.size","typeLabel":"integer"},"total":{"type":"integer","description":"How many items the whole list has.","example":135,"uniqueKey":"meta.total","typeLabel":"integer"},"limit":{"type":"integer","description":"The same as `size`.","example":20,"uniqueKey":"meta.limit","typeLabel":"integer"},"offset":{"type":"integer","description":"How many items come before this page.","example":0,"uniqueKey":"meta.offset","typeLabel":"integer"},"hasNextPage":{"type":"boolean","example":true,"uniqueKey":"meta.hasNextPage","typeLabel":"boolean"},"hasPreviousPage":{"type":"boolean","example":false,"uniqueKey":"meta.hasPreviousPage","typeLabel":"boolean"},"nextCursor":{"oneOf":[{"type":"string","description":"Pass this as `cursor` to read the next page of a list that is read by cursor. `null` on the last page.","uniqueKey":"meta.nextCursor.oneOf.0","typeLabel":"string"},{"type":"null","description":"Pass this as `cursor` to read the next page of a list that is read by cursor. `null` on the last page.","uniqueKey":"meta.nextCursor.oneOf.1","typeLabel":"null"}],"uniqueKey":"meta.nextCursor","typeLabel":"string | null"},"warnings":{"type":"array","items":{"type":"string","uniqueKey":"meta.warnings.items.[INDEX]","typeLabel":"string"},"description":"Things the call did not do, though it succeeded (for example a table that could not be created just now).","uniqueKey":"meta.warnings","typeLabel":"string[]"}},"uniqueKey":"meta","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"success":true,"data":{"signing":null,"secret":"Example secret"},"meta":{"page":1,"size":20,"total":135,"limit":20,"offset":0,"hasNextPage":true,"hasPreviousPage":false,"nextCursor":"\u003cstring>","warnings":["\u003cstring>"]}}}},"exampleType":"generated"}},"exampleType":"generated"},"25a696b0-87d4-46bf-b422-c7cfe183075e":{"description":"The `Idempotency-Key` header is missing","content":{"application/json":{"schema":{"type":"object","required":["success","message","error"],"additionalProperties":true,"properties":{"success":{"type":"boolean","description":"Always `false` on a failure.","example":false,"isRequired":true,"uniqueKey":"success","typeLabel":"boolean"},"message":{"type":"string","description":"The same text as `error.message`, for a caller that reads one line.","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"error":{"type":"object","required":["code","message","timestamp"],"properties":{"code":{"type":"string","description":"Machine-readable error code.","example":"RESOURCE_NOT_FOUND","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable explanation.","example":"Composition not found","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"timestamp":{"type":"string","format":"date-time","example":"2026-10-15T10:00:00.000Z","isRequired":true,"uniqueKey":"error.timestamp","typeLabel":"string\u003cdate-time>"},"param":{"type":"string","description":"The field that caused the error, when one did.","example":"name","uniqueKey":"error.param","typeLabel":"string"},"docUrl":{"type":"string","description":"Where this error is explained.","uniqueKey":"error.docUrl","typeLabel":"string"},"suggestedAction":{"type":"string","description":"What to do about it.","uniqueKey":"error.suggestedAction","typeLabel":"string"},"retryAfter":{"type":"integer","description":"Seconds to wait before trying again (rate limits). The same number is in the `Retry-After` header.","example":60,"uniqueKey":"error.retryAfter","typeLabel":"integer"},"details":{"type":"object","additionalProperties":true,"description":"More about the error: the fields that failed, a limit that was reached.","uniqueKey":"error.details","typeLabel":"object"},"correlationId":{"type":"string","description":"Quote this when you ask support about the call.","example":"req_123e4567-e89b-12d3-a456-426614174000","uniqueKey":"error.correlationId","typeLabel":"string"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"success":false,"message":"\u003cstring>","error":{"code":"RESOURCE_NOT_FOUND","message":"Composition not found","timestamp":"2026-10-15T10:00:00.000Z","param":"name","docUrl":"\u003cstring>","suggestedAction":"\u003cstring>","retryAfter":60,"details":{},"correlationId":"req_123e4567-e89b-12d3-a456-426614174000"}}}},"exampleType":"generated"}},"exampleType":"generated"},"421155dd-a9f1-4b0d-b2eb-fa976ff5cdb0":{"description":"The API key is missing or invalid","content":{"application/json":{"schema":{"type":"object","required":["success","message","error"],"additionalProperties":true,"properties":{"success":{"type":"boolean","description":"Always `false` on a failure.","example":false,"isRequired":true,"uniqueKey":"success","typeLabel":"boolean"},"message":{"type":"string","description":"The same text as `error.message`, for a caller that reads one line.","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"error":{"type":"object","required":["code","message","timestamp"],"properties":{"code":{"type":"string","description":"Machine-readable error code.","example":"RESOURCE_NOT_FOUND","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable explanation.","example":"Composition not found","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"timestamp":{"type":"string","format":"date-time","example":"2026-10-15T10:00:00.000Z","isRequired":true,"uniqueKey":"error.timestamp","typeLabel":"string\u003cdate-time>"},"param":{"type":"string","description":"The field that caused the error, when one did.","example":"name","uniqueKey":"error.param","typeLabel":"string"},"docUrl":{"type":"string","description":"Where this error is explained.","uniqueKey":"error.docUrl","typeLabel":"string"},"suggestedAction":{"type":"string","description":"What to do about it.","uniqueKey":"error.suggestedAction","typeLabel":"string"},"retryAfter":{"type":"integer","description":"Seconds to wait before trying again (rate limits). The same number is in the `Retry-After` header.","example":60,"uniqueKey":"error.retryAfter","typeLabel":"integer"},"details":{"type":"object","additionalProperties":true,"description":"More about the error: the fields that failed, a limit that was reached.","uniqueKey":"error.details","typeLabel":"object"},"correlationId":{"type":"string","description":"Quote this when you ask support about the call.","example":"req_123e4567-e89b-12d3-a456-426614174000","uniqueKey":"error.correlationId","typeLabel":"string"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"success":false,"message":"\u003cstring>","error":{"code":"RESOURCE_NOT_FOUND","message":"Composition not found","timestamp":"2026-10-15T10:00:00.000Z","param":"name","docUrl":"\u003cstring>","suggestedAction":"\u003cstring>","retryAfter":60,"details":{},"correlationId":"req_123e4567-e89b-12d3-a456-426614174000"}}}},"exampleType":"generated"}},"exampleType":"generated"},"a176b937-811e-407e-9151-3cd7044acd1a":{"description":"The caller does not administer this partner, or the API key has not full access","content":{"application/json":{"schema":{"type":"object","required":["success","message","error"],"additionalProperties":true,"properties":{"success":{"type":"boolean","description":"Always `false` on a failure.","example":false,"isRequired":true,"uniqueKey":"success","typeLabel":"boolean"},"message":{"type":"string","description":"The same text as `error.message`, for a caller that reads one line.","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"error":{"type":"object","required":["code","message","timestamp"],"properties":{"code":{"type":"string","description":"Machine-readable error code.","example":"RESOURCE_NOT_FOUND","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable explanation.","example":"Composition not found","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"timestamp":{"type":"string","format":"date-time","example":"2026-10-15T10:00:00.000Z","isRequired":true,"uniqueKey":"error.timestamp","typeLabel":"string\u003cdate-time>"},"param":{"type":"string","description":"The field that caused the error, when one did.","example":"name","uniqueKey":"error.param","typeLabel":"string"},"docUrl":{"type":"string","description":"Where this error is explained.","uniqueKey":"error.docUrl","typeLabel":"string"},"suggestedAction":{"type":"string","description":"What to do about it.","uniqueKey":"error.suggestedAction","typeLabel":"string"},"retryAfter":{"type":"integer","description":"Seconds to wait before trying again (rate limits). The same number is in the `Retry-After` header.","example":60,"uniqueKey":"error.retryAfter","typeLabel":"integer"},"details":{"type":"object","additionalProperties":true,"description":"More about the error: the fields that failed, a limit that was reached.","uniqueKey":"error.details","typeLabel":"object"},"correlationId":{"type":"string","description":"Quote this when you ask support about the call.","example":"req_123e4567-e89b-12d3-a456-426614174000","uniqueKey":"error.correlationId","typeLabel":"string"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"success":false,"message":"\u003cstring>","error":{"code":"RESOURCE_NOT_FOUND","message":"Composition not found","timestamp":"2026-10-15T10:00:00.000Z","param":"name","docUrl":"\u003cstring>","suggestedAction":"\u003cstring>","retryAfter":60,"details":{},"correlationId":"req_123e4567-e89b-12d3-a456-426614174000"}}}},"exampleType":"generated"}},"exampleType":"generated"},"c6efaf31-a3ac-41de-97b6-c6108105d08b":{"description":"There is no such partner (reported to administrators only)","content":{"application/json":{"schema":{"type":"object","required":["success","message","error"],"additionalProperties":true,"properties":{"success":{"type":"boolean","description":"Always `false` on a failure.","example":false,"isRequired":true,"uniqueKey":"success","typeLabel":"boolean"},"message":{"type":"string","description":"The same text as `error.message`, for a caller that reads one line.","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"error":{"type":"object","required":["code","message","timestamp"],"properties":{"code":{"type":"string","description":"Machine-readable error code.","example":"RESOURCE_NOT_FOUND","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable explanation.","example":"Composition not found","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"timestamp":{"type":"string","format":"date-time","example":"2026-10-15T10:00:00.000Z","isRequired":true,"uniqueKey":"error.timestamp","typeLabel":"string\u003cdate-time>"},"param":{"type":"string","description":"The field that caused the error, when one did.","example":"name","uniqueKey":"error.param","typeLabel":"string"},"docUrl":{"type":"string","description":"Where this error is explained.","uniqueKey":"error.docUrl","typeLabel":"string"},"suggestedAction":{"type":"string","description":"What to do about it.","uniqueKey":"error.suggestedAction","typeLabel":"string"},"retryAfter":{"type":"integer","description":"Seconds to wait before trying again (rate limits). The same number is in the `Retry-After` header.","example":60,"uniqueKey":"error.retryAfter","typeLabel":"integer"},"details":{"type":"object","additionalProperties":true,"description":"More about the error: the fields that failed, a limit that was reached.","uniqueKey":"error.details","typeLabel":"object"},"correlationId":{"type":"string","description":"Quote this when you ask support about the call.","example":"req_123e4567-e89b-12d3-a456-426614174000","uniqueKey":"error.correlationId","typeLabel":"string"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"success":false,"message":"\u003cstring>","error":{"code":"RESOURCE_NOT_FOUND","message":"Composition not found","timestamp":"2026-10-15T10:00:00.000Z","param":"name","docUrl":"\u003cstring>","suggestedAction":"\u003cstring>","retryAfter":60,"details":{},"correlationId":"req_123e4567-e89b-12d3-a456-426614174000"}}}},"exampleType":"generated"}},"exampleType":"generated"},"a5dd24fe-5df3-4148-8074-ec5ca14d45c5":{"description":"Too many changes in a short time. Try again after the Retry-After seconds.","content":{"application/json":{"schema":{"type":"object","required":["success","message","error"],"additionalProperties":true,"properties":{"success":{"type":"boolean","description":"Always `false` on a failure.","example":false,"isRequired":true,"uniqueKey":"success","typeLabel":"boolean"},"message":{"type":"string","description":"The same text as `error.message`, for a caller that reads one line.","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"error":{"type":"object","required":["code","message","timestamp"],"properties":{"code":{"type":"string","description":"Machine-readable error code.","example":"RESOURCE_NOT_FOUND","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable explanation.","example":"Composition not found","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"timestamp":{"type":"string","format":"date-time","example":"2026-10-15T10:00:00.000Z","isRequired":true,"uniqueKey":"error.timestamp","typeLabel":"string\u003cdate-time>"},"param":{"type":"string","description":"The field that caused the error, when one did.","example":"name","uniqueKey":"error.param","typeLabel":"string"},"docUrl":{"type":"string","description":"Where this error is explained.","uniqueKey":"error.docUrl","typeLabel":"string"},"suggestedAction":{"type":"string","description":"What to do about it.","uniqueKey":"error.suggestedAction","typeLabel":"string"},"retryAfter":{"type":"integer","description":"Seconds to wait before trying again (rate limits). The same number is in the `Retry-After` header.","example":60,"uniqueKey":"error.retryAfter","typeLabel":"integer"},"details":{"type":"object","additionalProperties":true,"description":"More about the error: the fields that failed, a limit that was reached.","uniqueKey":"error.details","typeLabel":"object"},"correlationId":{"type":"string","description":"Quote this when you ask support about the call.","example":"req_123e4567-e89b-12d3-a456-426614174000","uniqueKey":"error.correlationId","typeLabel":"string"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"success":false,"message":"\u003cstring>","error":{"code":"RESOURCE_NOT_FOUND","message":"Composition not found","timestamp":"2026-10-15T10:00:00.000Z","param":"name","docUrl":"\u003cstring>","suggestedAction":"\u003cstring>","retryAfter":60,"details":{},"correlationId":"req_123e4567-e89b-12d3-a456-426614174000"}}}},"exampleType":"generated"}},"exampleType":"generated"},"92516ec5-9646-4e94-ad9c-3a5c9c77f21b":{"description":"Signed context is not available on this server right now (ENTRY_CONTEXT_SIGNING_UNAVAILABLE). Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["success","message","error"],"additionalProperties":true,"properties":{"success":{"type":"boolean","description":"Always `false` on a failure.","example":false,"isRequired":true,"uniqueKey":"success","typeLabel":"boolean"},"message":{"type":"string","description":"The same text as `error.message`, for a caller that reads one line.","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"error":{"type":"object","required":["code","message","timestamp"],"properties":{"code":{"type":"string","description":"Machine-readable error code.","example":"RESOURCE_NOT_FOUND","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable explanation.","example":"Composition not found","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"timestamp":{"type":"string","format":"date-time","example":"2026-10-15T10:00:00.000Z","isRequired":true,"uniqueKey":"error.timestamp","typeLabel":"string\u003cdate-time>"},"param":{"type":"string","description":"The field that caused the error, when one did.","example":"name","uniqueKey":"error.param","typeLabel":"string"},"docUrl":{"type":"string","description":"Where this error is explained.","uniqueKey":"error.docUrl","typeLabel":"string"},"suggestedAction":{"type":"string","description":"What to do about it.","uniqueKey":"error.suggestedAction","typeLabel":"string"},"retryAfter":{"type":"integer","description":"Seconds to wait before trying again (rate limits). The same number is in the `Retry-After` header.","example":60,"uniqueKey":"error.retryAfter","typeLabel":"integer"},"details":{"type":"object","additionalProperties":true,"description":"More about the error: the fields that failed, a limit that was reached.","uniqueKey":"error.details","typeLabel":"object"},"correlationId":{"type":"string","description":"Quote this when you ask support about the call.","example":"req_123e4567-e89b-12d3-a456-426614174000","uniqueKey":"error.correlationId","typeLabel":"string"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"success":false,"message":"\u003cstring>","error":{"code":"RESOURCE_NOT_FOUND","message":"Composition not found","timestamp":"2026-10-15T10:00:00.000Z","param":"name","docUrl":"\u003cstring>","suggestedAction":"\u003cstring>","retryAfter":60,"details":{},"correlationId":"req_123e4567-e89b-12d3-a456-426614174000"}}}},"exampleType":"generated"}},"exampleType":"generated"}},"security":{"1e559c4b-0d05-497c-be36-d4830b9d6fd8":{"apiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","scopes":[],"schemeName":"apiKeyAuth"}}},"servers":{"8cdad7e2-72d7-448d-a767-c0ce9882d766":{"url":"https://api.widgetic.com/v1","description":"Production server","variables":{"env":{"default":"production","description":"Environment"},"apiUrl":{"default":"https://api.widgetic.com","description":"API URL"},"apiVersion":{"default":"/v1","description":"API Version path prefix"}}}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"http","scheme":"bearer","bearerFormat":"JWT","scopes":[],"schemeName":"apiKeyAuth"},"schema":{"title":"Bearer Auth","type":"string","isRequired":true,"description":"Bearer authentication header of the form `Bearer \u003ctoken>`, where `\u003ctoken>` is your auth token.","format":"bearer","typeLabel":"string\u003cbearer>","deprecated":false},"schemeName":"apiKeyAuth","name":"Authorization"}],"title":"apiKeyAuth"}]},"originalFileLocation":"openapi/widgetic-api-public.json"},"subdomain":"widgetic","siteName":"Widgetic","title":"Make a secret to sign the context of your embeds - Widgetic","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-11-08T14:06:36.843Z","originalFileLocation":"api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Makes a secret to sign the context of your embeds with, and returns it in secret: keep it now, it is shown once and cannot be read again. Keep it on your server only: whoever holds it can write contexts your compositions accept. Call this again to make a new secret; the one it replaces is still accepted for a day, so that your server can switch without an entry being refused (making another within that day ends the overlap with the first). What signing is for. hands attribution to a widget, which sends it with every entry it saves. The page is yours but the browser is the visitor\u0026#x27;s: anybody can change that attribute and file an entry under another customer\u0026#x27;s id. When your server signs the context, the gateway refuses an entry whose context was changed, and the entries you keep hold attribution your server wrote. How to sign (on your server, for each page you render): 1. Take the context to give the widget. It may hold text and whole numbers only (within ±2^53, written without a fraction or an exponent). 2. Choose when the signature stops being good: widgetic_exp, in seconds since 1970 (UTC), no more than seven days from now. A minute of difference between clocks is forgiven. 3. Write the text to sign, with no spaces except those inside values: widgetic-context.v1.... is the id of the composition in lower case. is the context as JSON with the keys in character-code order (so Z comes before a, and 10 before 9), no spaces, strings escaped as JSON escapes them, and the two keys of the signature left out. 4. Sign that text: HMAC-SHA256 with the 32 bytes the secret stands for (the base64 text after ctxsec_), and write the result as base64url without padding. 5. Give the widget the context with two keys added: widgetic_exp and widgetic_sig (the signature). The whole attribute, the two keys included, stays within the limits of any context: at most 20 keys, 2048 bytes of JSON, strings up to 500 characters. The two keys take two of the 20 keys and 87 bytes of the 2048. A test vector, to check your code against before you rely on it. Secret ctxsec_AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8= (the bytes 0 to 31), composition 7c9e6679-7425-40de-944b-e07fc1f90ae7, widgetic_exp 1792000000 and context {\u0026quot;customerId\u0026quot;:\u0026quot;c_42\u0026quot;,\u0026quot;plan\u0026quot;:\u0026quot;pro\u0026quot;,\u0026quot;seats\u0026quot;:3} sign the text widgetic-context.v1.7c9e6679-7425-40de-944b-e07fc1f90ae7.1792000000.{\u0026quot;customerId\u0026quot;:\u0026quot;c_42\u0026quot;,\u0026quot;plan\u0026quot;:\u0026quot;pro\u0026quot;,\u0026quot;seats\u0026quot;:3} and give the signature j6g7151F54tl9C8oEY9levaYSppHME4fAPZ7WPwL8C8. (The secret is the example\u0026#x27;s, not a real one.) What the gateway does with an entry. When you have a secret, an entry whose context carries a signature is checked: a signature that does not match is refused with 403 CONTEXT_SIGNATURE_INVALID, and one that is past widgetic_exp with 403 CONTEXT_SIGNATURE_EXPIRED. When you also require signatures (updatePartnerEntryContextSigning) an entry whose context carries none is refused with 403 CONTEXT_SIGNATURE_REQUIRED. The two keys are taken out before the entry is stored or announced: your entries and your entry.created events hold the context you wrote. A change you make reaches every part of the gateway within a minute. What it does not do. A signed context that has been seen (a page\u0026#x27;s source is public) can be sent again by anyone until widgetic_exp; when you must not accept the same context twice, put a value that is new for each page view in it (a submissionId you made up) and keep the ones you have seen. The signature covers the entries that reach Widgetic\u0026#x27;s gateway: a row that gets into a table another way (your own code writing straight into a database you brought, or the record calls of the composition\u0026#x27;s owner) does not pass through it, and carries no context. Retry this call with the same Idempotency-Key if its answer was lost: the answer, secret included, is then given again, and no second secret is made. This needs an API key with full access. The caller must be the person who administers the partner, or a Widgetic administrator.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Widgetic\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/widgetic/U_OgbihBw7xJOURr/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/widgetic/U_OgbihBw7xJOURr/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/widgetic/U_OgbihBw7xJOURr/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/widgetic/U_OgbihBw7xJOURr/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/widgetic/U_OgbihBw7xJOURr/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/widgetic/U_OgbihBw7xJOURr/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/widgetic/U_OgbihBw7xJOURr/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/widgetic/U_OgbihBw7xJOURr/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/widgetic/U_OgbihBw7xJOURr/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Make a secret to sign the context of your embeds - Widgetic\">\u003cmeta data-mint-head property=\"og:description\" content=\"Makes a secret to sign the context of your embeds with, and returns it in secret: keep it now, it is shown once and cannot be read again. Keep it on your server only: whoever holds it can write contexts your compositions accept. Call this again to make a new secret; the one it replaces is still accepted for a day, so that your server can switch without an entry being refused (making another within that day ends the overlap with the first). What signing is for. hands attribution to a widget, which sends it with every entry it saves. The page is yours but the browser is the visitor\u0026#x27;s: anybody can change that attribute and file an entry under another customer\u0026#x27;s id. When your server signs the context, the gateway refuses an entry whose context was changed, and the entries you keep hold attribution your server wrote. How to sign (on your server, for each page you render): 1. Take the context to give the widget. It may hold text and whole numbers only (within ±2^53, written without a fraction or an exponent). 2. Choose when the signature stops being good: widgetic_exp, in seconds since 1970 (UTC), no more than seven days from now. A minute of difference between clocks is forgiven. 3. Write the text to sign, with no spaces except those inside values: widgetic-context.v1.... is the id of the composition in lower case. is the context as JSON with the keys in character-code order (so Z comes before a, and 10 before 9), no spaces, strings escaped as JSON escapes them, and the two keys of the signature left out. 4. Sign that text: HMAC-SHA256 with the 32 bytes the secret stands for (the base64 text after ctxsec_), and write the result as base64url without padding. 5. Give the widget the context with two keys added: widgetic_exp and widgetic_sig (the signature). The whole attribute, the two keys included, stays within the limits of any context: at most 20 keys, 2048 bytes of JSON, strings up to 500 characters. The two keys take two of the 20 keys and 87 bytes of the 2048. A test vector, to check your code against before you rely on it. Secret ctxsec_AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8= (the bytes 0 to 31), composition 7c9e6679-7425-40de-944b-e07fc1f90ae7, widgetic_exp 1792000000 and context {\u0026quot;customerId\u0026quot;:\u0026quot;c_42\u0026quot;,\u0026quot;plan\u0026quot;:\u0026quot;pro\u0026quot;,\u0026quot;seats\u0026quot;:3} sign the text widgetic-context.v1.7c9e6679-7425-40de-944b-e07fc1f90ae7.1792000000.{\u0026quot;customerId\u0026quot;:\u0026quot;c_42\u0026quot;,\u0026quot;plan\u0026quot;:\u0026quot;pro\u0026quot;,\u0026quot;seats\u0026quot;:3} and give the signature j6g7151F54tl9C8oEY9levaYSppHME4fAPZ7WPwL8C8. (The secret is the example\u0026#x27;s, not a real one.) What the gateway does with an entry. When you have a secret, an entry whose context carries a signature is checked: a signature that does not match is refused with 403 CONTEXT_SIGNATURE_INVALID, and one that is past widgetic_exp with 403 CONTEXT_SIGNATURE_EXPIRED. When you also require signatures (updatePartnerEntryContextSigning) an entry whose context carries none is refused with 403 CONTEXT_SIGNATURE_REQUIRED. The two keys are taken out before the entry is stored or announced: your entries and your entry.created events hold the context you wrote. A change you make reaches every part of the gateway within a minute. What it does not do. A signed context that has been seen (a page\u0026#x27;s source is public) can be sent again by anyone until widgetic_exp; when you must not accept the same context twice, put a value that is new for each page view in it (a submissionId you made up) and keep the ones you have seen. The signature covers the entries that reach Widgetic\u0026#x27;s gateway: a row that gets into a table another way (your own code writing straight into a database you brought, or the record calls of the composition\u0026#x27;s owner) does not pass through it, and carries no context. Retry this call with the same Idempotency-Key if its answer was lost: the answer, secret included, is then given again, and no second secret is made. This needs an API key with full access. The caller must be the person who administers the partner, or a Widgetic administrator.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Widgetic\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://widgetic.com/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://widgetic.mintlify.site/_mintlify/api/og/v2?division=Partners\u0026amp;title=Make+a+secret+to+sign+the+context+of+your+embeds\u0026amp;description=Makes+a+secret+to+sign+the+%60context%60+of+your+embeds+with%2C+and+returns+it+in+%60secret%60%3A+**keep+it+now%2C+it+is%0Ashown+once**+and+cannot+be+read+again.+Keep+it+on+you\u0026amp;theme=7fb55fb4aca22bb80111c88a\u0026amp;signature=03ad7daaf8ad62e029bcaf0efecd8eae06dcac3a09485b531d22c478a8da07ca\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Make a secret to sign the context of your embeds - Widgetic\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Makes a secret to sign the context of your embeds with, and returns it in secret: keep it now, it is shown once and cannot be read again. Keep it on your server only: whoever holds it can write contexts your compositions accept. Call this again to make a new secret; the one it replaces is still accepted for a day, so that your server can switch without an entry being refused (making another within that day ends the overlap with the first). What signing is for. hands attribution to a widget, which sends it with every entry it saves. The page is yours but the browser is the visitor\u0026#x27;s: anybody can change that attribute and file an entry under another customer\u0026#x27;s id. When your server signs the context, the gateway refuses an entry whose context was changed, and the entries you keep hold attribution your server wrote. How to sign (on your server, for each page you render): 1. Take the context to give the widget. It may hold text and whole numbers only (within ±2^53, written without a fraction or an exponent). 2. Choose when the signature stops being good: widgetic_exp, in seconds since 1970 (UTC), no more than seven days from now. A minute of difference between clocks is forgiven. 3. Write the text to sign, with no spaces except those inside values: widgetic-context.v1.... is the id of the composition in lower case. is the context as JSON with the keys in character-code order (so Z comes before a, and 10 before 9), no spaces, strings escaped as JSON escapes them, and the two keys of the signature left out. 4. Sign that text: HMAC-SHA256 with the 32 bytes the secret stands for (the base64 text after ctxsec_), and write the result as base64url without padding. 5. Give the widget the context with two keys added: widgetic_exp and widgetic_sig (the signature). The whole attribute, the two keys included, stays within the limits of any context: at most 20 keys, 2048 bytes of JSON, strings up to 500 characters. The two keys take two of the 20 keys and 87 bytes of the 2048. A test vector, to check your code against before you rely on it. Secret ctxsec_AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8= (the bytes 0 to 31), composition 7c9e6679-7425-40de-944b-e07fc1f90ae7, widgetic_exp 1792000000 and context {\u0026quot;customerId\u0026quot;:\u0026quot;c_42\u0026quot;,\u0026quot;plan\u0026quot;:\u0026quot;pro\u0026quot;,\u0026quot;seats\u0026quot;:3} sign the text widgetic-context.v1.7c9e6679-7425-40de-944b-e07fc1f90ae7.1792000000.{\u0026quot;customerId\u0026quot;:\u0026quot;c_42\u0026quot;,\u0026quot;plan\u0026quot;:\u0026quot;pro\u0026quot;,\u0026quot;seats\u0026quot;:3} and give the signature j6g7151F54tl9C8oEY9levaYSppHME4fAPZ7WPwL8C8. (The secret is the example\u0026#x27;s, not a real one.) What the gateway does with an entry. When you have a secret, an entry whose context carries a signature is checked: a signature that does not match is refused with 403 CONTEXT_SIGNATURE_INVALID, and one that is past widgetic_exp with 403 CONTEXT_SIGNATURE_EXPIRED. When you also require signatures (updatePartnerEntryContextSigning) an entry whose context carries none is refused with 403 CONTEXT_SIGNATURE_REQUIRED. The two keys are taken out before the entry is stored or announced: your entries and your entry.created events hold the context you wrote. A change you make reaches every part of the gateway within a minute. What it does not do. A signed context that has been seen (a page\u0026#x27;s source is public) can be sent again by anyone until widgetic_exp; when you must not accept the same context twice, put a value that is new for each page view in it (a submissionId you made up) and keep the ones you have seen. The signature covers the entries that reach Widgetic\u0026#x27;s gateway: a row that gets into a table another way (your own code writing straight into a database you brought, or the record calls of the composition\u0026#x27;s owner) does not pass through it, and carries no context. Retry this call with the same Idempotency-Key if its answer was lost: the answer, secret included, is then given again, and no second secret is made. This needs an API key with full access. The caller must be the person who administers the partner, or a Widgetic administrator.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://widgetic.mintlify.site/_mintlify/api/og/v2?division=Partners\u0026amp;title=Make+a+secret+to+sign+the+context+of+your+embeds\u0026amp;description=Makes+a+secret+to+sign+the+%60context%60+of+your+embeds+with%2C+and+returns+it+in+%60secret%60%3A+**keep+it+now%2C+it+is%0Ashown+once**+and+cannot+be+read+again.+Keep+it+on+you\u0026amp;theme=7fb55fb4aca22bb80111c88a\u0026amp;signature=03ad7daaf8ad62e029bcaf0efecd8eae06dcac3a09485b531d22c478a8da07ca\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/widgetic/U_OgbihBw7xJOURr/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Widgetic\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#324E30\">\u003clink data-mint-head rel=\"canonical\" href=\"https://widgetic.com/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://widgetic.com/#organization\",\"name\":\"Widgetic\",\"url\":\"https://widgetic.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/widgetic/Od-pD6ChvIzhY_fR/brand/logo-light.svg?fit=max\u0026auto=format\u0026n=Od-pD6ChvIzhY_fR\u0026q=85\u0026s=c80ce649cc12d9f206a4ea5d3d2d9d31\"}},{\"@type\":\"WebSite\",\"@id\":\"https://widgetic.com#website\",\"name\":\"Widgetic\",\"url\":\"https://widgetic.com\",\"publisher\":{\"@id\":\"https://widgetic.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://widgetic.com/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds#webpage\",\"url\":\"https://widgetic.com/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds\",\"name\":\"Make a secret to sign the context of your embeds\",\"description\":\"Makes a secret to sign the context of your embeds with, and returns it in secret: keep it now, it is shown once and cannot be read again. Keep it on your server only: whoever holds it can write contexts your compositions accept. Call this again to make a new secret; the one it replaces is still accepted for a day, so that your server can switch without an entry being refused (making another within that day ends the overlap with the first). What signing is for. hands attribution to a widget, which sends it with every entry it saves. The page is yours but the browser is the visitor's: anybody can change that attribute and file an entry under another customer's id. When your server signs the context, the gateway refuses an entry whose context was changed, and the entries you keep hold attribution your server wrote. How to sign (on your server, for each page you render): 1. Take the context to give the widget. It may hold text and whole numbers only (within ±2^53, written without a fraction or an exponent). 2. Choose when the signature stops being good: widgetic_exp, in seconds since 1970 (UTC), no more than seven days from now. A minute of difference between clocks is forgiven. 3. Write the text to sign, with no spaces except those inside values: widgetic-context.v1.... is the id of the composition in lower case. is the context as JSON with the keys in character-code order (so Z comes before a, and 10 before 9), no spaces, strings escaped as JSON escapes them, and the two keys of the signature left out. 4. Sign that text: HMAC-SHA256 with the 32 bytes the secret stands for (the base64 text after ctxsec_), and write the result as base64url without padding. 5. Give the widget the context with two keys added: widgetic_exp and widgetic_sig (the signature). The whole attribute, the two keys included, stays within the limits of any context: at most 20 keys, 2048 bytes of JSON, strings up to 500 characters. The two keys take two of the 20 keys and 87 bytes of the 2048. A test vector, to check your code against before you rely on it. Secret ctxsec_AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8= (the bytes 0 to 31), composition 7c9e6679-7425-40de-944b-e07fc1f90ae7, widgetic_exp 1792000000 and context {\\\"customerId\\\":\\\"c_42\\\",\\\"plan\\\":\\\"pro\\\",\\\"seats\\\":3} sign the text widgetic-context.v1.7c9e6679-7425-40de-944b-e07fc1f90ae7.1792000000.{\\\"customerId\\\":\\\"c_42\\\",\\\"plan\\\":\\\"pro\\\",\\\"seats\\\":3} and give the signature j6g7151F54tl9C8oEY9levaYSppHME4fAPZ7WPwL8C8. (The secret is the example's, not a real one.) What the gateway does with an entry. When you have a secret, an entry whose context carries a signature is checked: a signature that does not match is refused with 403 CONTEXT_SIGNATURE_INVALID, and one that is past widgetic_exp with 403 CONTEXT_SIGNATURE_EXPIRED. When you also require signatures (updatePartnerEntryContextSigning) an entry whose context carries none is refused with 403 CONTEXT_SIGNATURE_REQUIRED. The two keys are taken out before the entry is stored or announced: your entries and your entry.created events hold the context you wrote. A change you make reaches every part of the gateway within a minute. What it does not do. A signed context that has been seen (a page's source is public) can be sent again by anyone until widgetic_exp; when you must not accept the same context twice, put a value that is new for each page view in it (a submissionId you made up) and keep the ones you have seen. The signature covers the entries that reach Widgetic's gateway: a row that gets into a table another way (your own code writing straight into a database you brought, or the record calls of the composition's owner) does not pass through it, and carries no context. Retry this call with the same Idempotency-Key if its answer was lost: the answer, secret included, is then given again, and no second secret is made. This needs an API key with full access. The caller must be the person who administers the partner, or a Widgetic administrator.\",\"dateModified\":\"2026-11-08T14:06:36.843Z\",\"isPartOf\":{\"@id\":\"https://widgetic.com#website\"},\"breadcrumb\":{\"@id\":\"https://widgetic.com/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://widgetic.com/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Partners\",\"item\":\"https://widgetic.com/api-reference/partners/list-the-workflows-a-partner-offers-as-places-to-start\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Make a secret to sign the context of your embeds\",\"item\":\"https://widgetic.com/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://widgetic.com/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds#apireference\",\"headline\":\"Make a secret to sign the context of your embeds\",\"name\":\"Make a secret to sign the context of your embeds\",\"description\":\"Makes a secret to sign the context of your embeds with, and returns it in secret: keep it now, it is shown once and cannot be read again. Keep it on your server only: whoever holds it can write contexts your compositions accept. Call this again to make a new secret; the one it replaces is still accepted for a day, so that your server can switch without an entry being refused (making another within that day ends the overlap with the first). What signing is for. hands attribution to a widget, which sends it with every entry it saves. The page is yours but the browser is the visitor's: anybody can change that attribute and file an entry under another customer's id. When your server signs the context, the gateway refuses an entry whose context was changed, and the entries you keep hold attribution your server wrote. How to sign (on your server, for each page you render): 1. Take the context to give the widget. It may hold text and whole numbers only (within ±2^53, written without a fraction or an exponent). 2. Choose when the signature stops being good: widgetic_exp, in seconds since 1970 (UTC), no more than seven days from now. A minute of difference between clocks is forgiven. 3. Write the text to sign, with no spaces except those inside values: widgetic-context.v1.... is the id of the composition in lower case. is the context as JSON with the keys in character-code order (so Z comes before a, and 10 before 9), no spaces, strings escaped as JSON escapes them, and the two keys of the signature left out. 4. Sign that text: HMAC-SHA256 with the 32 bytes the secret stands for (the base64 text after ctxsec_), and write the result as base64url without padding. 5. Give the widget the context with two keys added: widgetic_exp and widgetic_sig (the signature). The whole attribute, the two keys included, stays within the limits of any context: at most 20 keys, 2048 bytes of JSON, strings up to 500 characters. The two keys take two of the 20 keys and 87 bytes of the 2048. A test vector, to check your code against before you rely on it. Secret ctxsec_AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8= (the bytes 0 to 31), composition 7c9e6679-7425-40de-944b-e07fc1f90ae7, widgetic_exp 1792000000 and context {\\\"customerId\\\":\\\"c_42\\\",\\\"plan\\\":\\\"pro\\\",\\\"seats\\\":3} sign the text widgetic-context.v1.7c9e6679-7425-40de-944b-e07fc1f90ae7.1792000000.{\\\"customerId\\\":\\\"c_42\\\",\\\"plan\\\":\\\"pro\\\",\\\"seats\\\":3} and give the signature j6g7151F54tl9C8oEY9levaYSppHME4fAPZ7WPwL8C8. (The secret is the example's, not a real one.) What the gateway does with an entry. When you have a secret, an entry whose context carries a signature is checked: a signature that does not match is refused with 403 CONTEXT_SIGNATURE_INVALID, and one that is past widgetic_exp with 403 CONTEXT_SIGNATURE_EXPIRED. When you also require signatures (updatePartnerEntryContextSigning) an entry whose context carries none is refused with 403 CONTEXT_SIGNATURE_REQUIRED. The two keys are taken out before the entry is stored or announced: your entries and your entry.created events hold the context you wrote. A change you make reaches every part of the gateway within a minute. What it does not do. A signed context that has been seen (a page's source is public) can be sent again by anyone until widgetic_exp; when you must not accept the same context twice, put a value that is new for each page view in it (a submissionId you made up) and keep the ones you have seen. The signature covers the entries that reach Widgetic's gateway: a row that gets into a table another way (your own code writing straight into a database you brought, or the record calls of the composition's owner) does not pass through it, and carries no context. Retry this call with the same Idempotency-Key if its answer was lost: the answer, secret included, is then given again, and no second secret is made. This needs an API key with full access. The caller must be the person who administers the partner, or a Widgetic administrator.\",\"url\":\"https://widgetic.com/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds\",\"mainEntityOfPage\":{\"@id\":\"https://widgetic.com/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds#webpage\"},\"dateModified\":\"2026-11-08T14:06:36.843Z\",\"publisher\":{\"@id\":\"https://widgetic.com/#organization\"},\"isPartOf\":{\"@id\":\"https://widgetic.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Widgetic\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"Widgetic\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds.md","siteName":"Widgetic","nav":{"global":null,"tabs":[{"tab":"Documentation","pages":[{"title":"Documentation","href":"/docs/introduction"}]},{"tab":"API Reference","groups":[{"group":"API Reference","pages":[{"title":"API Reference Introduction","href":"/api-reference/introduction"},{"title":"Pagination","href":"/api-reference/pagination"},{"title":"Usage Limits","href":"/api-reference/usage-limits"},{"title":"Errors","href":"/api-reference/errors"}]},{"group":"Public Embed","pages":[{"title":"Append a visitor entry through the gateway","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /embed/compositions/{compositionId}/entries/{table}","href":"/api-reference/public-embed/append-a-visitor-entry-through-the-gateway"},{"title":"Read the published Workflow of an embed","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /embed/workflows/{workflowId}","href":"/api-reference/public-embed/read-the-published-workflow-of-an-embed"},{"title":"Read one published version of a Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /embed/workflows/{workflowId}/versions/{versionId}","href":"/api-reference/public-embed/read-one-published-version-of-a-workflow"},{"title":"Report what visitors did in a Workflow, as counts","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /embed/workflows/{workflowId}/events","href":"/api-reference/public-embed/report-what-visitors-did-in-a-workflow-as-counts"},{"title":"Show a published Workflow in a page of its own","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /embed/workflows/{workflowId}/frame","href":"/api-reference/public-embed/show-a-published-workflow-in-a-page-of-its-own"},{"title":"Resolve a composition UUID to a published widget URL","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /embed/compositions/{compositionId}","href":"/api-reference/public-embed/resolve-a-composition-uuid-to-a-published-widget-url"},{"title":"Embed a published composition with its saved values","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /embed/compositions/{compositionId}/frame","href":"/api-reference/public-embed/embed-a-published-composition-with-its-saved-values"},{"title":"Batch-check whether compositions are currently served for embed","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /embed/compositions/status","href":"/api-reference/public-embed/batch-check-whether-compositions-are-currently-served-for-embed"},{"title":"Call a gateway operation of an adapter a published widget uses","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /embed/compositions/{compositionId}/adapters/{adapterId}/{operation}","href":"/api-reference/public-embed/call-a-gateway-operation-of-an-adapter-a-published-widget-uses"},{"title":"Send the file a visitor chose through the upload adapter of a published widget","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /embed/compositions/{compositionId}/adapters/upload/files/{ticket}","href":"/api-reference/public-embed/send-the-file-a-visitor-chose-through-the-upload-adapter-of-a-published-widget"}]},{"group":"Workflows","pages":[{"title":"List the compositions a workflow can show, and what each can do","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /workspaces/{workspaceId}/workflows/composition-options","href":"/api-reference/workflows/list-the-compositions-a-workflow-can-show-and-what-each-can-do"},{"title":"List the starting points for a new Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /workspaces/{workspaceId}/workflows/presets","href":"/api-reference/workflows/list-the-starting-points-for-a-new-workflow"},{"title":"Start a Workflow from a starting point","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /workspaces/{workspaceId}/workflows/from-preset","href":"/api-reference/workflows/start-a-workflow-from-a-starting-point"},{"title":"List the Workflows of a Workspace","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /workspaces/{workspaceId}/workflows","href":"/api-reference/workflows/list-the-workflows-of-a-workspace"},{"title":"Create a Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /workspaces/{workspaceId}/workflows","href":"/api-reference/workflows/create-a-workflow"},{"title":"Get a Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /workspaces/{workspaceId}/workflows/{workflowId}","href":"/api-reference/workflows/get-a-workflow"},{"title":"Save the Draft of a Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /workspaces/{workspaceId}/workflows/{workflowId}","href":"/api-reference/workflows/save-the-draft-of-a-workflow"},{"title":"Delete a Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /workspaces/{workspaceId}/workflows/{workflowId}","href":"/api-reference/workflows/delete-a-workflow"},{"title":"Duplicate a Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /workspaces/{workspaceId}/workflows/{workflowId}/duplicate","href":"/api-reference/workflows/duplicate-a-workflow"},{"title":"Publish the Draft of a Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /workspaces/{workspaceId}/workflows/{workflowId}/publish","href":"/api-reference/workflows/publish-the-draft-of-a-workflow"},{"title":"Discard the Unpublished Changes of a Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /workspaces/{workspaceId}/workflows/{workflowId}/discard","href":"/api-reference/workflows/discard-the-unpublished-changes-of-a-workflow"},{"title":"List the Published Versions of a Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /workspaces/{workspaceId}/workflows/{workflowId}/versions","href":"/api-reference/workflows/list-the-published-versions-of-a-workflow"},{"title":"Get a Published Version of a Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /workspaces/{workspaceId}/workflows/{workflowId}/versions/{versionId}","href":"/api-reference/workflows/get-a-published-version-of-a-workflow"},{"title":"Restore a Version of a Workflow into the Draft","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /workspaces/{workspaceId}/workflows/{workflowId}/versions/{versionId}/restore","href":"/api-reference/workflows/restore-a-version-of-a-workflow-into-the-draft"},{"title":"Pause a Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /workspaces/{workspaceId}/workflows/{workflowId}/pause","href":"/api-reference/workflows/pause-a-workflow"},{"title":"Resume a Paused Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /workspaces/{workspaceId}/workflows/{workflowId}/resume","href":"/api-reference/workflows/resume-a-paused-workflow"},{"title":"Archive a Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /workspaces/{workspaceId}/workflows/{workflowId}/archive","href":"/api-reference/workflows/archive-a-workflow"},{"title":"Unarchive a Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /workspaces/{workspaceId}/workflows/{workflowId}/unarchive","href":"/api-reference/workflows/unarchive-a-workflow"},{"title":"Get what Visitors Did in a Workflow","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /workspaces/{workspaceId}/workflows/{workflowId}/stats","href":"/api-reference/workflows/get-what-visitors-did-in-a-workflow"}]},{"group":"Partners","pages":[{"title":"List the workflows a partner offers as places to start","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/workflow-presets","href":"/api-reference/partners/list-the-workflows-a-partner-offers-as-places-to-start"},{"title":"Offer a workflow as a place to start, or replace what a key offers","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /partners/{partnerId}/workflow-presets/{key}","href":"/api-reference/partners/offer-a-workflow-as-a-place-to-start-or-replace-what-a-key-offers"},{"title":"Stop offering a workflow as a place to start","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /partners/{partnerId}/workflow-presets/{key}","href":"/api-reference/partners/stop-offering-a-workflow-as-a-place-to-start"},{"title":"Find the partner you administer","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/mine","href":"/api-reference/partners/find-the-partner-you-administer"},{"title":"Get partner credit balance","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/credits/balance","href":"/api-reference/partners/get-partner-credit-balance"},{"title":"Get partner credit transaction history","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/credits/transactions","href":"/api-reference/partners/get-partner-credit-transaction-history"},{"title":"Buy extra credits for a partner","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /partners/{partnerId}/credits/extra-invoice","href":"/api-reference/partners/buy-extra-credits-for-a-partner"},{"title":"Get comprehensive partner billing overview","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/billing-overview","href":"/api-reference/partners/get-comprehensive-partner-billing-overview"},{"title":"Get a partner's contract","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/contract","href":"/api-reference/partners/get-a-partners-contract"},{"title":"Get where a partner's uploaded files are stored","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/storage","href":"/api-reference/partners/get-where-a-partners-uploaded-files-are-stored"},{"title":"Set where a partner's uploaded files are stored","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /partners/{partnerId}/storage","href":"/api-reference/partners/set-where-a-partners-uploaded-files-are-stored"},{"title":"Stop storing a partner's uploaded files in its own bucket","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /partners/{partnerId}/storage","href":"/api-reference/partners/stop-storing-a-partners-uploaded-files-in-its-own-bucket"},{"title":"Check that a partner's storage destination still works","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /partners/{partnerId}/storage/verify","href":"/api-reference/partners/check-that-a-partners-storage-destination-still-works"},{"title":"List the widgets a partner offers as presets","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/presets","href":"/api-reference/partners/list-the-widgets-a-partner-offers-as-presets"},{"title":"Make a widget a preset, or replace a preset","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /partners/{partnerId}/presets/{key}","href":"/api-reference/partners/make-a-widget-a-preset-or-replace-a-preset"},{"title":"Take a widget off the partner's presets","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /partners/{partnerId}/presets/{key}","href":"/api-reference/partners/take-a-widget-off-the-partners-presets"},{"title":"Read partner-wide design defaults","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/design-defaults","href":"/api-reference/partners/read-partner-wide-design-defaults"},{"title":"Set or clear partner-wide design defaults","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /partners/{partnerId}/design-defaults","href":"/api-reference/partners/set-or-clear-partner-wide-design-defaults"},{"title":"What a partner's customers store","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/storage/usage","href":"/api-reference/partners/what-a-partners-customers-store"},{"title":"What was done with a partner's published widgets","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/analytics/summary","href":"/api-reference/partners/what-was-done-with-a-partners-published-widgets"},{"title":"What each managed user's widgets did","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/analytics/managed-users","href":"/api-reference/partners/what-each-managed-users-widgets-did"},{"title":"Which widgets were viewed the most","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/analytics/top-widgets","href":"/api-reference/partners/which-widgets-were-viewed-the-most"},{"title":"What was done with a partner's widgets, day by day","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/analytics/timeline","href":"/api-reference/partners/what-was-done-with-a-partners-widgets-day-by-day"},{"title":"What your partner account was told","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/notifications","href":"/api-reference/partners/what-your-partner-account-was-told"},{"title":"How your notifications reached you","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/notifications/deliveries","href":"/api-reference/partners/how-your-notifications-reached-you"},{"title":"Where your notifications go","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/notifications/settings","href":"/api-reference/partners/where-your-notifications-go"},{"title":"Choose where your notifications go","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /partners/{partnerId}/notifications/settings","href":"/api-reference/partners/choose-where-your-notifications-go"},{"title":"Make a new secret for your webhook","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /partners/{partnerId}/notifications/webhook-secret","href":"/api-reference/partners/make-a-new-secret-for-your-webhook"},{"title":"Send a webhook delivery again","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /partners/{partnerId}/notifications/deliveries/{deliveryId}/replay","href":"/api-reference/partners/send-a-webhook-delivery-again"},{"title":"Send a test event to your webhook","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /partners/{partnerId}/notifications/test-event","href":"/api-reference/partners/send-a-test-event-to-your-webhook"},{"title":"See how the context of your embeds is signed","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/entry-context-signing","href":"/api-reference/partners/see-how-the-context-of-your-embeds-is-signed"},{"title":"Require a signed context, or stop requiring it","description":"Chooses what the gateway does with an entry whose `context` carries no valid signature.\n\nWith `required: false` (the default) an entry that carries a signature is checked and refused when the\nsignature is wrong or out of date, and an entry that carries none is accepted, as it always was. With\n`required: true` an entry without a valid signature is refused with 403 `CONTEXT_SIGNATURE_REQUIRED`: use it\nonce every page of yours that embeds a composition signs its context.\n\nSignatures cannot be required before you have made a secret (`rotatePartnerEntryContextSecret`): the answer\nis 409, so that you cannot lock your own compositions out of taking entries. The change reaches every part of\nthe gateway within a minute.\n\nSaving the same choice twice leaves the same state, so a retry is harmless and `Idempotency-Key` is optional.\nThis needs an API key with full access. The caller must be the person who administers the partner, or a\nWidgetic administrator.\n","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /partners/{partnerId}/entry-context-signing","href":"/api-reference/partners/require-a-signed-context-or-stop-requiring-it"},{"title":"Make a secret to sign the context of your embeds","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /partners/{partnerId}/entry-context-signing/secret","href":"/api-reference/partners/make-a-secret-to-sign-the-context-of-your-embeds"},{"title":"See the Neon database a partner keeps the data of its compositions in","description":"Returns the database set with `setPartnerDataDatabase`, without its password: the host, the database and the\nrole, when it last passed the check, and why the latest re-check failed if it did. Responds 404 while the\npartner has no database of its own, which means the data of its compositions is kept by Widgetic.\n\nThe caller must be the person who administers the partner (an API key of that account works, with the\n`partner:read` scope), or a Widgetic administrator.\n","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/data-database","href":"/api-reference/partners/see-the-neon-database-a-partner-keeps-the-data-of-its-compositions-in"},{"title":"Keep the data of a partner's compositions in a Neon database of its own","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /partners/{partnerId}/data-database","href":"/api-reference/partners/keep-the-data-of-a-partners-compositions-in-a-neon-database-of-its-own"},{"title":"Stop keeping the data of a partner's compositions in its own database","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /partners/{partnerId}/data-database","href":"/api-reference/partners/stop-keeping-the-data-of-a-partners-compositions-in-its-own-database"},{"title":"Check that a partner's own database still works","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /partners/{partnerId}/data-database/verify","href":"/api-reference/partners/check-that-a-partners-own-database-still-works"},{"title":"See which adapter keys a partner has connected","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /partners/{partnerId}/adapter-connections","href":"/api-reference/partners/see-which-adapter-keys-a-partner-has-connected"},{"title":"Connect an adapter key to a partner","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /partners/{partnerId}/adapter-connections/{adapterId}/{credentialKey}","href":"/api-reference/partners/connect-an-adapter-key-to-a-partner"},{"title":"Remove an adapter key from a partner","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /partners/{partnerId}/adapter-connections/{adapterId}/{credentialKey}","href":"/api-reference/partners/remove-an-adapter-key-from-a-partner"},{"title":"Confirm a partner's adapter address with the code that was emailed to it","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /partners/{partnerId}/adapter-connections/{adapterId}/{credentialKey}/confirm","href":"/api-reference/partners/confirm-a-partners-adapter-address-with-the-code-that-was-emailed-to-it"}]},{"group":"Widgets","pages":[{"title":"List Widgets","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /widgets","href":"/api-reference/widgets/list-widgets"},{"title":"Create Widget","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /widgets","href":"/api-reference/widgets/create-widget"},{"title":"Create a composition for a widget in one call","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /widgets/{id}/composition","href":"/api-reference/widgets/create-a-composition-for-a-widget-in-one-call"},{"title":"Get Widgets Batch","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /widgets/batch","href":"/api-reference/widgets/get-widgets-batch"}]},{"group":"Users","pages":[{"title":"List the websites allowed to show your widgets","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /users/{id}/workspace/domains","href":"/api-reference/users/list-the-websites-allowed-to-show-your-widgets"},{"title":"Allow a website to show your widgets","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /users/{id}/workspace/domains","href":"/api-reference/users/allow-a-website-to-show-your-widgets"},{"title":"Change a website on your list","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /users/{id}/workspace/domains/{domainId}","href":"/api-reference/users/change-a-website-on-your-list"},{"title":"Stop allowing a website to show your widgets","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /users/{id}/workspace/domains/{domainId}","href":"/api-reference/users/stop-allowing-a-website-to-show-your-widgets"},{"title":"List the API keys of an account","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /users/{id}/keys","href":"/api-reference/users/list-the-api-keys-of-an-account"},{"title":"Create an API key","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /users/{id}/keys","href":"/api-reference/users/create-an-api-key"},{"title":"Rename an API key, or switch it off or on","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /users/{id}/keys/{keyId}","href":"/api-reference/users/rename-an-api-key-or-switch-it-off-or-on"},{"title":"Delete an API key","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /users/{id}/keys/{keyId}","href":"/api-reference/users/delete-an-api-key"},{"title":"Read what an API key was used for","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /users/{id}/api-keys/{keyId}/logs","href":"/api-reference/users/read-what-an-api-key-was-used-for"},{"title":"See which adapter keys an account has connected","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /users/{userId}/adapter-connections","href":"/api-reference/users/see-which-adapter-keys-an-account-has-connected"},{"title":"Connect an adapter key to an account","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /users/{userId}/adapter-connections/{adapterId}/{credentialKey}","href":"/api-reference/users/connect-an-adapter-key-to-an-account"},{"title":"Remove an adapter key from an account","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /users/{userId}/adapter-connections/{adapterId}/{credentialKey}","href":"/api-reference/users/remove-an-adapter-key-from-an-account"},{"title":"Confirm an adapter address with the code that was emailed to it","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /users/{userId}/adapter-connections/{adapterId}/{credentialKey}/confirm","href":"/api-reference/users/confirm-an-adapter-address-with-the-code-that-was-emailed-to-it"}]},{"group":"Uploads","pages":[{"title":"List the account's uploads","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /uploads","href":"/api-reference/uploads/list-the-accounts-uploads"},{"title":"Upload a file","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /uploads","href":"/api-reference/uploads/upload-a-file"},{"title":"Upload size limits and accepted file types","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /uploads/limits","href":"/api-reference/uploads/upload-size-limits-and-accepted-file-types"},{"title":"Get an upload by id","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /uploads/{id}","href":"/api-reference/uploads/get-an-upload-by-id"},{"title":"Delete an upload","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /uploads/{id}","href":"/api-reference/uploads/delete-an-upload"}]},{"group":"Tokens","pages":[{"title":"Validate current authentication token","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /tokens/validate","href":"/api-reference/tokens/validate-current-authentication-token"}]},{"group":"Operations","pages":[{"title":"Get operation status","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /operations/{id}","href":"/api-reference/operations/get-operation-status"}]},{"group":"Managed Users","pages":[{"title":"Get Managed Users","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /managed-users","href":"/api-reference/managed-users/get-managed-users"},{"title":"Create Managed User","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /managed-users","href":"/api-reference/managed-users/create-managed-user"},{"title":"Get Managed Users By Manager","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /users/{managerId}/managed-users","href":"/api-reference/managed-users/get-managed-users-by-manager"},{"title":"Get Managed User By ID","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /managed-users/{id}","href":"/api-reference/managed-users/get-managed-user-by-id"},{"title":"Update Managed User","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /managed-users/{id}","href":"/api-reference/managed-users/update-managed-user"},{"title":"Delete Managed User","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /managed-users/{id}","href":"/api-reference/managed-users/delete-managed-user"},{"title":"Create an editor session for a managed user","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /managed-users/{id}/editor-sessions","href":"/api-reference/managed-users/create-an-editor-session-for-a-managed-user"},{"title":"End every editor session of a managed user","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /managed-users/{id}/editor-sessions","href":"/api-reference/managed-users/end-every-editor-session-of-a-managed-user"},{"title":"End one editor session of a managed user","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /managed-users/{id}/editor-sessions/{sessionId}","href":"/api-reference/managed-users/end-one-editor-session-of-a-managed-user"},{"title":"What a managed user's editor sessions spent","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /managed-users/{id}/usage","href":"/api-reference/managed-users/what-a-managed-users-editor-sessions-spent"},{"title":"Give a managed user a copy of one of your presets","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /managed-users/{id}/presets/{key}/copy","href":"/api-reference/managed-users/give-a-managed-user-a-copy-of-one-of-your-presets"},{"title":"Create a composition from one of your presets in one call","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /managed-users/{id}/presets/{key}/composition","href":"/api-reference/managed-users/create-a-composition-from-one-of-your-presets-in-one-call"},{"title":"Read monthly credit cap and usage for one managed user","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /managed-users/{id}/limits","href":"/api-reference/managed-users/read-monthly-credit-cap-and-usage-for-one-managed-user"},{"title":"Set or clear the monthly credit cap for one managed user","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /managed-users/{id}/limits","href":"/api-reference/managed-users/set-or-clear-the-monthly-credit-cap-for-one-managed-user"},{"title":"Storage used by one managed user's uploads","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /managed-users/{id}/storage-usage","href":"/api-reference/managed-users/storage-used-by-one-managed-users-uploads"},{"title":"List entries across a managed user's compositions","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /managed-users/{id}/entries","href":"/api-reference/managed-users/list-entries-across-a-managed-users-compositions"},{"title":"Read design defaults for one managed user","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /managed-users/{id}/design-defaults","href":"/api-reference/managed-users/read-design-defaults-for-one-managed-user"},{"title":"Set or clear design defaults for one managed user","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /managed-users/{id}/design-defaults","href":"/api-reference/managed-users/set-or-clear-design-defaults-for-one-managed-user"}]},{"group":"Invoices","pages":[{"title":"List a partner's invoices","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /invoices/partner/{partnerId}","href":"/api-reference/invoices/list-a-partners-invoices"}]},{"group":"Entitlements","pages":[{"title":"Get partner entitlements","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /entitlements/partners/{partnerId}","href":"/api-reference/entitlements/get-partner-entitlements"},{"title":"Get managed user entitlements","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /entitlements/managed-users/{managedUserId}","href":"/api-reference/entitlements/get-managed-user-entitlements"}]},{"group":"Credits","pages":[{"title":"Get an account's credit balance","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /credits/user/{userId}/balance","href":"/api-reference/credits/get-an-accounts-credit-balance"},{"title":"List an account's credit ledger","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /credits/user/{userId}/transactions","href":"/api-reference/credits/list-an-accounts-credit-ledger"}]},{"group":"Compositions","pages":[{"title":"Get All Compositions","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions","href":"/api-reference/compositions/get-all-compositions"},{"title":"Create Composition","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /compositions","href":"/api-reference/compositions/create-composition"},{"title":"Duplicate Composition","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /compositions/{id}/duplicate","href":"/api-reference/compositions/duplicate-composition"},{"title":"Get Composition Versions","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/versions","href":"/api-reference/compositions/get-composition-versions"},{"title":"Update Composition Status","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /compositions/{id}/status","href":"/api-reference/compositions/update-composition-status"},{"title":"Get Composition","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}","href":"/api-reference/compositions/get-composition"},{"title":"Update Composition","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /compositions/{id}","href":"/api-reference/compositions/update-composition"},{"title":"Delete Composition","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /compositions/{id}","href":"/api-reference/compositions/delete-composition"},{"title":"Get Composition Design","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/design","href":"/api-reference/compositions/get-composition-design"},{"title":"Get Current Content","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/content","href":"/api-reference/compositions/get-current-content"},{"title":"Set Dynamic Content","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /compositions/{id}/content","href":"/api-reference/compositions/set-dynamic-content"},{"title":"Get Composition Embed Settings","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/embed-settings","href":"/api-reference/compositions/get-composition-embed-settings"},{"title":"Get Composition Preview","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/preview","href":"/api-reference/compositions/get-composition-preview"},{"title":"Get All Records From Composition Database Table","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/database/{table}","href":"/api-reference/compositions/get-all-records-from-composition-database-table"},{"title":"Create Record In Composition Database","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /compositions/{id}/database/{table}","href":"/api-reference/compositions/create-record-in-composition-database"},{"title":"Get Record From Composition Database","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/database/{table}/{recordId}","href":"/api-reference/compositions/get-record-from-composition-database"},{"title":"Update Record In Composition Database","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /compositions/{id}/database/{table}/{recordId}","href":"/api-reference/compositions/update-record-in-composition-database"},{"title":"Delete Record From Composition Database","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /compositions/{id}/database/{table}/{recordId}","href":"/api-reference/compositions/delete-record-from-composition-database"},{"title":"Describe What a Composition Keeps","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/entries","href":"/api-reference/compositions/describe-what-a-composition-keeps"},{"title":"Read the Entries of a Composition's Table","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/entries/{table}","href":"/api-reference/compositions/read-the-entries-of-a-compositions-table"},{"title":"Add a content list item","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /compositions/{id}/content/{list}/items","href":"/api-reference/compositions/add-a-content-list-item"},{"title":"Delete a content list item","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /compositions/{id}/content/{list}/items/{itemId}","href":"/api-reference/compositions/delete-a-content-list-item"},{"title":"Update a content list item","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json patch /compositions/{id}/content/{list}/items/{itemId}","href":"/api-reference/compositions/update-a-content-list-item"},{"title":"Read the composition data source binding","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/data-source","href":"/api-reference/compositions/read-the-composition-data-source-binding"},{"title":"Bind a public JSON data source for embed refresh","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /compositions/{id}/data-source","href":"/api-reference/compositions/bind-a-public-json-data-source-for-embed-refresh"},{"title":"Remove the composition data source binding","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /compositions/{id}/data-source","href":"/api-reference/compositions/remove-the-composition-data-source-binding"},{"title":"Validate Content","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /compositions/{id}/content/validate","href":"/api-reference/compositions/validate-content"},{"title":"Get Content Schema","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/schema/content","href":"/api-reference/compositions/get-content-schema"},{"title":"Get Design Schema","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/schema/design","href":"/api-reference/compositions/get-design-schema"},{"title":"Get Embed Schema","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/schema/embed","href":"/api-reference/compositions/get-embed-schema"},{"title":"Check Composition Access","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/access","href":"/api-reference/compositions/check-composition-access"},{"title":"Get Compositions Batch","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /compositions/batch","href":"/api-reference/compositions/get-compositions-batch"},{"title":"List composition entry items with paging and filters","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/entries/{table}/items","href":"/api-reference/compositions/list-composition-entry-items-with-paging-and-filters"},{"title":"Delete composition entry items by id or host context","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /compositions/{id}/entries/{table}/items","href":"/api-reference/compositions/delete-composition-entry-items-by-id-or-host-context"},{"title":"Export composition entry items","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/entries/{table}/export","href":"/api-reference/compositions/export-composition-entry-items"},{"title":"See the documents a widget's AI answers from","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /compositions/{id}/adapters/ai-answers/knowledge","href":"/api-reference/compositions/see-the-documents-a-widgets-ai-answers-from"},{"title":"Add a document for a widget's AI to answer from","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /compositions/{id}/adapters/ai-answers/knowledge/documents","href":"/api-reference/compositions/add-a-document-for-a-widgets-ai-to-answer-from"},{"title":"Add a text file or a picture of a document (a PDF once PDFs are read) for a widget's AI to answer from","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /compositions/{id}/adapters/ai-answers/knowledge/documents/file","href":"/api-reference/compositions/add-a-text-file-or-a-picture-of-a-document-a-pdf-once-pdfs-are-read-for-a-widgets-ai-to-answer-from"},{"title":"Remove a document from a widget's knowledge base","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /compositions/{id}/adapters/ai-answers/knowledge/documents/{documentId}","href":"/api-reference/compositions/remove-a-document-from-a-widgets-knowledge-base"}]},{"group":"Canvases","pages":[{"title":"Get All Canvases","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /canvases","href":"/api-reference/canvases/get-all-canvases"},{"title":"Create Canvas","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /canvases","href":"/api-reference/canvases/create-canvas"},{"title":"Get Canvas","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /canvases/{id}","href":"/api-reference/canvases/get-canvas"},{"title":"Update Canvas","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /canvases/{id}","href":"/api-reference/canvases/update-canvas"},{"title":"Delete Canvas","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /canvases/{id}","href":"/api-reference/canvases/delete-canvas"}]},{"group":"Brand Kit","pages":[{"title":"The Brand Kit of the current workspace","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json get /brand-kit","href":"/api-reference/brand-kit/the-brand-kit-of-the-current-workspace"},{"title":"Save Brand Kit tokens","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json put /brand-kit","href":"/api-reference/brand-kit/save-brand-kit-tokens"},{"title":"Reset the Brand Kit to the default","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /brand-kit","href":"/api-reference/brand-kit/reset-the-brand-kit-to-the-default"},{"title":"Change part of the Brand Kit","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json patch /brand-kit","href":"/api-reference/brand-kit/change-part-of-the-brand-kit"},{"title":"Upload a font file to the Brand Kit","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /brand-kit/fonts","href":"/api-reference/brand-kit/upload-a-font-file-to-the-brand-kit"},{"title":"Add a named SVG icon to the Brand Kit","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json post /brand-kit/icons","href":"/api-reference/brand-kit/add-a-named-svg-icon-to-the-brand-kit"},{"title":"Remove a font or icon from the Brand Kit","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json delete /brand-kit/assets/{assetId}","href":"/api-reference/brand-kit/remove-a-font-or-icon-from-the-brand-kit"},{"title":"Rename an icon or relabel a font variant","deprecated":null,"version":null,"openapi":"/openapi/widgetic-api-public.json patch /brand-kit/assets/{assetId}","href":"/api-reference/brand-kit/rename-an-icon-or-relabel-a-font-variant"}]}]},{"tab":"Resources","pages":[{"title":"Resources","href":"/resources/examples"}]}]},"basePath":"","title":"Make a secret to sign the context of your embeds - Widgetic","buildId":"dpl_DqYu5MPb49gWBBbUGgpHQUmCHY3P","deploymentId":"dpl_DqYu5MPb49gWBBbUGgpHQUmCHY3P","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-CybtLBIt.js","utils-BMLj2fvV.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-B6In562Y.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-Dr8Mfhp9.js","snippetPresets-2rmQvMVl.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","conditional-requirements-CFM0id0Q.js","ApiExamples-WMqJYdZj.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-CJ-MlPHu.js","shallow-dY3TMRCk.js","getApiPlaygroundDisplay-v-1B2bKm.js","CodeSnippet-BDhiTB7U.js","CodeSnippets-D9hnzQcS.js","Page-C4GwDT3_.js","getPastedJson-Th2V45jI.js","icon-BQXch1W9.js","MethodPill-BCqUneP3.js","DuplicateIcon-Q_-bhurZ.js","createIcon-DUjLHRqp.js","DynamicMarkdown-B-f2cqXQ.js","SectionHeading-Da5NsV4v.js","axios-vUo_bRtp.js","Markdown-D13FWkIM.js","clsx-D3Isdib3.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-C-XZBk9h.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink--qIqmmVG.js"]}