# Rewrite Copy

> Rewrite one flagged sentence or the whole draft. Costs 1 AI credit.

<Note>
  **Beta.** This endpoint is not in production yet and may change before it ships.
</Note>

Asks the chat model to rewrite the copy, then has the Copy check accept or discard the result. Nothing is saved: the rewrite is returned for you to apply. Costs **1 AI credit** from the key owner's monthly pool once the model has answered, whether or not the check accepts the rewrite. A `422` or a `502` from the model is not charged.

## Body Parameters

<ParamField body="subject" type="string">
  Subject line, up to 500 characters.
</ParamField>

<ParamField body="body" type="string">
  Email body, plain text or HTML.
</ParamField>

<ParamField body="sendAsHtml" type="boolean" default="false">
  Set to `true` when the body is HTML.
</ParamField>

<ParamField body="stepNumber" type="integer" default="1">
  Sequence step the copy belongs to (1-50).
</ParamField>

<ParamField body="target" type="object" required>
  What to rewrite.
  <Expandable title="target">
    <ParamField body="kind" type="string" required>`email` for the whole draft, `span` for one sentence.</ParamField>
    <ParamField body="field" type="string">For a span: `subject` or `body`.</ParamField>
    <ParamField body="start" type="integer">For a span: start offset in the text returned by `/copy/judge`.</ParamField>
    <ParamField body="end" type="integer">For a span: end offset.</ParamField>
    <ParamField body="text" type="string">For a span: the exact sentence at `start` to `end`.</ParamField>
    <ParamField body="category" type="string">For a span: the flag category from `/copy/judge`.</ParamField>
  </Expandable>
</ParamField>

<ParamField body="signals" type="array">
  Overall problems from a previous `/copy/judge` call, to steer the rewrite.
</ParamField>

## Response

For `kind: "email"`:

<ResponseField name="data" type="object">
  <Expandable title="Email rewrite">
    <ResponseField name="subject" type="string">Rewritten subject.</ResponseField>
    <ResponseField name="bodyText" type="string">Rewritten body.</ResponseField>
    <ResponseField name="verdict" type="object">Copy check verdict for the rewritten draft, same shape as `/copy/judge`.</ResponseField>
  </Expandable>
</ResponseField>

For `kind: "span"`, `data` holds `replacement`, `accepted`, `keepProbability` and `issue`.

<RequestExample>
```bash cURL
curl -X POST "https://api.foxreach.io/api/v1/copy/rewrite" \
  -H "X-API-Key: otr_your_key" \
  -H "Content-Type: application/json" \
  -d '{"subject": "Quick question", "body": "Hi {{firstName}}, ...", "target": {"kind": "email"}}'
```

```python Python (beta)
from foxreach import FoxReach

client = FoxReach(api_key="otr_your_key")
result = client.copy.rewrite("Quick question", "Hi {{firstName}}, ...")
print(result["bodyText"])
```

```typescript TypeScript (beta)
import { FoxReach } from "foxreach";

const client = new FoxReach({ apiKey: "otr_your_key" });
const result = await client.copy.rewrite({ subject: "Quick question", body: "Hi {{firstName}}, ..." });
console.log(result.bodyText);
```
</RequestExample>

<ResponseExample>
```json
{
  "data": {
    "kind": "email",
    "subject": "Quick question",
    "bodyText": "Hi {{firstName}}, who handles outbound at your company?",
    "verdict": {"score": 93, "placement": "inbox", "summary": "Reads like a personal note.", "signals": [], "flags": [], "words": []},
    "subjectText": "Quick question",
    "judgedBodyText": "Hi {{firstName}}, who handles outbound at your company?"
  }
}
```
</ResponseExample>

## Errors

| Status | Description |
|--------|-------------|
| `400` | A span rewrite is missing `field`, `start`, `end` or `text`, or the draft is empty |
| `403` | `ai_credits_exhausted`: the monthly AI credits are used up, or the key is read-only |
| `409` | The draft no longer matches the span. Run `/copy/judge` again |
| `422` | The model's rewrite was discarded (it added merge tags that are not in your draft). Not charged |
| `502` | The model could not be reached. Not charged for a model failure, retry shortly |
| `503` | Rewriting is unavailable on this server |

## Rate Limit

- **100 requests per minute, shared by every `expensive` call in your workspace.** Fixed 60-second window.
- Every response includes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` (unix epoch seconds) and `X-RateLimit-Bucket` (`expensive`).
- A `429` response includes a `Retry-After` header (seconds until the bucket resets).

For client-side patterns (`Retry-After`, exponential backoff, monitoring `X-RateLimit-Remaining`), see [Rate Limiting](/rate-limiting).
