[{"data":1,"prerenderedAt":97},["ShallowReactive",2],{"doc:\u002Fdocs\u002Fsdks\u002Fgo":3},{"page":4,"toc":89,"updated":96},{"path":5,"title":6,"seoTitle":7,"description":8,"blocks":9},"\u002Fdocs\u002Fsdks\u002Fgo","Go","Go SDK: Read Events and Verify Webhooks","Read identification events with a secret key and verify signed webhooks from Go, with context-aware calls and typed events.",[10,13,18,23,26,33,36,38,43,45,48,50,54,57,59,63,66],{"type":11,"text":12},"p","The Go module reads stored events by request ID and verifies webhook signatures. Every call takes a `context.Context`, and the client is safe for concurrent use.",{"type":14,"level":15,"text":16,"id":17},"heading",2,"Requirements","requirements",{"type":19,"items":20},"list",[21,22],"Go 1.21 or newer.","A [secret key](\u002Fdocs\u002Fapi-keys), and a webhook signing secret if you receive [webhooks](\u002Fdocs\u002Fwebhooks).",{"type":14,"level":15,"text":24,"id":25},"Install","install",{"type":27,"samples":28},"code",[29],{"label":30,"lang":31,"code":32},"Terminal","bash","go get github.com\u002Ffingerly-io\u002Ffingerly-go",{"type":14,"level":15,"text":34,"id":35},"Read an event","read-an-event",{"type":11,"text":37},"Create one client with your secret key and reuse it. The key decides the regional API and the environment the client reads.",{"type":27,"samples":39},[40],{"label":6,"lang":41,"code":42},"go","import fingerly \"github.com\u002Ffingerly-io\u002Ffingerly-go\"\n\nclient := fingerly.New(os.Getenv(\"FINGERLY_SECRET_KEY\"))\nevent, err := client.Events.Get(ctx, \"01a0a84b-e6a2-7c09-9f51-0b3d7a26c8e4\")",{"type":11,"text":44},"An event has the fields listed in [Get an event](\u002Freference\u002Fget-event#response). `suspect_score` is `null` when the request was not scored.",{"type":14,"level":15,"text":46,"id":47},"Verify a checkout","verify-a-checkout",{"type":11,"text":49},"Read the event your client identified, check it belongs to this action and is recent, then decide on its level. See [server-side verification](\u002Fdocs\u002Fserver-side-verification).",{"type":27,"samples":51},[52],{"label":6,"lang":41,"code":53},"func decide(ctx context.Context, orderID, requestID string) (string, error) {\n    event, err := client.Events.Get(ctx, requestID)\n    var apiErr *fingerly.APIError\n    if errors.As(err, &apiErr) && apiErr.Status == http.StatusNotFound {\n        return \"refuse\", nil\n    } else if err != nil {\n        return \"\", err\n    }\n\n    if event.Tag != \"checkout:\"+orderID || time.Since(event.OccurredAt) > 2*time.Minute {\n        return \"refuse\", nil\n    }\n\n    switch event.SuspectLevel {\n    case \"high\":\n        return \"review\", nil\n    case \"medium\":\n        return \"challenge\", nil\n    }\n    return \"allow\", nil\n}",{"type":14,"level":15,"text":55,"id":56},"Verify a webhook","verify-a-webhook",{"type":11,"text":58},"Check the signature over the raw request body before parsing it. The helper rejects timestamps more than five minutes from now.",{"type":27,"samples":60},[61],{"label":6,"lang":41,"code":62},"func fingerlyWebhook(w http.ResponseWriter, r *http.Request) {\n    body, err := io.ReadAll(r.Body)\n    if err != nil {\n        http.Error(w, \"unreadable body\", http.StatusBadRequest)\n        return\n    }\n    if !fingerly.VerifyWebhook(\n        os.Getenv(\"FINGERLY_WEBHOOK_SECRET\"),\n        body,\n        r.Header.Get(\"X-Fingerly-Timestamp\"),\n        r.Header.Get(\"X-Fingerly-Signature\"),\n    ) {\n        http.Error(w, \"invalid signature\", http.StatusBadRequest)\n        return\n    }\n\n    var event fingerly.WebhookEvent\n    _ = json.Unmarshal(body, &event)\n    enqueue(event.ID, body)   \u002F\u002F deduplicate on the event ID\n    w.WriteHeader(http.StatusNoContent)\n}",{"type":14,"level":15,"text":64,"id":65},"API","api",{"type":67,"columns":68,"rows":72},"table",[69,70,71],"Member","Returns","Notes",[73,77,81,85],[74,75,76],"`fingerly.New(secretKey string, opts ...Option)`","`*Client`","Options: `WithEndpoint`, `WithHTTPClient`.",[78,79,80],"`client.Events.Get(ctx, requestID)`","`(*Event, error)`","A non-2xx response returns `*fingerly.APIError` with `Status`.",[82,83,84],"`client.Events.List(ctx, *EventListParams)`","`(*EventPage, error)`","Params: `From`, `To` (`time.Time`), `Page`, `Limit`, `Visitor`, `Level`.",[86,87,88],"`fingerly.VerifyWebhook(secret, body, timestamp, signature)`","`bool`","Five minutes of tolerance. `VerifyWebhookWithTolerance` changes it.",[90,91,92,93,94,95],{"id":17,"text":16,"level":15},{"id":25,"text":24,"level":15},{"id":35,"text":34,"level":15},{"id":47,"text":46,"level":15},{"id":56,"text":55,"level":15},{"id":65,"text":64,"level":15},"2026-09-17T08:28:36.000Z",1789667797821]