{ "annotation": { "id": "3f2504e04f8911d39a0c0305e82c3301", "annotated_at": "2026-08-15T09:00:00Z", "timezone": "Asia/Tokyo", "title": "Pricing page redesign", "color": "#3b82f6", "source": "manual", "created_at": "2023-11-07T05:31:56Z", "updated_at": "2023-11-07T05:31:56Z", "description": "Rolled out to all visitors after the A/B test.", "source_id": "bcast_1234567890" }}
Web Analytics
Create an annotation
Creates a manual annotation. Requires the web_analytics write permission.
source is always stored as manual and source_id is always empty: only the platform writes automatic rows, so there is no way to attach a caller-supplied key to one. This endpoint is therefore not idempotent — a retried call (a CI job re-running a deploy marker, for instance) writes a second annotation. De-duplicate on the caller’s side, or delete the extra row.
Omitted color and timezone are filled in server-side: the default colour, and the workspace timezone falling back to UTC.
POST
/
api
/
annotations.create
Create an annotation
curl --request POST \ --url https://{notifuseDomain}/api/annotations.create \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "workspace_id": "ws_1234567890", "annotated_at": "2026-08-15T09:00:00Z", "title": "Pricing page redesign", "timezone": "Asia/Tokyo", "description": "Rolled out to all visitors after the A/B test.", "color": "#3b82f6", "source": "manual"}'
import requests
url = "https://{notifuseDomain}/api/annotations.create"
payload = {
"workspace_id": "ws_1234567890",
"annotated_at": "2026-08-15T09:00:00Z",
"title": "Pricing page redesign",
"timezone": "Asia/Tokyo",
"description": "Rolled out to all visitors after the A/B test.",
"color": "#3b82f6",
"source": "manual"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Notifuse Documentation","colors":{"primary":"#7763F1","light":"#7763F1","dark":"#7763F1"},"logo":{"light":"https://mintcdn.com/notifuse/Gw4P7NadUImyvZfw/assets/logo/logo-small.png?fit=max\u0026auto=format\u0026n=Gw4P7NadUImyvZfw\u0026q=85\u0026s=3f27c94b7162528f7c2d50f0d0dffdc4","dark":"https://mintcdn.com/notifuse/Gw4P7NadUImyvZfw/assets/logo/logo-small.png?fit=max\u0026auto=format\u0026n=Gw4P7NadUImyvZfw\u0026q=85\u0026s=3f27c94b7162528f7c2d50f0d0dffdc4","href":"https://notifuse.com"},"favicon":"https://mintcdn.com/notifuse/Gw4P7NadUImyvZfw/assets/logo/icon.png?fit=max\u0026auto=format\u0026n=Gw4P7NadUImyvZfw\u0026q=85\u0026s=4747c87b24b335428a3813ddeddb25c6","appearance":{"default":"light","strict":true},"navbar":{"links":[{"href":"mailto:hello@notifuse.com","label":"Support"},{"href":"https://github.com/notifuse","label":"GitHub"}],"primary":{"type":"button","label":"Try Notifuse Cloud","href":"https://cloud.notifuse.com"}},"footer":{"socials":{"x":"https://x.com/notifuse","github":"https://github.com/notifuse"}},"styling":{"latex":true},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"notifuse","hasAudioNarration":false,"actualSubdomain":"notifuse","customDomains":["docs.notifuse.com"],"gitSource":{"type":"github","owner":"notifuse","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ae9df284323a0c25b2c5b30","collectionId":"b5de9097-7179-4ec5-86b5-8d626496611a","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ae9df284323a0c25b2c5b30"},"entitlements":{},"buildId":"6ae9ede375120cb36f290c17","clientVersion":"0.0.4067","searchFilterCounts":[{"language":"default","tag":"API Reference","count":74},{"language":"default","tag":"Documentation","count":40},{"language":"default","tag":"Features","count":25},{"language":"default","tag":"Blog","count":21},{"language":"default","tag":"Web Analytics","count":17},{"language":"default","tag":"Broadcasts","count":12},{"language":"default","tag":"Webhooks","count":10},{"language":"default","tag":"Self-hosting","count":8},{"language":"default","tag":"Email Providers","count":7},{"language":"default","tag":"Contacts","count":7}]},"assistantConfig":{},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"api-reference/web-analytics/create-an-annotation","slug":"/api-reference/web-analytics/create-an-annotation","pageMetadata":{"title":"Create an annotation","description":"Creates a manual annotation. Requires the web_analytics write permission.\n\n`source` is always stored as `manual` and `source_id` is always empty: only the platform writes automatic rows, so there is no way to attach a caller-supplied key to one. **This endpoint is therefore not idempotent** — a retried call (a CI job re-running a deploy marker, for instance) writes a second annotation. De-duplicate on the caller's side, or delete the extra row.\n\nOmitted `color` and `timezone` are filled in server-side: the default colour, and the workspace timezone falling back to UTC.\n","deprecated":null,"version":null,"openapi":"/openapi.json post /api/annotations.create","href":"/api-reference/web-analytics/create-an-annotation","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 p: \"p\",\n strong: \"strong\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_Fragment, {\n children: [_jsx(_components.p, {\n children: \"Creates a manual annotation. Requires the web_analytics write permission.\"\n }), \"\\n\", _jsxs(_components.p, {\n children: [_jsx(_components.code, {\n children: \"source\"\n }), \" is always stored as \", _jsx(_components.code, {\n children: \"manual\"\n }), \" and \", _jsx(_components.code, {\n children: \"source_id\"\n }), \" is always empty: only the platform writes automatic rows, so there is no way to attach a caller-supplied key to one. \", _jsx(_components.strong, {\n children: \"This endpoint is therefore not idempotent\"\n }), \" — a retried call (a CI job re-running a deploy marker, for instance) writes a second annotation. De-duplicate on the caller’s side, or delete the extra row.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Omitted \", _jsx(_components.code, {\n children: \"color\"\n }), \" and \", _jsx(_components.code, {\n children: \"timezone\"\n }), \" are filled in server-side: the default colour, and the workspace timezone falling back to UTC.\"]\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":"Create an annotation","description":"Creates a manual annotation. Requires the web_analytics write permission.\n\n`source` is always stored as `manual` and `source_id` is always empty: only the platform writes automatic rows, so there is no way to attach a caller-supplied key to one. **This endpoint is therefore not idempotent** — a retried call (a CI job re-running a deploy marker, for instance) writes a second annotation. De-duplicate on the caller's side, or delete the extra row.\n\nOmitted `color` and `timezone` are filled in server-side: the default colour, and the workspace timezone falling back to UTC.\n","deprecated":null,"version":null,"openapi":"/openapi.json post /api/annotations.create","href":"/api-reference/web-analytics/create-an-annotation","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"summary":"Create an annotation","description":"Creates a manual annotation. Requires the web_analytics write permission.\n\n`source` is always stored as `manual` and `source_id` is always empty: only the platform writes automatic rows, so there is no way to attach a caller-supplied key to one. **This endpoint is therefore not idempotent** — a retried call (a CI job re-running a deploy marker, for instance) writes a second annotation. De-duplicate on the caller's side, or delete the extra row.\n\nOmitted `color` and `timezone` are filled in server-side: the default colour, and the workspace timezone falling back to UTC.\n","operationId":"createAnnotation","tags":["Web Analytics"],"security":["ba24b4f2-eb16-4026-9ca4-98c0778f1c86"],"requestBody":"814e3229-285f-4d77-abc2-b762b31cbb89","responses":{"201":"a97009d9-5ac2-465b-b2c4-246ccfe7cf20","400":"30ea5a93-84cb-4267-b72a-a44a16f09eb6","401":"6efcb41f-c300-4a3e-8cf0-c52bc2557b7a","403":"7e5a725d-3792-4ff6-831e-0ff58e484cf2","500":"6c819eb2-a92a-44e9-877c-1bf8ef8a9f27"},"method":"post","type":"path","servers":["26d4277a-6e4c-4b4f-b10e-d4b74e4c1afe"],"path":"/api/annotations.create","baseUrlOptions":["https://{notifuseDomain}"],"title":"Create an annotation","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["workspace_id","annotated_at","title"],"properties":{"workspace_id":{"type":"string","example":"ws_1234567890","isRequired":true,"uniqueKey":"workspace_id","typeLabel":"string"},"annotated_at":{"type":"string","format":"date-time","description":"The moment to mark, as an RFC3339 instant.","example":"2026-08-15T09:00:00Z","isRequired":true,"uniqueKey":"annotated_at","typeLabel":"string\u003cdate-time>"},"title":{"type":"string","maxLength":100,"example":"Pricing page redesign","isRequired":true,"uniqueKey":"title","typeLabel":"string"},"timezone":{"type":"string","description":"IANA timezone the moment was entered in, kept for display. Defaults to the workspace timezone, then to UTC.","example":"Asia/Tokyo","uniqueKey":"timezone","typeLabel":"string"},"description":{"type":"string","maxLength":500,"example":"Rolled out to all visitors after the A/B test.","uniqueKey":"description","typeLabel":"string"},"color":{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$","default":"#3b82f6","example":"#3b82f6","uniqueKey":"color","typeLabel":"string"},"source":{"type":"string","enum":["manual"],"description":"Only `manual` is accepted. Sending `broadcast` is rejected rather than quietly downgraded: it would be claiming the slot of an automatic row.","default":"manual","uniqueKey":"source","typeLabel":"enum\u003cstring>"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"workspace_id":"ws_1234567890","annotated_at":"2026-08-15T09:00:00Z","title":"Pricing page redesign","timezone":"Asia/Tokyo","description":"Rolled out to all visitors after the A/B test.","color":"#3b82f6","source":"manual"}}},"exampleType":"generated"}},"exampleType":"generated"},"responses":{"a97009d9-5ac2-465b-b2c4-246ccfe7cf20":{"description":"Annotation created","content":{"application/json":{"schema":{"type":"object","properties":{"annotation":{"type":"object","required":["id","annotated_at","timezone","title","color","source","created_at","updated_at"],"properties":{"id":{"type":"string","description":"Server-generated identifier (a UUID with its dashes removed).","example":"3f2504e04f8911d39a0c0305e82c3301","isRequired":true,"uniqueKey":"annotation.id","typeLabel":"string"},"annotated_at":{"type":"string","format":"date-time","description":"The moment the annotation marks, as a real instant.","example":"2026-08-15T09:00:00Z","isRequired":true,"uniqueKey":"annotation.annotated_at","typeLabel":"string\u003cdate-time>"},"timezone":{"type":"string","description":"IANA timezone the moment was entered in. This is display intent only — annotated_at already fixes the instant, and filtering never uses this field. It is what lets \"9am in Tokyo\" render back as 9am instead of the reader's local equivalent.","example":"Asia/Tokyo","isRequired":true,"uniqueKey":"annotation.timezone","typeLabel":"string"},"title":{"type":"string","maxLength":100,"description":"Counted in characters, not bytes.","example":"Pricing page redesign","isRequired":true,"uniqueKey":"annotation.title","typeLabel":"string"},"color":{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$","description":"Six-digit hex colour used for the marker on the charts.","example":"#3b82f6","isRequired":true,"uniqueKey":"annotation.color","typeLabel":"string"},"source":{"type":"string","enum":["manual","broadcast"],"description":"Who wrote the row. `manual` is anything typed by an operator or posted to this API; `broadcast` rows are written automatically when a broadcast starts sending. There is deliberately no API source — see the note on annotations.create.","example":"manual","isRequired":true,"uniqueKey":"annotation.source","typeLabel":"enum\u003cstring>"},"created_at":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"annotation.created_at","typeLabel":"string\u003cdate-time>"},"updated_at":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"annotation.updated_at","typeLabel":"string\u003cdate-time>"},"description":{"type":"string","maxLength":500,"description":"Optional longer note. Counted in characters, not bytes.","example":"Rolled out to all visitors after the A/B test.","uniqueKey":"annotation.description","typeLabel":"string"},"source_id":{"type":"string","description":"The entity that caused an automatic annotation (a broadcast id today). Always absent on manual rows, and never settable through the API. An annotation outlives the entity it points at: deleting a broadcast leaves its annotation, because the send did happen.","example":"bcast_1234567890","uniqueKey":"annotation.source_id","typeLabel":"string"}},"uniqueKey":"annotation","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"annotation":{"id":"3f2504e04f8911d39a0c0305e82c3301","annotated_at":"2026-08-15T09:00:00Z","timezone":"Asia/Tokyo","title":"Pricing page redesign","color":"#3b82f6","source":"manual","created_at":"2023-11-07T05:31:56Z","updated_at":"2023-11-07T05:31:56Z","description":"Rolled out to all visitors after the A/B test.","source_id":"bcast_1234567890"}}}},"exampleType":"generated"}},"exampleType":"generated"},"30ea5a93-84cb-4267-b72a-a44a16f09eb6":{"description":"Bad request - unparseable body, validation failed, or the instance runs in demo mode, where every mutating endpoint is closed.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","isRequired":true,"uniqueKey":"error","typeLabel":"string"}},"required":["error"],"uniqueKey":"","typeLabel":"object"},"examples":{"invalidBody":{"title":"invalidBody","value":{"error":"Invalid request body"}},"missingTitle":{"title":"missingTitle","value":{"error":"invalid request: title is required"}},"invalidColor":{"title":"invalidColor","value":{"error":"invalid request: color must be a hex color like #3b82f6"}},"systemSource":{"title":"systemSource","value":{"error":"invalid request: source must be \"manual\""}},"demoMode":{"title":"demoMode","value":{"error":"This operation is not allowed in demo mode"}}},"exampleType":"examples"}},"exampleType":"examples"},"6efcb41f-c300-4a3e-8cf0-c52bc2557b7a":{"description":"Unauthorized - invalid or missing authentication token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","isRequired":true,"uniqueKey":"error","typeLabel":"string"}},"required":["error"],"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"error":"\u003cstring>"}}},"exampleType":"generated"}},"exampleType":"generated"},"7e5a725d-3792-4ff6-831e-0ff58e484cf2":{"description":"Forbidden - missing required permission","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","isRequired":true,"uniqueKey":"error","typeLabel":"string"}},"required":["error"],"uniqueKey":"","typeLabel":"object"},"example":{"error":"Insufficient permissions: write access to web analytics required"},"examples":{"Example":{"title":"Example","value":{"error":"Insufficient permissions: write access to web analytics required"}}},"exampleType":"examples"}},"exampleType":"examples"},"6c819eb2-a92a-44e9-877c-1bf8ef8a9f27":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","isRequired":true,"uniqueKey":"error","typeLabel":"string"}},"required":["error"],"uniqueKey":"","typeLabel":"object"},"example":{"error":"Failed to create annotation"},"examples":{"Example":{"title":"Example","value":{"error":"Failed to create annotation"}}},"exampleType":"examples"}},"exampleType":"examples"}},"security":{"ba24b4f2-eb16-4026-9ca4-98c0778f1c86":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API token for authentication","scopes":[],"schemeName":"BearerAuth"}}},"servers":{"26d4277a-6e4c-4b4f-b10e-d4b74e4c1afe":{"url":"https://{notifuseDomain}","description":"Customer-specific Notifuse API server","variables":{"notifuseDomain":{"description":"Your unique Notifuse domain","default":"demo.notifuse.com"}}}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"http","scheme":"bearer","description":"API token for authentication","scopes":[],"schemeName":"BearerAuth"},"schema":{"title":"Bearer Auth","type":"string","isRequired":true,"description":"API token for authentication","format":"bearer","typeLabel":"string\u003cbearer>","deprecated":false},"schemeName":"BearerAuth","name":"Authorization"}],"title":"BearerAuth"}]},"originalFileLocation":"openapi.json"},"subdomain":"notifuse","siteName":"Notifuse Documentation","title":"Create an annotation - Notifuse Documentation","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-23T13:59:41.725Z","originalFileLocation":"api-reference/web-analytics/create-an-annotation.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=\"light\";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=\"light\"}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=\"Creates a manual annotation. Requires the web_analytics write permission. source is always stored as manual and source_id is always empty: only the platform writes automatic rows, so there is no way to attach a caller-supplied key to one. This endpoint is therefore not idempotent — a retried call (a CI job re-running a deploy marker, for instance) writes a second annotation. De-duplicate on the caller\u0026#x27;s side, or delete the extra row. Omitted color and timezone are filled in server-side: the default colour, and the workspace timezone falling back to UTC.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Notifuse Documentation\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/notifuse/c0N0ayUOq9_6B61d/_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/notifuse/c0N0ayUOq9_6B61d/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/notifuse/c0N0ayUOq9_6B61d/_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/notifuse/c0N0ayUOq9_6B61d/_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/notifuse/c0N0ayUOq9_6B61d/_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/notifuse/c0N0ayUOq9_6B61d/_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/notifuse/c0N0ayUOq9_6B61d/_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/notifuse/c0N0ayUOq9_6B61d/_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/notifuse/c0N0ayUOq9_6B61d/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Create an annotation - Notifuse Documentation\">\u003cmeta data-mint-head property=\"og:description\" content=\"Creates a manual annotation. Requires the web_analytics write permission. source is always stored as manual and source_id is always empty: only the platform writes automatic rows, so there is no way to attach a caller-supplied key to one. This endpoint is therefore not idempotent — a retried call (a CI job re-running a deploy marker, for instance) writes a second annotation. De-duplicate on the caller\u0026#x27;s side, or delete the extra row. Omitted color and timezone are filled in server-side: the default colour, and the workspace timezone falling back to UTC.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Notifuse Documentation\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.notifuse.com/api-reference/web-analytics/create-an-annotation\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://notifuse.mintlify.app/_mintlify/api/og/v2?division=Web+Analytics\u0026amp;title=Create+an+annotation\u0026amp;description=Creates+a+manual+annotation.+Requires+the+web_analytics+write+permission.%0A%0A%60source%60+is+always+stored+as+%60manual%60+and+%60source_id%60+is+always+empty%3A+only+the+platf\u0026amp;theme=2416c428fba7698fa1a23c53\u0026amp;signature=e2d3d7cf6fe6fc4c22011ad08e5147cac84235139ce4104660d37345ec653460\">\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=\"Create an annotation - Notifuse Documentation\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Creates a manual annotation. Requires the web_analytics write permission. source is always stored as manual and source_id is always empty: only the platform writes automatic rows, so there is no way to attach a caller-supplied key to one. This endpoint is therefore not idempotent — a retried call (a CI job re-running a deploy marker, for instance) writes a second annotation. De-duplicate on the caller\u0026#x27;s side, or delete the extra row. Omitted color and timezone are filled in server-side: the default colour, and the workspace timezone falling back to UTC.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://notifuse.mintlify.app/_mintlify/api/og/v2?division=Web+Analytics\u0026amp;title=Create+an+annotation\u0026amp;description=Creates+a+manual+annotation.+Requires+the+web_analytics+write+permission.%0A%0A%60source%60+is+always+stored+as+%60manual%60+and+%60source_id%60+is+always+empty%3A+only+the+platf\u0026amp;theme=2416c428fba7698fa1a23c53\u0026amp;signature=e2d3d7cf6fe6fc4c22011ad08e5147cac84235139ce4104660d37345ec653460\">\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/notifuse/c0N0ayUOq9_6B61d/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Notifuse Documentation\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#7763F1\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.notifuse.com/api-reference/web-analytics/create-an-annotation\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/web-analytics/create-an-annotation.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.notifuse.com/#organization\",\"name\":\"Notifuse Documentation\",\"url\":\"https://docs.notifuse.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/notifuse/Gw4P7NadUImyvZfw/assets/logo/logo-small.png?fit=max\u0026auto=format\u0026n=Gw4P7NadUImyvZfw\u0026q=85\u0026s=3f27c94b7162528f7c2d50f0d0dffdc4\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.notifuse.com#website\",\"name\":\"Notifuse Documentation\",\"url\":\"https://docs.notifuse.com\",\"publisher\":{\"@id\":\"https://docs.notifuse.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.notifuse.com/api-reference/web-analytics/create-an-annotation#webpage\",\"url\":\"https://docs.notifuse.com/api-reference/web-analytics/create-an-annotation\",\"name\":\"Create an annotation\",\"description\":\"Creates a manual annotation. Requires the web_analytics write permission. source is always stored as manual and source_id is always empty: only the platform writes automatic rows, so there is no way to attach a caller-supplied key to one. This endpoint is therefore not idempotent — a retried call (a CI job re-running a deploy marker, for instance) writes a second annotation. De-duplicate on the caller's side, or delete the extra row. Omitted color and timezone are filled in server-side: the default colour, and the workspace timezone falling back to UTC.\",\"dateModified\":\"2026-10-23T13:59:41.725Z\",\"isPartOf\":{\"@id\":\"https://docs.notifuse.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.notifuse.com/api-reference/web-analytics/create-an-annotation#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.notifuse.com/api-reference/web-analytics/create-an-annotation#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Web Analytics\",\"item\":\"https://docs.notifuse.com/api-reference/web-analytics/ingest-a-web-analytics-beat\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Create an annotation\",\"item\":\"https://docs.notifuse.com/api-reference/web-analytics/create-an-annotation\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.notifuse.com/api-reference/web-analytics/create-an-annotation#apireference\",\"headline\":\"Create an annotation\",\"name\":\"Create an annotation\",\"description\":\"Creates a manual annotation. Requires the web_analytics write permission. source is always stored as manual and source_id is always empty: only the platform writes automatic rows, so there is no way to attach a caller-supplied key to one. This endpoint is therefore not idempotent — a retried call (a CI job re-running a deploy marker, for instance) writes a second annotation. De-duplicate on the caller's side, or delete the extra row. Omitted color and timezone are filled in server-side: the default colour, and the workspace timezone falling back to UTC.\",\"url\":\"https://docs.notifuse.com/api-reference/web-analytics/create-an-annotation\",\"mainEntityOfPage\":{\"@id\":\"https://docs.notifuse.com/api-reference/web-analytics/create-an-annotation#webpage\"},\"dateModified\":\"2026-10-23T13:59:41.725Z\",\"publisher\":{\"@id\":\"https://docs.notifuse.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.notifuse.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Notifuse Documentation\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Notifuse Documentation","nav":{"global":null,"tabs":[{"tab":"Documentation","pages":[{"title":"Documentation","href":""}]},{"tab":"Self-hosting","pages":[{"title":"Self-hosting","href":"/self-hosting/installation"}]},{"tab":"API Reference","groups":[{"group":"Authentication","pages":[{"title":"Root user programmatic signin","deprecated":null,"version":null,"openapi":"/openapi.json post /api/user.rootSignin","href":"/api-reference/authentication/root-user-programmatic-signin"}]},{"group":"Transactional","pages":[{"title":"Send a transactional notification","deprecated":null,"version":null,"openapi":"/openapi.json post /api/transactional.send","href":"/api-reference/send-a-transactional-notification"}]},{"group":"Contacts","pages":[{"title":"List contacts with filtering and pagination","deprecated":null,"version":null,"openapi":"/openapi.json get /api/contacts.list","href":"/api-reference/list-contacts-with-filtering-and-pagination"},{"title":"Count contacts in a workspace","deprecated":null,"version":null,"openapi":"/openapi.json get /api/contacts.count","href":"/api-reference/count-contacts-in-a-workspace"},{"title":"Create or update a contact","deprecated":null,"version":null,"openapi":"/openapi.json post /api/contacts.upsert","href":"/api-reference/create-or-update-a-contact"},{"title":"Get a contact by email address","deprecated":null,"version":null,"openapi":"/openapi.json get /api/contacts.getByEmail","href":"/api-reference/get-a-contact-by-email-address"},{"title":"Get a contact by external ID","deprecated":null,"version":null,"openapi":"/openapi.json get /api/contacts.getByExternalID","href":"/api-reference/get-a-contact-by-external-id"},{"title":"Batch import contacts","deprecated":null,"version":null,"openapi":"/openapi.json post /api/contacts.import","href":"/api-reference/batch-import-contacts"},{"title":"Delete a contact","deprecated":null,"version":null,"openapi":"/openapi.json post /api/contacts.delete","href":"/api-reference/delete-a-contact"}]},{"group":"Lists","pages":[{"title":"Update contact list subscription status","deprecated":null,"version":null,"openapi":"/openapi.json post /api/contactLists.updateStatus","href":"/api-reference/update-contact-list-subscription-status"},{"title":"Subscribe to email lists","deprecated":null,"version":null,"openapi":"/openapi.json post /subscribe","href":"/api-reference/subscribe-to-email-lists"},{"title":"Subscribe to email lists (authenticated)","deprecated":null,"version":null,"openapi":"/openapi.json post /api/lists.subscribe","href":"/api-reference/subscribe-to-email-lists-authenticated"}]},{"group":"Custom Events","pages":[{"title":"Import custom events","deprecated":null,"version":null,"openapi":"/openapi.json post /api/customEvents.import","href":"/api-reference/import-custom-events"}]},{"group":"Web Analytics","pages":[{"title":"Ingest a web analytics beat","deprecated":null,"version":null,"openapi":"/openapi.json post /track","href":"/api-reference/web-analytics/ingest-a-web-analytics-beat"},{"title":"Replace the workspace's web analytics settings","deprecated":null,"version":null,"openapi":"/openapi.json post /api/workspaces.setWebAnalyticsSettings","href":"/api-reference/web-analytics/replace-the-workspaces-web-analytics-settings"},{"title":"Start an attribution backfill","deprecated":null,"version":null,"openapi":"/openapi.json post /api/webAnalytics.backfillStart","href":"/api-reference/web-analytics/start-an-attribution-backfill"},{"title":"Get the latest backfill run","deprecated":null,"version":null,"openapi":"/openapi.json post /api/webAnalytics.backfillStatus","href":"/api-reference/web-analytics/get-the-latest-backfill-run"},{"title":"Cancel the in-flight backfill run","deprecated":null,"version":null,"openapi":"/openapi.json post /api/webAnalytics.backfillCancel","href":"/api-reference/web-analytics/cancel-the-in-flight-backfill-run"},{"title":"List annotations","deprecated":null,"version":null,"openapi":"/openapi.json get /api/annotations.list","href":"/api-reference/web-analytics/list-annotations"},{"title":"Get an annotation","description":"Retrieves a single annotation by ID. Requires the web_analytics read permission.","deprecated":null,"version":null,"openapi":"/openapi.json get /api/annotations.get","href":"/api-reference/web-analytics/get-an-annotation"},{"title":"Create an annotation","deprecated":null,"version":null,"openapi":"/openapi.json post /api/annotations.create","href":"/api-reference/web-analytics/create-an-annotation"},{"title":"Update an annotation","description":"Edits an annotation's moment, timezone and presentation. Requires the web_analytics write permission.\n\nAutomatic annotations are editable — an operator may want to reword a broadcast's title — but their origin is not: `source` and `source_id` are reloaded from storage and carried forward, so an edit can neither promote a manual row to a system one nor take over another broadcast's slot.\n","deprecated":null,"version":null,"openapi":"/openapi.json post /api/annotations.update","href":"/api-reference/web-analytics/update-an-annotation"},{"title":"Delete an annotation","deprecated":null,"version":null,"openapi":"/openapi.json post /api/annotations.delete","href":"/api-reference/web-analytics/delete-an-annotation"}]},{"group":"Broadcasts","pages":[{"title":"List broadcasts","deprecated":null,"version":null,"openapi":"/openapi.json get /api/broadcasts.list","href":"/api-reference/list-broadcasts"},{"title":"Get a broadcast","deprecated":null,"version":null,"openapi":"/openapi.json get /api/broadcasts.get","href":"/api-reference/get-a-broadcast"},{"title":"Create a broadcast","deprecated":null,"version":null,"openapi":"/openapi.json post /api/broadcasts.create","href":"/api-reference/create-a-broadcast"},{"title":"Update a broadcast","deprecated":null,"version":null,"openapi":"/openapi.json post /api/broadcasts.update","href":"/api-reference/update-a-broadcast"},{"title":"Schedule a broadcast","deprecated":null,"version":null,"openapi":"/openapi.json post /api/broadcasts.schedule","href":"/api-reference/schedule-a-broadcast"},{"title":"Pause a broadcast","deprecated":null,"version":null,"openapi":"/openapi.json post /api/broadcasts.pause","href":"/api-reference/pause-a-broadcast"},{"title":"Resume a broadcast","deprecated":null,"version":null,"openapi":"/openapi.json post /api/broadcasts.resume","href":"/api-reference/resume-a-broadcast"},{"title":"Cancel a broadcast","deprecated":null,"version":null,"openapi":"/openapi.json post /api/broadcasts.cancel","href":"/api-reference/cancel-a-broadcast"},{"title":"Send broadcast to individual","deprecated":null,"version":null,"openapi":"/openapi.json post /api/broadcasts.sendToIndividual","href":"/api-reference/send-broadcast-to-individual"},{"title":"Delete a broadcast","deprecated":null,"version":null,"openapi":"/openapi.json post /api/broadcasts.delete","href":"/api-reference/delete-a-broadcast"},{"title":"Get A/B test results","deprecated":null,"version":null,"openapi":"/openapi.json get /api/broadcasts.getTestResults","href":"/api-reference/get-ab-test-results"},{"title":"Select winning A/B test variation","deprecated":null,"version":null,"openapi":"/openapi.json post /api/broadcasts.selectWinner","href":"/api-reference/select-winning-ab-test-variation"}]},{"group":"Templates","pages":[{"title":"List templates","deprecated":null,"version":null,"openapi":"/openapi.json get /api/templates.list","href":"/api-reference/list-templates"},{"title":"Get a template","deprecated":null,"version":null,"openapi":"/openapi.json get /api/templates.get","href":"/api-reference/get-a-template"},{"title":"Create a template","deprecated":null,"version":null,"openapi":"/openapi.json post /api/templates.create","href":"/api-reference/create-a-template"},{"title":"Update a template","deprecated":null,"version":null,"openapi":"/openapi.json post /api/templates.update","href":"/api-reference/update-a-template"},{"title":"Delete a template","deprecated":null,"version":null,"openapi":"/openapi.json post /api/templates.delete","href":"/api-reference/delete-a-template"},{"title":"Compile template","deprecated":null,"version":null,"openapi":"/openapi.json post /api/templates.compile","href":"/api-reference/compile-template"}]},{"group":"Blog","pages":[{"title":"List blog categories","deprecated":null,"version":null,"openapi":"/openapi.json get /api/blogCategories.list","href":"/api-reference/blog/list-blog-categories"},{"title":"Get a blog category","deprecated":null,"version":null,"openapi":"/openapi.json get /api/blogCategories.get","href":"/api-reference/blog/get-a-blog-category"},{"title":"Create a blog category","deprecated":null,"version":null,"openapi":"/openapi.json post /api/blogCategories.create","href":"/api-reference/blog/create-a-blog-category"},{"title":"Update a blog category","deprecated":null,"version":null,"openapi":"/openapi.json post /api/blogCategories.update","href":"/api-reference/blog/update-a-blog-category"},{"title":"Delete a blog category","deprecated":null,"version":null,"openapi":"/openapi.json post /api/blogCategories.delete","href":"/api-reference/blog/delete-a-blog-category"},{"title":"List blog posts","deprecated":null,"version":null,"openapi":"/openapi.json get /api/blogPosts.list","href":"/api-reference/blog/list-blog-posts"},{"title":"Get a blog post","deprecated":null,"version":null,"openapi":"/openapi.json get /api/blogPosts.get","href":"/api-reference/blog/get-a-blog-post"},{"title":"Create a blog post","deprecated":null,"version":null,"openapi":"/openapi.json post /api/blogPosts.create","href":"/api-reference/blog/create-a-blog-post"},{"title":"Update a blog post","deprecated":null,"version":null,"openapi":"/openapi.json post /api/blogPosts.update","href":"/api-reference/blog/update-a-blog-post"},{"title":"Delete a blog post","deprecated":null,"version":null,"openapi":"/openapi.json post /api/blogPosts.delete","href":"/api-reference/blog/delete-a-blog-post"},{"title":"Publish a blog post","deprecated":null,"version":null,"openapi":"/openapi.json post /api/blogPosts.publish","href":"/api-reference/blog/publish-a-blog-post"},{"title":"Unpublish a blog post","deprecated":null,"version":null,"openapi":"/openapi.json post /api/blogPosts.unpublish","href":"/api-reference/blog/unpublish-a-blog-post"},{"title":"List blog theme versions","deprecated":null,"version":null,"openapi":"/openapi.json get /api/blogThemes.list","href":"/api-reference/blog/list-blog-theme-versions"},{"title":"Get a blog theme version","deprecated":null,"version":null,"openapi":"/openapi.json get /api/blogThemes.get","href":"/api-reference/blog/get-a-blog-theme-version"},{"title":"Get the published blog theme","deprecated":null,"version":null,"openapi":"/openapi.json get /api/blogThemes.getPublished","href":"/api-reference/blog/get-the-published-blog-theme"},{"title":"Create a blog theme version","deprecated":null,"version":null,"openapi":"/openapi.json post /api/blogThemes.create","href":"/api-reference/blog/create-a-blog-theme-version"},{"title":"Update a blog theme version","deprecated":null,"version":null,"openapi":"/openapi.json post /api/blogThemes.update","href":"/api-reference/blog/update-a-blog-theme-version"},{"title":"Publish a blog theme version","deprecated":null,"version":null,"openapi":"/openapi.json post /api/blogThemes.publish","href":"/api-reference/blog/publish-a-blog-theme-version"}]},{"group":"Webhooks","pages":[{"title":"Create a webhook subscription","deprecated":null,"version":null,"openapi":"/openapi.json post /api/webhookSubscriptions.create","href":"/api-reference/create-a-webhook-subscription"},{"title":"List webhook subscriptions","deprecated":null,"version":null,"openapi":"/openapi.json get /api/webhookSubscriptions.list","href":"/api-reference/list-webhook-subscriptions"},{"title":"Get a webhook subscription","deprecated":null,"version":null,"openapi":"/openapi.json get /api/webhookSubscriptions.get","href":"/api-reference/get-a-webhook-subscription"},{"title":"Update a webhook subscription","deprecated":null,"version":null,"openapi":"/openapi.json post /api/webhookSubscriptions.update","href":"/api-reference/update-a-webhook-subscription"},{"title":"Delete a webhook subscription","deprecated":null,"version":null,"openapi":"/openapi.json post /api/webhookSubscriptions.delete","href":"/api-reference/delete-a-webhook-subscription"},{"title":"Toggle webhook subscription enabled state","deprecated":null,"version":null,"openapi":"/openapi.json post /api/webhookSubscriptions.toggle","href":"/api-reference/toggle-webhook-subscription-enabled-state"},{"title":"Regenerate webhook secret","deprecated":null,"version":null,"openapi":"/openapi.json post /api/webhookSubscriptions.regenerateSecret","href":"/api-reference/regenerate-webhook-secret"},{"title":"Get webhook delivery history","deprecated":null,"version":null,"openapi":"/openapi.json get /api/webhookSubscriptions.deliveries","href":"/api-reference/get-webhook-delivery-history"},{"title":"Send a test webhook","deprecated":null,"version":null,"openapi":"/openapi.json post /api/webhookSubscriptions.test","href":"/api-reference/send-a-test-webhook"},{"title":"List available event types","deprecated":null,"version":null,"openapi":"/openapi.json get /api/webhookSubscriptions.eventTypes","href":"/api-reference/list-available-event-types"}]},{"group":"Audit logs","pages":[{"title":"List audit logs","deprecated":null,"version":null,"openapi":"/openapi.json get /api/auditLogs.list","href":"/api-reference/audit-logs/list-audit-logs"},{"title":"Get an audit log entry","deprecated":null,"version":null,"openapi":"/openapi.json get /api/auditLogs.get","href":"/api-reference/audit-logs/get-an-audit-log-entry"},{"title":"List audit actions","deprecated":null,"version":null,"openapi":"/openapi.json get /api/auditLogs.actions","href":"/api-reference/audit-logs/list-audit-actions"},{"title":"Export audit logs","deprecated":null,"version":null,"openapi":"/openapi.json post /api/auditLogs.export","href":"/api-reference/audit-logs/export-audit-logs"},{"title":"Set the workspace audit log retention","deprecated":null,"version":null,"openapi":"/openapi.json post /api/workspaces.setAuditLogSettings","href":"/api-reference/audit-logs/set-the-workspace-audit-log-retention"}]}]},{"tab":"Cloud","href":"https://cloud.notifuse.com"}]},"basePath":"","title":"Create an annotation - Notifuse Documentation","buildId":"dpl_9VVk5y1P8k1ATeJguVngy9Q3cmbD","deploymentId":"dpl_9VVk5y1P8k1ATeJguVngy9Q3cmbD","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-DX1Meug0.js","utils-B_OMIQVC.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-ChxhRPMa.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-CuKvD8Iv.js","snippetPresets-C5d7p2hp.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","ApiExamples-CfHcE8m4.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-C1zZV314.js","shallow-CmQhqCJn.js","getApiPlaygroundDisplay-YRo9s1O7.js","CodeSnippet-RN1MTdfk.js","CodeSnippets-DKLPHxJA.js","Page-BAvA99GL.js","getPastedJson-bz0M41mU.js","icon-CsmhpPrv.js","MethodPill-CNGsVE77.js","DuplicateIcon-DilfU_Z2.js","createIcon-BdsYzQck.js","DynamicMarkdown-CbqEDjbV.js","SectionHeading-O6hXpFCN.js","axios-vUo_bRtp.js","Markdown-nKm-uidQ.js","clsx-ClVdStUn.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-CIQkMg3R.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-ImrFS4Fy.js"]}