> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flokitai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Set up a receiver

> Configure an endpoint, install your Company's signing secret, and test delivery.

## Configure the endpoint

Endpoint setup, signing-secret reveal, and replay require authorized FloKit operator access. If you do not have that access, ask your FloKit operator to configure the endpoint and provide the signing secret through a secure channel. Your application implements the receiver; it does not need Admin credentials to receive events.

1. Open Admin and select **Webhooks**.
2. Select the **Endpoints** tab and click **Add endpoint**.
3. Select the Company, App, and environment.
4. Enter a descriptive name and the public HTTPS receiver URL.
5. Confirm **Initial successful subscription payment** and save the endpoint.
6. In **Webhook signing secret**, reveal and copy the Company's secret.
7. Store the secret in your server's secret manager and configure the receiver below.
8. Click **Send test** in Admin.
9. Open the delivery and confirm its status and attempt history.

Use a public HTTPS address with a valid TLS certificate. Localhost, private networks, metadata addresses, and redirects are rejected. Authentication uses the FloKit signature header; custom authorization headers are not supported. Keep the secret on your server and never put it in a browser bundle, URL, log, or analytics event.

The secret is shared by all endpoints for the selected Company. Revealing it requires privileged operator access and is audited. The Admin reveal hides automatically and when you navigate away.

## Accept durably

After [signature verification](/webhooks/signatures), validate the [payload](/webhooks/subscription-started) and accept it durably before acknowledging the request. The SQL below is an optional PostgreSQL implementation example for your receiver; FloKit neither requires nor provisions PostgreSQL, and you can use an equivalent atomic operation in another durable datastore.

```sql theme={null}
CREATE TABLE flokit_webhook_events (
  event_id TEXT PRIMARY KEY,
  payload JSONB NOT NULL,
  received_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE flokit_webhook_jobs (
  event_id TEXT PRIMARY KEY REFERENCES flokit_webhook_events(event_id),
  status TEXT NOT NULL DEFAULT 'pending'
);

-- Bind event_id and payload as parameters. Run both statements in one transaction.
WITH accepted AS (
  INSERT INTO flokit_webhook_events (event_id, payload)
  VALUES ($1, $2::jsonb)
  ON CONFLICT (event_id) DO NOTHING
  RETURNING event_id
)
INSERT INTO flokit_webhook_jobs (event_id)
SELECT event_id FROM accepted;
```

Commit before returning `200 OK` or `204 No Content`. A duplicate event is a successful acknowledgment with no new job. If the database transaction fails, return a retryable error. Your background job processes the accepted event independently.

Never use email, the Stripe Event ID, delivery ID, or an in-memory cache as the receiver's deduplication key. Use `event_id`. Protect the stored payload with access controls, encryption, and an appropriate retention policy; questionnaire answers may be sensitive.

## Test events

Admin **Send test** follows the same delivery pipeline and signature checks. These events contain `test_event: true` and obvious synthetic identifiers. Accept and deduplicate them normally, then skip business side effects. Test sends use the Company's actual signing secret.

`test_event` does not identify Stripe or another provider's Test mode. A real checkout in a provider test account is still a normal payment event without that flag. Use an isolated App and receiver for provider test purchases, and verify the connection's provider mode before testing. The payload's `environment` is the FloKit connection environment, not independent proof of provider Test/Live mode.

See [retries, dead deliveries, and replay](/webhooks/delivery-retries-and-troubleshooting) when a delivery does not succeed.
