Skip to content

Webhooks

getmyenv webhooks: signed HTTPS deliveries with HMAC SHA-256, up to 5 attempts, and the list of events. Names and metadata only, never values.

Last updated: 2026-09-28

Delivery

Webhooks are HTTPS POST requests to a URL you control: your own server, Zapier, Make, or any receiver that accepts JSON.

The project owner adds them in Project settings, Webhooks. Each webhook belongs to one project.

Events

  • variable.set, variable.unset, variable.deleted
  • variable.requested: a machine loaded values with run
  • context.created, context.updated, context.deleted
  • project.deleted
  • backup.created, backup.restored
  • member.invited, member.joined, member.keys_sent, member.removed
  • context.key_rotated, project.transferred

Payloads carry the project, the context, variable names, and member emails. Never values or keys.

Headers

  • X-Getmyenv-Event: the event name, for example variable.set.
  • X-Getmyenv-Delivery: a unique delivery id.
  • X-Getmyenv-Timestamp: seconds since the Unix epoch.
  • X-Getmyenv-Signature: HMAC SHA-256 in the form v1=<hex>.

Retries

Each delivery gets up to 5 attempts. Network errors, timeouts, 5xx responses, and 429 are retried after 1 minute, 5 minutes, 30 minutes and 2 hours. Each attempt times out after 10 seconds. 2xx responses count as delivered. Other 4xx responses are recorded and not retried. The next attempt time is stored with the delivery, so retries continue after a server restart. Redirects are not followed.

Each attempt resolves the host when it connects. Private, loopback, link-local, CGNAT, multicast and reserved addresses are refused, including IPv4 addresses inside IPv6.

Delivery statuses: pending, retrying, delivered, failed.

Verify a signature (Node)

javascript
import crypto from "node:crypto"; export function verifyGetmyenvSignature({ rawBody, timestamp, signature, secret, }) { const expected = "v1=" + crypto .createHmac("sha256", secret) .update(`${timestamp}.${rawBody}`) .digest("hex"); const a = Buffer.from(expected); const b = Buffer.from(signature); return a.length === b.length && crypto.timingSafeEqual(a, b); }

Reproduce with curl

bash
# Print the signing input for a captured delivery printf '%s.%s' "$X_GETMYENV_TIMESTAMP" "$RAW_BODY" \ | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" -hex