---
title: "Renders the quota-threshold outreach for one identity **as it would go out right now**, and sends nothing."
method: GET
path: "/admin/identities/{email}/quota-outreach"
tags: ["admin"]
---

# Renders the quota-threshold outreach for one identity \*\*as it would go out right now\*\*, and sends nothing.

`GET /admin/identities/{email}/quota-outreach`

## Request

- Base URL: `https://api.mapmap.ai`
- URL: `https://api.mapmap.ai/admin/identities/{email}/quota-outreach`
- Auth: HTTP bearer

This exists so the copy can be read before a customer reads it. It
builds the same payload the webhook carries from the same live
counters, renders the same email body the mailer would send, and writes
nothing at all: no claim row, no mail, no webhook, no Slack post. Run
it twice and the answer is identical.

## Path parameters

- `email` string, required

## Response `200`

The payload and rendered copy; nothing is sent

- QuotaOutreachPreviewResponse: Response for `GET /admin/identities/{email}/quota-outreach`.
  - `already_fired` integer[], required: Thresholds already fired for this identity this period, ascending. Anything listed here will NOT fire again.
  - `email` string, required: Canonical (lowercased) identity email.
  - `email_body` string, required: Plain-text email body, as it would be sent.
  - `email_subject` string, required: Subject line the email would carry.
  - `identity_id` string, required: The identity the quota belongs to.
  - `payload` ThresholdPayload, required: The `quota.threshold` event, shared verbatim by the email, the webhook and the Slack message so the three can never disagree.
    - `days_left` integer, nullable: Whole days from now to `period_ends`; `None` when that is unknown.
    - `endpoint_advice` EndpointAdvice: The cheaper-endpoint nudge, when the period's shape supports one.
      - `docs` string, required: Where the matrix meter is documented.
      - `estimated_matrix_units` integer, required: What the same work would draw through `/matrix`, at one unit per [`MATRIX_ELEMENTS_PER_UNIT`] elements.
      - `kind` string, required: Stable machine tag; only one kind exists today.
      - `route_calls` integer, required: Units drawn by `/route*` in this period.
    - `event` string, required: Always `quota.threshold`.
    - `identity_id` string, required: The identity the quota belongs to (never a key id: quotas pool).
    - `period` string, required: Billing month, `YYYY-MM`.
    - `period_ends` string, nullable: RFC 3339 end of the period: the subscription's `current_period_end` when there is one, otherwise midnight UTC on the first of next month, which is when a calendar-month quota resets. `None` only when neither is known.
    - `plan` string, required: Plan label as stored on the identity (`free`, `starter`, …).
    - `projected_end_of_period` integer, required: `units_used + run_rate_per_day * days_left`: what this period ends at if nothing changes.
    - `quota` integer, required: The identity's monthly quota in units.
    - `recommended_plan` PlanTier: One published plan, as the outreach quotes it. **Source of truth is `website/public/pricing.json`**, in the same monorepo (`api.plans[]`: `id`, `included_calls`, `monthly_gbp`). The gateway has no pricing surface of its own, it stores a plan *label* and a per-key `monthly_quota`, never a tier table, so the three tiers are embedded here and held to that file by `embedded_tiers_match_published_pricing_json`, which reads it and fails if a number drifts. Change the price there, not here.
      - `name` string, required: Plan id as the pricing page and `identities.plan` spell it.
      - `price_gbp_month` integer, required: List price in whole pounds per month.
      - `units` integer, required: Included units per month.
    - `run_rate_per_day` integer, required: Units per day over the trailing [`RUN_RATE_WINDOW_DAYS`] (fewer days when the period is younger than that).
    - `threshold` integer, required: 50, 80 or 100.
    - `units_used` integer, required: Identity-pooled units drawn this period.
    - `upgrade_url` string, required: Where to upgrade.
    - `usage_url` string, required: Where to watch usage.
  - `period` string, required: Billing month the preview is for, `YYYY-MM`.
  - `rendered_threshold` integer, required: The threshold the rendered copy below is for.
  - `slack_message` string, required: The operator Slack line. Its "email sent / webhook sent" tail reads `not sent` here because this preview sends nothing.
  - `threshold_now` integer, nullable: The highest threshold this identity has crossed right now, or `null` when it is below 50%. The preview renders at this threshold when there is one, and at 50 otherwise, so copy can be reviewed for an identity that has not crossed anything yet.

## Other responses

- `401`: Missing or wrong admin token
- `404`: Unknown identity email

---

[API](https://skmtc.dev/mapmap/apis/sn-gateway.md) · [All operations](https://skmtc.dev/mapmap/apis/sn-gateway/llms.txt) · [OpenAPI document](https://skmtc.dev/mapmap/apis/sn-gateway/revisions/2293be8b4c38?raw)
