---
title: "Inbound event from partner (user.created, user.deleted)"
method: POST
path: "/api/v1/partner/webhook"
tags: ["Partners"]
---

# Inbound event from partner (user.created, user.deleted)

`POST /api/v1/partner/webhook`

## Request

- Base URL: `https://www.agenttax.io`
- URL: `https://www.agenttax.io/api/v1/partner/webhook`
- Auth: API key in header `X-AgentTax-Signature`

Partner-to-AgentTax event channel. Body is JSON; the event type is carried in `X-AgentTax-Event`.

**Authentication is HMAC over the raw body** (the partnerProvisioningKey scheme does NOT apply here):

- `X-AgentTax-Partner`: partner slug (e.g. `invoica`).
- `X-AgentTax-Signature`: `t=<unix-seconds>,v1=<hex>`. v1 = HMAC-SHA256(secret, body). ±5 min clock skew tolerance.
- `X-AgentTax-Nonce`: 8-128 char unique-per-request token. Replay-rejected if seen within the tolerance window.
- `X-AgentTax-Event`: one of `user.created`, `user.deleted`.

The response NEVER returns the API key — partner must call `/partner/provision` directly to obtain credentials. This prevents credential leakage via webhook replay attacks.

## Headers

- `x-agenttax-partner` string, required
- `x-agenttax-signature` string, required: HMAC-SHA256 of the raw body, formatted as `t=<unix-seconds>,v1=<hex>`.
- `x-agenttax-nonce` string, required: Unique per-request nonce. Replay-rejected if seen within the 5-minute tolerance window.
- `x-agenttax-event` 'user.created' | 'user.deleted', required: Inbound event type. Carried in `X-AgentTax-Event` header. Body is event-specific; see request schemas below.

## Request body

- union
  - PartnerWebhookUserCreatedBody
    - `external_id` string, required
    - `email` string, email
    - `display_name` string
  - PartnerWebhookUserDeletedBody
    - `external_id` string, required

## Response `200`

Event processed. Body never returns an `api_key` — call /partner/provision for credentials.

- PartnerWebhookResponse
  - `ok` true, required
  - `event` 'user.created' | 'user.deleted', required: Inbound event type. Carried in `X-AgentTax-Event` header. Body is event-specific; see request schemas below.
  - `partner_user_id` string
  - `agenttax_account_id` string
  - `already_provisioned` boolean
  - `found` boolean
  - `already_deleted` boolean
  - `entity_id` string

## Other responses

- `400`: Missing required header, malformed body, or unsupported event.
- `401`: Invalid HMAC signature OR nonce replay rejected.
- `404`: Partner slug not found or inactive.
- `500`: Server misconfiguration (e.g. webhook secret undecryptable).

---

[API](https://skmtc.dev/agenttax/apis/agenttax-api.md) · [All operations](https://skmtc.dev/agenttax/apis/agenttax-api/llms.txt) · [OpenAPI document](https://skmtc.dev/agenttax/apis/agenttax-api/revisions/c4af8147c0cb?raw)
