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

# Events

> The four things tracenow evaluates, what each event type represents, how status is determined, and why it matters for your rules.

Every `/trace` call is anchored to an **event**: a specific user action your system wants to
evaluate. Policies are scoped to event types, so the rules you write for a login are separate
from the rules you write for a signup, each with the signals and thresholds that make sense
for that action.

## Event types

| Event         | What it represents                                                   |
| ------------- | -------------------------------------------------------------------- |
| `signup`      | A new account creation attempt                                       |
| `login`       | An authentication attempt against an existing account                |
| `otp`         | A one-time passcode send request (SMS, voice, or email)              |
| `transaction` | A payment or other high-value action within an authenticated session |

Each event type gets its own **policy** under Guard. A policy for `signup` can deny
disposable emails and automation; a policy for `login` can deny credential stuffing based
on per-IP failure velocity (rules that would be irrelevant on the other type).

## Status

Every event has a status: `attempted`, `succeeded`, or `failed`.

| Status      | Meaning                                                                                                                          |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `attempted` | The request is being evaluated. Outcome is not yet known; this is the status at the edge before the request reaches your origin. |
| `succeeded` | The action completed successfully (account created, user authenticated, OTP sent, payment accepted).                             |
| `failed`    | The action was rejected by your system (wrong password, OTP rate-limit hit, payment declined).                                   |

### How status is determined

Status reaches tracenow in two ways depending on where the trace originates.

**At the Cloudflare edge (outcome trace)**

The Worker fires an initial trace with `status: attempted` before the request reaches your
origin. Once your origin responds, the Worker maps the HTTP response code to an outcome and
fires a second, non-blocking trace:

* `2xx` → `succeeded`
* `4xx` / `5xx` → `failed`

You configure this mapping per route when you set up the integration. The second trace is
async, so it adds zero latency to the user-facing response.

**In the in-app call**

When you call `/trace` from your backend, you set `status` directly to the real outcome
you observed. This is always more accurate than the HTTP-code mapping because your server
knows exactly what happened: a `200` login response could still mean a wrong-password
rejection depending on your API design.

<Note>
  The in-app call lets you pass `status: "failed"` even if your server returns `200`. Use it
  whenever your response shape doesn't map cleanly to HTTP codes.
</Note>

### Why status matters

Status is a first-class signal. You can write rules against `event.status` directly, which
unlocks the most powerful account-takeover patterns:

* **Credential stuffing:** `velocity.ip.failed_count_1h gt 5` AND `event.status eq "failed"`. Blocks an IP racking up login failures.
* **Suspicious success after failures:** `velocity.user.failed_count_1h gt 3` AND `event.status eq "succeeded"`. Challenges a login that succeeds after a brute-force run.
* **New country on success:** `ip.is_new_country_for_user` AND `event.status eq "succeeded"`. Challenges a login from a country the account has never used.

Without status, none of these conditions are expressible. Without the in-app call, the
outcome comes from HTTP code mapping. That is close enough for most apps, but the in-app call gives you exact control when you need it.

## Event × status reference

| Event         | Typical statuses                   | Notes                                                                                                     |
| ------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `signup`      | `attempted`, `succeeded`, `failed` | Edge fires `attempted`; outcome trace fires `succeeded`/`failed` once the account is created or rejected. |
| `login`       | `attempted`, `succeeded`, `failed` | `failed` is the key signal for credential stuffing and brute-force rules.                                 |
| `otp`         | `attempted`, `succeeded`, `failed` | `attempted` is the dominant signal for SMS pumping. The damage happens before the code is verified.       |
| `transaction` | `attempted`, `succeeded`, `failed` | `failed` can indicate card testing.                                                                       |

## What goes into an event

Beyond the type and status, a trace carries the signals tracenow enriches and evaluates:

```json theme={null}
{
  "event": "login",
  "status": "failed",
  "ip": "203.0.113.42",
  "email": "user@example.com",
  "phone": "+14155552671",
  "device_token": "dt_...",
  "subject_user_id": "usr_123",
  "visitor_id": "dv_...",
  "properties": {}
}
```

Send whatever you have. Not all fields are required. `subject_user_id` is only available
from the in-app call; the edge never has it. See [Server-side integration](/guides/server-side)
for the full field reference.

## Next steps

<Columns cols={2}>
  <Card title="Signals" icon="radar" href="/concepts/signals">
    Every field your rules can evaluate: IP, email, phone, device, velocity, and event status.
  </Card>

  <Card title="Rules" icon="sliders" href="/guides/rules">
    How to combine signals into conditions, and conditions into policies.
  </Card>
</Columns>
