{"schema_version":"1.0","publisher":"Primitive SDKs","canonical_url":"https://test.abhinandan.one/go-receiving-webhooks/go-standard-webhooks","markdown_url":"https://test.abhinandan.one/go-receiving-webhooks/go-standard-webhooks.md","article":{"id":"7c83ee7f-dc4c-463b-aa76-0e4b6348371f","article_slug":"go-standard-webhooks","parent_article_slug":"go-receiving-webhooks","parent_article_title":"Receiving and Verifying Webhooks","kind":"guide","published_at":"2026-08-11T18:55:01.984712+00:00","keywords":["VerifyStandardWebhooksSignature","Standard Webhooks Go","webhook-id webhook-timestamp webhook-signature","whsec_ secret Go SDK","Primitive-Signature alternative"],"meta_description":"VerifyStandardWebhooksSignature checks the webhook-id, webhook-timestamp, and webhook-signature headers against a whsec_-prefixed secret in the Go SDK.","og_image_url":null,"source_file_paths":[],"recording_id":null,"replayable":false,"task_name":"Standard Webhooks Signature Support (Go)","category":"Go SDK","summary":null,"description":"Verify Primitive webhook deliveries using the Standard Webhooks header format instead of the default Primitive-Signature HMAC scheme, using VerifyStandardWebhooksSignature in the Go SDK.","content_kind":"repo_page","content_markdown":"Use `VerifyStandardWebhooksSignature` when a receiver already expects the [Standard Webhooks](https://www.standardwebhooks.com/) convention (`webhook-id` / `webhook-timestamp` / `webhook-signature` headers, `whsec_`-prefixed secret) instead of Primitive's own `Primitive-Signature` header. Reach for it only when your tooling is already wired for that convention; every other Go SDK integration should verify with the default HMAC scheme documented in [Receiving and Verifying Webhooks](go-receiving-webhooks).\n\nBoth schemes sign the exact same raw request body, so the trust guarantee is identical.\n\n## When to use this instead of the default\n\nUse Standard Webhooks only when a receiver, gateway, or shared verification library in your stack already speaks the `webhook-id` / `webhook-timestamp` / `webhook-signature` convention. Otherwise use Primitive's default `Primitive-Signature: t=<unix-seconds>,v1=<hex>` header, verified automatically by `primitive.Receive` and `primitive.HandleWebhook`, which needs no extra secret formatting.\n\n## Prerequisites\n\n- The Go SDK installed: `go get github.com/primitivedotdev/sdks/sdk-go@latest`\n- Your webhook secret from `GET /account/webhook-secret`, in its `whsec_`-prefixed form\n- The raw, unparsed request body and its `webhook-id`, `webhook-timestamp`, and `webhook-signature` headers\n\n<Warning>\n\nVerify against the exact raw request body bytes, before any JSON decoding or re-serialization. Re-serializing the body (even reformatting whitespace) changes the bytes the signature was computed over and verification will fail.\n\n</Warning>\n\n## Verify a delivery\n\n`VerifyStandardWebhooksSignature` takes a `StandardWebhooksVerifyOptions` struct with the raw body, the three header values, and your secret, and returns `(bool, error)`. Deliveries older than the 300-second (5-minute) default tolerance, or more than 60 seconds in the future, are rejected.\n\n<Steps>\n\n<Step title=\"Extract the three Standard Webhooks headers\">\n\nPull `webhook-id`, `webhook-timestamp`, and `webhook-signature` from the incoming request. Header names are case-insensitive per RFC 7230; match them accordingly.\n\n</Step>\n\n<Step title=\"Call VerifyStandardWebhooksSignature\">\n\nPass the raw body, the three header values, and your `whsec_`-prefixed secret:\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\n\tprimitive \"github.com/primitivedotdev/sdks/sdk-go\"\n)\n\nfunc handle(w http.ResponseWriter, r *http.Request, rawBody []byte) {\n\tok, err := primitive.VerifyStandardWebhooksSignature(primitive.StandardWebhooksVerifyOptions{\n\t\tRawBody:         rawBody,\n\t\tMsgID:           r.Header.Get(\"webhook-id\"),\n\t\tTimestamp:       r.Header.Get(\"webhook-timestamp\"),\n\t\tSignatureHeader: r.Header.Get(\"webhook-signature\"),\n\t\tSecret:          \"whsec_...\",\n\t})\n\tif err != nil {\n\t\tlog.Printf(\"invalid webhook signature: %v\", err)\n\t\thttp.Error(w, \"invalid signature\", http.StatusBadRequest)\n\t\treturn\n\t}\n\tif !ok {\n\t\thttp.Error(w, \"invalid signature\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tfmt.Fprintln(w, \"verified\")\n}\n```\n\n</Step>\n\n<Step title=\"Handle a verification failure\">\n\n`VerifyStandardWebhooksSignature` returns a non-nil error on a malformed header, an expired timestamp, or a signature mismatch. Respond with a 4xx status and do not process the payload; a genuine delivery from Primitive is redelivered on a 5xx or timeout, not on a 4xx rejection of a bad signature.\n\n</Step>\n\n</Steps>\n\n## Timestamp tolerance\n\nThe default tolerance rejects any delivery whose `webhook-timestamp` is more than 300 seconds (5 minutes) older than your wall clock, or more than 60 seconds in the future, which defends against replayed captures of old but otherwise-valid signatures. Set `ToleranceSeconds` on `StandardWebhooksVerifyOptions` to change the past-age window.\n\n## Next steps\n\n<CardGroup cols={2}>\n\n<Card title=\"Receiving and Verifying Webhooks\" href=\"go-receiving-webhooks\">\n\nVerify inbound webhook signatures with the default Primitive-Signature scheme and normalize the payload with primitive.Receive.\n\n</Card>\n\n<Card title=\"Webhook Event Types\" href=\"go-webhook-event-types\">\n\nLearn the email, payment, and interaction webhook event families and the X-Webhook-Event header discriminator.\n\n</Card>\n\n<Card title=\"Error Handling\" href=\"go-error-handling\">\n\nInspect WebhookVerificationError and the other typed Go SDK error types to handle failures precisely.\n\n</Card>\n\n<Card title=\"Webhook Events Overview\" href=\"webhook-events\">\n\nUnderstand the shared webhook contract across every SDK, including signature verification and forward-compatibility guarantees.\n\n</Card>\n\n</CardGroup>","canonical_base_url":"https://test.abhinandan.one","seo_indexing_enabled":true,"last_modified":"2026-08-21T18:22:43.359885+00:00","video_url":null,"voiceover_url":null,"tools_used":[],"demonstrated_by":[],"steps":[],"related_links":[],"intro":null,"prerequisites":[],"verification":[],"troubleshooting":[],"suggest_edit_url":null,"raise_issue_url":"https://github.com/abhi-browzer/primitive-sdks/issues/new?title=Docs+feedback%3A+Standard+Webhooks+Signature+Support+%28Go%29&body=Page%3A+https%3A%2F%2Ftest.abhinandan.one%2Fgo-standard-webhooks","page_feedback_enabled":true,"verified_ref":null,"verified_at":"2026-08-11T18:38:45.205849+00:00"}}