# GreenHill ReportQuest API Agent Guide

This public guide bootstraps an agent that has no ReportQuest source code or internal documentation. It explains authentication and contract discovery. After discovery, generated OpenAPI and Reporting Recipes are the authoritative consumer contracts.

Base URL: `https://api.reportquest.com`

## Required user input

The user should supply:

- a ReportQuest API key, personal access token (PAT), or already-issued access token;
- the expected client or user identity when available;
- an account reference, normally an account number, account name, or external identifier;
- the reporting question and requested dates; and
- the desired output, such as a concise answer, presentation-neutral report specification, Markdown report, PDF, or spreadsheet.

The agent determines the credential type. Do not ask the user to classify it.

## Credential recognition

Normalize a credential by trimming surrounding whitespace. If it includes the prefix `Bearer ` or `Token `, compare that prefix case-insensitively and use the value following it.

A ReportQuest access token:

- has exactly three non-empty segments separated by two periods;
- uses Base64URL characters (`A-Z`, `a-z`, `0-9`, `-`, and `_`) in each segment; and
- is already the credential required by authenticated endpoints.

A ReportQuest API key or PAT:

- is exactly 65 characters;
- starts with the version character `1`;
- has 64 remaining characters from the uppercase Base32 alphabet `A-Z` and `2-7`; and
- contains no periods.

ReportQuest API keys and PATs remain valid until they expire or are revoked. Use them directly with the Bearer scheme.

If a supplied value matches neither format, do not transmit it. Report that it is not a recognized ReportQuest credential.

## Credential security

- Send credentials only to the configured ReportQuest API base URL over HTTPS.
- Put credentials only in the `Authorization` request header.
- Never put a credential in a URL, query string, command output, report, source file, or diagnostic message.
- Keep the API key or PAT and access token only in memory for the current task.
- Redact authorization headers from request traces and errors.
- Do not include credentials in generated scripts unless the script reads them from a secure runtime secret.

## Obtain or use a Bearer credential

For protected requests, use the PAT or API-issued access token directly:

```http
Authorization: Bearer <PAT_OR_ACCESS_TOKEN>
```

Exchanging a PAT for a time-limited API JWT is optional:

```http
POST /api/v1/Auth/Token
Authorization: Token <API_KEY_OR_PAT>
```

The request body is empty. A successful response has this shape; expiration values below are illustrative and the returned values are authoritative:

```json
{
  "access_token": "<ACCESS_TOKEN>",
  "token_type": "Bearer",
  "expires_in": 3600,
  "expires_at": "2026-08-13T18:00:00-04:00"
}
```

Use `access_token` in memory with the Bearer scheme. The exchange does not invalidate the PAT.

If the supplied credential is already an access token, skip the exchange. PATs can also skip the exchange and be used directly. The token endpoint exchanges API keys and PATs; it does not renew or echo an existing access token.

## Verify identity and discover the contracts

Before retrieving account or report data, make these requests with the Bearer credential:

1. `GET /api/v1/Users/WhoAmI`
2. `GET /swagger/v1/swagger.json`
3. `GET /api/v1/Reporting/Recipes`

If the user supplied an expected client or user, compare it with WhoAmI. Stop before retrieving client data if they conflict. If no expected identity was supplied, retain the returned identity as report provenance.

Use the contracts in this order:

1. OpenAPI defines actual operations, authentication, parameters, defaults, response schemas, field meanings, units, scales, dates, null behavior, ordering, warnings, and errors.
2. Reporting Recipes define how operations may be safely combined, which response fields to select, what context to preserve, which calculations are prohibited, and which limitations must be disclosed.
3. This guide is bootstrap guidance only. It never overrides OpenAPI or Reporting Recipes.

Retrieve both contracts before attempting an analytical report. Follow recipe operation IDs back to OpenAPI for the HTTP request and response definitions.

## Resolve an account reference

`accountId` is an opaque internal GreenHill identifier. It uniquely identifies an entitled individual or composite account for downstream API operations, but it has no semantic meaning to the user.

An `accountId` is durable for the current API session and expected to remain stable for the foreseeable future. It should not be stored as a permanent external account key because GreenHill may change it in the future. Retain the user's account number or external identifier as the durable, user-facing reference.

Users almost always identify an account by account number. Resolve it using one of these OpenAPI operations:

- Direct lookup: `GET /api/v1/Account?accountNumber=<URL_ENCODED_ACCOUNT_NUMBER>`. Add `accountGroupId=<AGI>` when the account number alone is ambiguous. This returns detailed information for one entitled account.
- Search: `GET /api/v1/Accounts?searchText=<URL_ENCODED_SEARCH_TEXT>`. This searches entitled accounts case-insensitively by account number, account name, or short name and returns paginated summaries.
- External identifier: use the `externalIdentifier` parameter on `GET /api/v1/Account` only when the user or integration identifies the account that way.

Do not require the user to know an `accountId`. After resolution, use the returned `accountId` for other operations during the current task or API session. Preserve both `accountId` and the user-facing account number in report provenance.

## Build an analytical answer or report

1. Match the user's intent to a Reporting Recipe.
2. If no recipe matches, determine whether one OpenAPI operation directly answers the question. Otherwise report the requested capability as unsupported.
3. Resolve the account and explicit requested dates.
4. Call only operations required by the recipe or direct answer.
5. Apply only documented deterministic selection, joining, sorting, ranking, top-N, and composition rules.
6. Preserve requested and effective dates, date adjustments, identifiers, messages, calculation issues, source operation IDs, unsupported disclosures, and relevant known gaps.
7. Return partial results only when the missing portion and its consequence are explicit.

Do not calculate, geometrically link, aggregate, or annualize returns. Do not calculate contribution, attribution, risk, yield, composite returns, or benchmark returns. Do not replace null with zero or fabricate historical holdings, classifications, policy targets, currency, freshness, benchmark identity, or methodology. Use only calculations and projections explicitly authorized by the authenticated contracts.

Generating a configured report job is a server-side action and may be resource intensive. Do not start a report job unless the user explicitly asks for that output. Contribution operations may also be resource intensive; call them only when required and do not poll them repeatedly.

## Common authentication failures

- `401` from the token endpoint: the API key or PAT is invalid, expired, revoked, or was sent with the wrong authorization scheme. The PAT can still be used directly with the Bearer scheme if it remains valid.
- `401` from OpenAPI, Recipes, or another authenticated endpoint: the JWT or PAT is invalid, expired, or revoked. Obtain a current credential instead of repeatedly retrying.
- `403`: the authenticated user lacks permission for the operation or resource. Do not attempt to bypass authorization.
- WhoAmI identity mismatch: stop before retrieving client data and report the mismatch.
- Account lookup returns no match: verify the account number, try the entitled-account search operation, and preserve the no-match result. Do not guess an `accountId`.
- Account search returns multiple plausible matches: use account number, account group ID, name, and the user's stated context to resolve the intended account; disclose remaining ambiguity rather than selecting arbitrarily.

## Minimal successful bootstrap

A zero-context agent is ready to answer ReportQuest questions when it has:

1. recognized or exchanged the credential without exposing it;
2. verified WhoAmI;
3. loaded the current OpenAPI document;
4. loaded the current Reporting Recipes manifest;
5. resolved the user's account reference to an entitled `accountId`; and
6. retained the source operations, effective dates, warnings, and limitations needed for the answer.
