# Security

A Ha Tang integration holds several secrets: API keys, webhook signing secrets, the chat identity secret and the Payments secret key. This page is a checklist for keeping each one safe, limiting what a leaked one can do, and verifying everything that reaches your servers.

## Know your credentials

| Credential | Looks like | Where it lives | Secret? |
|---|---|---|---|
| API key | `ht_...` | Your server only | Yes |
| Webhook signing secret | `whsec_...` | Your server only | Yes |
| Chat identity secret | shown once on the website's page | Your server only | Yes |
| Payments secret key | `sk_...` | Your server only | Yes |
| Chat site id | `site_...` | Your web pages and apps | No, it is public |
| Mobile app key | `hak_...` | Inside your app build | No, but revocable |

Anything marked secret must never appear in browser JavaScript, a mobile app, a public plugin, a Git repository or a support ticket. Keep it in environment variables or a secret manager.

## API keys

- **Give each key only the scopes it needs.** A server that only sends email needs `email:send`, not `*` ([Authentication](https://hatang.dev/docs/guides/getting-started/authentication.md#scopes)).
- **Use one key per service or environment**, named after where it runs. You can then revoke one without touching the others, and the **Last used** column tells you which ones are still in use.
- **Restrict keys.** Lock an email key to one **Sending domain**. Only if a key must run in a browser, fill in **Browser origins**; requests from any other origin are refused ([Restricted keys](https://hatang.dev/docs/guides/getting-started/authentication.md#restricted-keys)).
- **Rotate keys** when someone who knew them leaves, after a suspected leak, and on a schedule: create the new key, deploy it, then revoke the old one. A revoked key stops working within a minute.
- **Audit usage.** **Email → Logs** lists every API request with the key that made it, the user agent, the status and the bodies. Unexpected callers or endpoints are a sign of a leak.

Keys are shown only once when created. Ha Tang stores only a hash, so a lost key cannot be recovered; create a new one.

## Webhooks

- **Verify every delivery.** Check the signature over the raw body and reject deliveries whose timestamp is more than 300 seconds old ([Webhooks](https://hatang.dev/docs/guides/getting-started/webhooks.md)). Deliveries are authenticated by their signature, not by where they come from. The `user-agent: hatang-webhooks/1.0` header is informative only.
- **Use HTTPS endpoints.** Ha Tang only delivers to public `https` URLs and does not follow redirects.
- **Rotate the signing secret** if it may have leaked. For 24 hours after a rotation, deliveries carry signatures from both the old and the new secret, so you can deploy without dropping events.
- **Deduplicate on `svix-id`** so a replayed or retried delivery cannot trigger the same action twice.
- **Payments IPN calls** to your `ipn_url` are signed separately, with `Hatang-Signature` and the environment's secret key. See [Verify IPN](https://hatang.dev/docs/guides/payments/verify-ipn.md).

## Chat identity

- **Verify identities.** When your site or app tells the chat who a user is, include the `hash` (HMAC-SHA256 of the user id with the site's identity secret) computed on your server. Without it, anyone could claim to be another customer and read their history ([Identity verification](https://hatang.dev/docs/guides/support/web-widget/identity-verification.md)).
- **Keep the identity secret on your server**, and rotate it with **Rotate & reveal** if it may have leaked. Hashes made with the old secret stop verifying at once.
- **Limit where the widget runs.** The widget only starts on your website's domain, its subdomains and the **Extra allowed origins** you list. Remove preview and localhost origins you no longer use.
- **Revoke mobile app keys** you no longer ship, after releasing an app version with a new key.

## Payments

- Keep the secret key of each environment on your server and check `environment` on every Payments event and IPN, so a development payment never fulfils a real order.
- A `ht_test_` key can never reach production data. Production access is chosen per request with `Hatang-Environment` ([Payments environments](https://hatang.dev/docs/guides/payments/environments.md)).

## SMTP relay

The SMTP relay at `smtp.hatang.dev:5870` uses STARTTLS, with the username `hatang` and an API key as the password. Give that key only the `email:send` scope. After 10 failed sign-in attempts from one IP address, the relay refuses further attempts from that address for 15 minutes.

## Your team

- Give employees the lowest access level that lets them do their job, and keep **Developer** access, which can create API keys and webhooks, to the people who need it ([Team and roles](https://hatang.dev/help/account/employees-and-roles)).
- Remove people who leave from **Settings → Employees**, and rotate the API keys and secrets they knew. Their keys keep working until you revoke them, because keys do not belong to a person.

## If a secret leaks

1. **API key:** revoke it in **Settings → API Keys**, create a replacement, and check **Email → Logs** for calls you did not make.
2. **Webhook secret:** rotate it and deploy the new one within 24 hours.
3. **Identity secret:** click **Rotate & reveal** and update your servers.
4. **Payments secret key:** replace it in **Payments settings → Integration keys** and update your servers.

## Next steps

- [Authentication](https://hatang.dev/docs/guides/getting-started/authentication.md)
- [Webhooks](https://hatang.dev/docs/guides/getting-started/webhooks.md)
- [Identity verification](https://hatang.dev/docs/guides/support/web-widget/identity-verification.md)

Source: https://hatang.dev/docs/guides/getting-started/security
