---
title: "Engagement history for an address"
method: GET
path: "/v1/activity/{email}"
tags: ["Activity"]
---

# Engagement history for an address

`GET /v1/activity/{email}`

## Request

- Base URL: `https://api.kawaa.com`
- URL: `https://api.kawaa.com/v1/activity/{email}`
- Auth: one of:
  - API key in header `X-Api-Key`
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.kawaa.com/oauth/authorize`, token URL `https://api.kawaa.com/oauth/token`, scopes: `verification:write`)

Opens and clicks that your own account's Kawaa tracking pixels and tracked links have recorded for the address. Only your account's tracking counts: engagement another Kawaa customer's tracking observed for the same address is never returned. Charges 0.5 credits.

This is engagement history, not a verification: it says nothing about whether the mailbox exists. An address your tracking has recorded nothing for comes back with `level: "unknown"` and `confidence: 0`, which means "we have nothing", not "this address is inactive".

**Without a key, an identical repeat inside 15 minutes is not charged again.** Without an `Idempotency-Key`, the same account asking for the same address (spelled exactly the same way) within 15 minutes of the lookup that was charged gets that lookup's stored answer back, with `credits_used: 0` and `idempotent_replay: true`, so a GET that an HTTP client, proxy or browser resends on its own costs nothing more. Concurrent copies are charged once. The window counts from the charge and a replay does not extend it: the first repeat after it is a new 0.5-credit lookup with a fresh read. Engagement recorded inside the window therefore shows up after it; to buy a fresh read sooner, send a new `Idempotency-Key`. A key keeps its own 24-hour receipt, separate from this window. A lookup that was charged but never answered (its request failed after the charge) is finished free by the next identical repeat, even after the window. Another account's lookup is never replayed to you.

## Path parameters

- `email` string, email, required

## Headers

- `Idempotency-Key` string

## Response `200`

What is known about the address.

- object
  - `success` unknown, required
  - `data` EmailActivity, required
    - `email` string, email, required: The validated address, echoed unchanged from the path. Malformed or whitespace-padded values are refused before the paid lookup begins.
    - `email_hash` string
    - `activity` ActivityData, required
      - `level` 'active' | 'inactive' | 'dormant' | 'unknown', required: How recently this address was seen active. `inactive` sits between the active and dormant windows; `unknown` means there was nothing to judge from, not that the address is inactive.
      - `score` number, required
      - `last_activity_at` string, date-time, nullable, required
      - `engagement` object, required
        - `open_count` integer, required
        - `click_count` integer, required
        - `reply_count` integer, required: Counts replies recorded by Kawaa email warmup campaigns only. It is not a measurement of replies to your own mail, which Kawaa cannot see. Warmup is switched off, so no new replies are recorded, and new opens and clicks come only from your own tracking pixels and links.
      - `deliverability` object, required
        - `bounce_count` integer, nullable, required
        - `complaint_count` integer, nullable, required
      - `confidence` number, required: 0 means your account has recorded no activity for this address, not that it is inactive.
      - `data_points` integer, required
      - `message` string: Present only when no activity data is available for a single-address lookup.
    - `credits_used` number, required
    - `credits_remaining` number: The account's balance after this call. On a charged lookup, the balance the charge left. On a replay (`idempotent_replay: true`), the current balance as read when the replay authenticated, or, for a copy racing the charge, the lower of that and what the charge left. Absent when the balance could not be read.
    - `idempotent_replay` boolean: True when this repeated an earlier lookup and therefore charged nothing: one under the same `Idempotency-Key` (that receipt lasts about 24 hours), or, without a key, the same address looked up by the same account within 15 minutes of the lookup that was charged. **Absent means it was charged**: the field is added only on a replay. `credits_used: 0` alone cannot tell you which happened, because a lookup with nothing to bill also reports 0; this is the field that distinguishes them.

## Other responses

- `400`: The request is malformed, or names a field this endpoint does not accept. Retrying it unchanged will fail identically.
- `401`: No credential, or one that is not accepted. `code` distinguishes `API_KEY_SUSPENDED` (subscription ended; restartable) from `API_KEY_REVOKED`, `SESSION_EXPIRED` and `OAUTH_TOKEN_EXPIRED` (a connected app's one-hour access token lapsed: refresh it and retry, or sign in again if no refresh token was issued or the refresh is refused).
- `402`: The account cannot pay for this request. The message carries the numbers and where to top up. Nothing was charged.
- `403`: Refused, and **the code says which of three problems it is**, and they need different remedies: - `INSUFFICIENT_SCOPE`: the credential is valid but not scoped for this route. With an API key, issue one that carries the scope named in the message. With an OAuth access token, connect the app again asking for that scope as well as the ones it has, unless the message says a connected app can never be given it; then use an API key with every scope the message names, or have the account owner do it in the dashboard. - `PLAN_UPGRADE_REQUIRED`: the account's plan does not include the feature. **No key of any scope reaches it**, so issuing another is wasted work; the remedy is a plan change. Returned by the verification routes for `options.enrich`, and by the finder, the monitors, the audit log, auto-clean and the white-label routes. - `PLAN_LIMIT_EXCEEDED`: the plan includes the feature and the account is at its ceiling (webhook endpoints, team seats, integrations, auto-clean lists). Delete one or upgrade. - `FORBIDDEN`: refused for a reason none of the above covers. `ErrorCode` is an open set, so branch on the code with a default rather than exhaustively.
- `409`: The `Idempotency-Key` was used before for a different request on this route. No credit moved. Repeat the original request exactly, or use a new key.
- `429`: Too many requests. When the server knows how long to wait, `Retry-After` says so and `error.retry_after_seconds` carries the same number; the `X-RateLimit-*` headers say where you stand.
- `500`: The lookup was charged for and then failed, or its result could not be stored. The refund is attempted and can itself fail, leaving the charge unsettled, which is what makes this materially different from the 503 beside it, where nothing was charged. Check `GET /v1/usage` before paying for another attempt. While a charge stands, an identical repeat inside its replay window (the key's 24 hours, or 15 minutes without a key) finishes that lookup instead of buying another.
- `503`: The retry protection for this lookup could not be resolved, a concurrent attempt was refunded, or this copy's read failed while the request that paid for the same lookup was still running (its charge is left to that request, which stores its answer or refunds). Nothing was charged for this request. **With a key, retry with the SAME key**: a new one buys the lookup again. Without one, repeat the identical request: it is answered from the charge that stands, if one does, rather than bought again.
- `default`: Any status this operation does not list. Kawaa's own errors carry the error envelope. The gateway in front of the API can answer any operation with its own bare body (`GatewayError`): a `503` after about 29 seconds, when the request may still have run and been charged, a `413` for a body over about 6 MB, or a `400` for a path with malformed percent-encoding.

---

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