Skip to navigation

Overview

Events notify you when important actions happen inside an organization. For example, Polytomic emits a sync.completed event every time a sync finishes.

You can consume events in two ways:

  • Poll the events endpoint.
  • Register a webhook to receive events in real time.

⚠️ At-most-once delivery

Polytomic delivers each event at most once and does not re-send events after delivery. If you need guaranteed processing of every change, build a fallback that polls the events endpoint in addition to consuming the webhook.

Retention

Polytomic retains events for 48 hours. After that they are no longer available from the events endpoint.

Event types

Each event type has its own page with the conditions that fire it, its fields, and an example payload.

Webhooks

Create and manage webhooks through the webhook API endpoints. A webhook fires events for the organization it belongs to. Each organization can have one webhook.

HMAC validation

Use HMAC validation to confirm that a delivered event came from Polytomic. When you create or update a webhook, you supply a secret. Polytomic signs each delivery with that secret and passes the signature in the Polytomic-Signature header. Compute the same HMAC on the request body and compare.

Delivery

Your endpoint must return a 2xx status code. If it does not, Polytomic retries the delivery up to five times with exponential backoff. Event ordering is not guaranteed.

Record logs

The sync.completed event includes logs_url, the endpoint that returns an index of the record logs the execution produced.

Consuming events

The following Go example receives a webhook delivery and verifies the HMAC signature:

package main
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"io/ioutil"
"net/http"
"github.com/gin-gonic/gin"
)
var key = []byte("somepassword")
func main() {
r := gin.Default()
r.POST("/webhook", func(c *gin.Context) {
body, _ := ioutil.ReadAll(c.Request.Body)
hash := c.Request.Header.Get("Polytomic-Signature")
sig, err := hex.DecodeString(hash)
if err != nil {
panic(err)
}
mac := hmac.New(sha256.New, key)
mac.Write(body)
if !hmac.Equal(sig, mac.Sum(nil)) {
panic("Invalid signature")
}
fmt.Printf("Headers: %+v, Body: %s", c.Request.Header, string(body))
c.Status(http.StatusOK)
})
r.Run("0.0.0.0:8000")
}