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

# TARS internal admin API

> Internal SuperAdmin contracts for TARS analytics, email creative, and prospect-proposal preparation.

TARS uses internal REST endpoints and MCP tools for operator-only work. They
are available only to authenticated Apostra SuperAdmins and are not part of the
customer-facing Buyer or Seller API.

The Marketing mandate at `/tars/mandates/marketing` reads from three of these
REST endpoints. It combines search engine visibility, answer-engine visibility,
website journeys, and the existing canonical buyer-lead view. The standalone
marketing admin remains available until a later retirement slice.

## Authentication and errors

All REST endpoints use the normal API session or bearer-token authentication
and require the `superAdmin` role. Internal MCP tools are listed only for a
directly authenticated SuperAdmin and re-check that access when called.

* Invalid query parameters return `400`.
* A caller without SuperAdmin access receives `403`.
* An unavailable marketing database returns `503` without exposing connection
  details. The failure is logged and reported to Sentry.
* Journey responses can be `partial`: each unavailable tile has
  `{ "status": "unavailable", "data": null }`. Treat that state as unknown,
  not as a zero metric.

Dates use `YYYY-MM-DD`. Custom `from` and `to` values are inclusive, must be
provided together, and take precedence over `window`.

## Marketing email creative library

The Email library stores reusable drafts, approved creative, uploaded assets,
themes, previews, and immutable version history. It does not choose an
audience, enrol recipients, send email, or show delivery and sent-email
history. Those operations belong to separate sequence and delivery surfaces.

Use the model-visible `tars_open_marketing_email_library` tool to ask a
compatible TARS host to display the library. Its structured response includes
template, asset, and theme counts plus a bounded summary of the latest template
versions. A tool response confirms only that the host was asked to open the
library; it does not prove that the widget rendered.

The widget uses these app-only tools internally:

* `tars_get_marketing_email_library` loads templates, assets, and themes.
* `tars_get_marketing_email_template` loads one template and its version
  history.
* `tars_preview_marketing_email_version` renders one saved version with sample
  merge-token values.
* `tars_create_marketing_email_copy_draft` creates a reusable copy draft or
  saves a new version of an existing draft. The editor can place one active
  library image after the copy; older versions remain unchanged.
* `tars_approve_marketing_email_version` approves a draft version. The author
  cannot approve their own draft.

All six tools require a directly authenticated SuperAdmin. They are not
advertised to delegated service principals. Models should call only the owner
tool, `tars_open_marketing_email_library`; the widget owns the five app-only
calls.

The supporting REST surface is rooted at
`/api/v2/admin/marketing/email-library`. It is an internal Admin UI contract,
uses the same SuperAdmin boundary, and exposes library reads, template and
version writes, preview rendering, approval, and bounded asset upload. Invalid
input returns `400`, unauthenticated calls return `401`, and authenticated
callers without SuperAdmin access receive `403`.

## Prospect proposal preparation

`tars_open_prospect_proposal_authoring` is the read-only handoff from one TARS
organisation to the existing Commercial Offer authoring view. Supply at least
one of `orgRef`, `orgName`, or `customerId`. When a Harvian handoff must be
checked, also supply its exact `customerId`, protected `userRef`, or both under
`harvian`.

The tool resolves the existing organisation and canonical billing customer. It
returns one authoring URL when the match is safe. Otherwise it returns explicit
not-found, ambiguous Harvian, or missing-billing-customer blockers. It never
creates an account, research question, proposal, offer, Page, or customer, and
does not return contacts, interaction text, or private evidence.

The existing Commercial Offer service provides two matching preview routes:

* `POST /api/v2/admin/storefront-rate-cards/commercial-offers/preview` returns
  the resolved preview snapshot as JSON.
* `POST /api/v2/admin/storefront-rate-cards/commercial-offers/preview/document.pdf`
  renders that same snapshot as a downloadable PDF.

Both routes accept the same strict body:

