# Architecture & security

URL: https://supapulse.app/docs/data-privacy/architecture

How Supapulse is built, how ingest requests are checked and processed, how tokens work, and who can see your data.

## The stack [#the-stack]

- A Laravel application serves the dashboard, the API and the marketing site.
- PostgreSQL stores sites, pageviews, events and revenue.
- Ingest events go onto a queue. Separate worker processes store them, so a traffic spike slows processing down instead of failing requests.
- A WebSocket server pushes live updates to the dashboard.
- Export files and contact-form attachments are stored in DigitalOcean Spaces.
- Billing runs through Stripe Checkout; card details go to Stripe, not Supapulse.

Supapulse runs in one hosting region. There's no choice of data location.

## What the ingest API checks [#what-the-ingest-api-checks]

Each `POST /api/ingest` goes through these checks, in order:

1. **Rate limit.** 2,000 requests per hour per IP address, then `429`.
2. **Token present.** From the `X-API-Token` header or the `token` field, else `401`.
3. **Token format.** Must start with `pub_` or `sec_`, else `401`.
4. **Token valid.** Must belong to an active site, else `401`.
5. **Origin.** If the request has an `Origin` or `Referer` header, its host must be the site's domain or a subdomain of it, else `403`.
6. **Event type.** Public tokens can send `pageview` and `event`; secret tokens can also send `revenue`. Anything else is `422`.

Only then is the event queued and `202` returned.

## Tokens [#tokens]

| | Public (`pub_…`) | Secret (`sec_…`) |
| --- | --- | --- |
| Lives in | Your pages | Your server's environment |
| Can send | Pageviews, events | Pageviews, events, revenue |
| Shown in the dashboard | Always | Once, right after you regenerate it; masked after that |
| Regenerate | Site settings | Site settings |

Regenerating a token invalidates the old one at once. Each token is 32 random characters after its prefix.

## Who can see a site's data [#who-can-see-a-sites-data]

Sites belong to teams. Team members have one of four roles: owner, admin, member or viewer. Accounts can turn on two-factor authentication. Supapulse staff with admin access can see accounts and sites to provide support.

## Data handling [#data-handling]

- IP addresses and user agents travel with each queued job until it runs. They're never written to pageview, event or revenue records.
- Visitor hashes use a per-site salt that rotates every 24 hours by default.
- See [Privacy & compliance](https://supapulse.app/docs/data-privacy/privacy) for retention.

## Reporting a security issue [#reporting-a-security-issue]

Email [support@supapulse.app](mailto:support@supapulse.app) with the details and how to reproduce them. Please don't test against other customers' sites or data.
