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

# RFP lifecycle

> Create a seller RFP, poll its turns, revise, grade and endorse responses, render them, and measure RFP performance.

An **RFP** is one commercial opportunity on your storefront: a buyer's brief that arrived over AdCP, one
you typed in, one you imported, or a practice brief. An **RFP turn** is one request and the storefront
agent's response to it. Turns are immutable: revising a response appends a new turn instead of
rewriting the old one.

You can work RFPs in the [Demand inbox](/sell/demand-inbox) and the proposal studio
(`open_page` with `page: "proposal_studio"`), or entirely over MCP with `save_rfp`. The account must be
a seller account.

## Create an RFP and poll the turn

```json save_rfp theme={null}
{
  "action": "create",
  "origin": "manual",
  "purpose": "draft",
  "request": {
    "brief": "Reach high-intent home cooks with premium video this autumn.",
    "budget": "125000",
    "currency": "USD",
    "channels": ["olv", "ctv"],
    "countries": ["US"]
  },
  "strategy": { "posture": "hold_value" }
}
```

| Field      | Notes                                                                                                                                                              |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `origin`   | `adcp` (a buyer's request), `manual`, `imported` or `starter`.                                                                                                     |
| `purpose`  | `live` (a real opportunity), `evaluation` (practice, graded) or `draft`.                                                                                           |
| `request`  | `brief` (required, up to 20,000 characters), `budget`, `currency`, `flight`, `channels`, `formatKinds`, `countries`, `constraints`, `productCount`, `instruction`. |
| `strategy` | Optional. `posture`: `hold_value` (anchor on your default prices), `win_share` (lean toward the floor) or `pass` (decline).                                        |

The call returns at once with `rfpId`, `turnId` and `turnState`. Poll the turn with `get`
(`kind: "rfp_turn"`, the `turnId`) or `GET /api/v2/storefront/rfp-turns/{id}`:

`queued → processing → ready | passed | needs_clarification | failed`

| State                 | Meaning                                                                                                                |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `ready`               | A response with products, prices and budget allocations. Its decision is `pitch` or `counter_pitch`.                   |
| `passed`              | A deliberate decision not to propose, with the reason, for example a brief that conflicts with your acceptance policy. |
| `needs_clarification` | No products; the response lists what must be resolved. Fix the catalog or the request, then append a turn.             |
| `failed`              | The run failed. Don't keep polling it.                                                                                 |

A counter-pitch can carry `limitations`, for example an age range none of the products can deliver
(see [Targeting](/buy/targeting#age-ranges-in-briefs)).

## Continue the lifecycle

`save_rfp` takes one `action` at a time; fields from another action are refused.

| `action`                 | Needs                                           | Does                                                                                                     |
| ------------------------ | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `create`                 | `origin`, `purpose`, `request`                  | Creates the RFP and its first turn, and queues the response.                                             |
| `append_turn`            | `rfpId`, `parentTurnId`, `request`              | Adds a revision turn (coach and re-run) and queues it.                                                   |
| `record_feedback`        | `rfpId`, `turnId`; `grade`, `ledBy`, `feedback` | Grades a response (`A`–`F`), says who led it (`agent` or `human`), adds a note (up to 4,000 characters). |
| `endorse`                | `rfpId`; optional `commentary`                  | Endorses the RFP's response as a good example.                                                           |
| `unendorse`              | `rfpId`                                         | Removes the endorsement.                                                                                 |
| `attach_response`        | `rfpId`, `materialId`                           | Attaches an uploaded or historical proposal from your [Library](/sell/library) as the response.          |
| `request_representation` | `rfpId`, `turnId`, `representation`             | Renders the response as a file.                                                                          |
| `cancel_representation`  | `rfpId`, `representationId`                     | Cancels a render that hasn't finished.                                                                   |

Over REST, `POST /api/v2/storefront/rfps` takes the same actions; `GET /rfps` and `GET /rfps/{id}` read
RFPs with their turns.

## Render a response

`request_representation` with `representation.format`:

| `format`               | Result                 |
| ---------------------- | ---------------------- |
| `html`                 | A proposal page.       |
| `pdf`                  | A PDF of the proposal. |
| `seller_response_json` | The response as JSON.  |

`representation.audience` is `buyer_delivery` (the default: what you send a buyer) or `seller_preview`
(for your own review). Representations move through `queued`, `processing`, `ready`, `failed` and
`canceled`. Download a ready one with `GET /api/v2/storefront/rfp-representations/{id}`.

PowerPoint (`pptx`) isn't available yet and is refused with `CAPABILITY_NOT_SUPPORTED`.

## RFP performance

`get_rfp_performance` (optional `range` and `metrics`) reports:

| Metric                          | Label                  | Meaning                                                       |
| ------------------------------- | ---------------------- | ------------------------------------------------------------- |
| `win_rate`                      | Win rate               | Won RFPs out of those decided.                                |
| `booked_budget`                 | Booked budget          | Budget booked from won RFPs.                                  |
| `average_grade`                 | Average grade          | Mean of recorded grades.                                      |
| `buyer_response_rate`           | Buyer response rate    | RFPs with a grade or a commercial result, out of all RFPs.    |
| `acceptance_rate`               | Answered with an offer | Finished turns that ended `ready`, out of all finished turns. |
| `average_processing_latency_ms` | Average response time  | Mean time from a turn's creation to its final state.          |

A metric with no inputs is reported as unavailable, never as 0.

## Not available yet

* Releasing a turn for delivery and recording the commercial outcome over MCP (`release_turn`,
  `record_outcome`).
* Required Library units and endorsed pairs that a turn must follow, and buyer-proposal JSON.

## Related

* [Demand inbox](/sell/demand-inbox)
* [Playbook](/sell/playbook)
* [The storefront agent](/concepts/storefront-agent)