```json theme={null}
{
  "schemaVersion": 1,
  "organizationName": "Example Publisher",
  "currency": "USD",
  "sourceRateCardId": "8",
  "sourcePlanId": "9",
  "narrative": {
    "documentTitle": "Proposal for Example Publisher",
    "executiveSummary": "A source-grounded summary for the prospect.",
    "scope": {
      "included": ["One included outcome"],
      "exclusions": ["One explicit exclusion"]
    }
  }
}
```

`effectiveAt` is optional and selects the published plan effective at that ISO
timestamp. The narrative is optional and bounded. Callers cannot submit
evidence through these routes; trusted evidence must come from the existing
Customer Knowledge path.

Previewing is non-mutating. Pricing, payment choices, term, support and
entitlements come from the selected published plan. The response is marked as
unissued, uses `Cache-Control: private, no-store`, and creates no customer,
offer, entitlement revision or acceptance record. Formal issuance continues
through the existing Commercial Offer authority.

## SEO overview

`GET /api/v2/admin/marketing/seo`

| Parameter    | Default | Allowed values                            |
| ------------ | ------- | ----------------------------------------- |
| `window`     | `30`    | `7`, `14`, `28`, `30`, `90`, `180`, `365` |
| `from`, `to` | —       | Inclusive date pair                       |
| `limit`      | `25`    | Integer from `1` to `100`                 |

The response contains:

* `freshness`: latest loaded date, row count, and synchronization time;
* `window`: the effective and available date bounds;
* `kpis`: current and prior impressions, clicks, click-through rate, and
  average position;
* `trend`: daily performance;
* `topPages`, `topQueries`, and `pageQueries`;
* `opportunities`: page/query pairs with at least 10 impressions whose
  impression-weighted average position is between 4 and 10, ordered by
  impressions.

Query rows include rank tier, tier movement, zero-click and AI-query flags, and
an at-risk signal. The first contract intentionally excludes live metadata
health and the model-generated digest from the legacy dashboard.

## Answer-engine visibility

`GET /api/v2/admin/marketing/aeo`

| Parameter    | Default | Allowed values            |
| ------------ | ------- | ------------------------- |
| `window`     | `30`    | Integer from `1` to `365` |
| `from`, `to` | —       | Inclusive date pair       |
| `limit`      | `10`    | Integer from `1` to `25`  |

The response supplies its fetch time and effective range, source status,
prompt/run totals, current and prior primary-brand mention rates, share of
voice by brand, performance by model, and the most-used citation URLs.

## Website journeys

`GET /api/v2/admin/marketing/journeys`

| Parameter    | Default | Allowed values            |
| ------------ | ------- | ------------------------- |
| `window`     | `30`    | Integer from `1` to `365` |
| `from`, `to` | —       | Inclusive date pair       |
| `pathSteps`  | `4`     | Integer from `2` to `4`   |

The response supplies its fetch time and effective range, overall source
status, current/prior traffic and conversion KPIs, source breakdowns, homepage
and converting paths, preview/contact/storefront funnels, and storefront signup
attribution. Each tile reports its own availability.

## Data-source configuration

The API process owns all credentials. The browser never receives database or
PostHog keys.

* `MARKETING_DATABASE_URL`: isolated `scope3_marketing` connection. Use a role
  with `SELECT`-only grants; the pool also sets PostgreSQL sessions read-only.
* `MARKETING_DB_POOL_MAX`, `MARKETING_DB_IDLE_TIMEOUT_MS`,
  `MARKETING_DB_CONNECTION_TIMEOUT_MS`, `MARKETING_DB_STATEMENT_TIMEOUT_MS`:
  optional pool limits and timeouts.
* `POSTHOG_API_KEY` and `POSTHOG_MARKETING_PROJECT_ID`: marketing-site HogQL
  reads.
* `POSTHOG_API_KEY_INTERCHANGE` and `POSTHOG_INTERCHANGE_PROJECT_ID`:
  Apostra signup-attribution reads.

Missing PostHog keys degrade the affected journey tiles instead of fabricating
zero values. Marketing database access has no fallback to the application or
ledger databases.
