Customer API

Voice Rewrite API

Rewrite text in your voice seat from the writing app you already use. A human still copies and sends the result. Nothing auto-sends.

OpenAPI: /docs/voice-rewrite.openapi.yaml

Base URL

WhereURL
Local portalhttp://localhost:3000
Hosted Apographhttps://apograph.ai

Routes live under /api/v1. Give the HTTP client at least 120 seconds. Do not point production traffic at localhost. If a response includes "non_production": true, the seat used a desk URL — treat that as dogfood.

Auth

External apps send a Bearer tenant key. Generate a high-entropy secret, set APOGRAPH_TENANT_API_KEY on the portal host, and send the same secret from the writing app. Never put the key in the JSON body, in git, or in tickets. Rotate by generating a new secret, updating the host, then the app. A signed-in portal cookie also works for browser tools.

Authorization: Bearer $APOGRAPH_TENANT_API_KEY
Content-Type: application/json

POST /api/v1/voice/rewrite

Rewrite text in the caller’s seat. LUAR is scored in this response (a number, never null, never "async"). If LUAR cannot be scored, the call fails closed with luar_unavailable.

FieldRequiredNotes
textyesNon-empty after trim. Max 150000 characters.
voice_seat_idnoDefault c1rw. Unknown seats fail closed.
channelnoemail | linkedin_message | note | generic
polishnofalse (default) or "light"
max_wordsnoPositive number. Cap on the voiced draft.

Copy-paste curl

curl -sS -X POST "$APOGRAPH_BASE_URL/api/v1/voice/rewrite" \
  -H "Authorization: Bearer $APOGRAPH_TENANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'EOF'
{
  "text": "Thanks for the intro. I can walk through how we measure whether a draft still sounds like the author, then we can pick a time next week.",
  "channel": "email",
  "polish": false
}
EOF

POST /api/v1/voice/luar

Score-only LUAR after you edit or polish in the writing app. Same auth. Does not rewrite. Does not send.

Copy-paste curl

curl -sS -X POST "$APOGRAPH_BASE_URL/api/v1/voice/luar" \
  -H "Authorization: Bearer $APOGRAPH_TENANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'EOF'
{
  "text": "Thanks for the intro. I can walk you through how we score whether a draft still sounds like you, then we can find a time next week."
}
EOF

Errors

HTTPerrorWhat you do
401unauthorizedFix the key. Do not retry the same secret.
400bad_requestFix the body. message says which field.
503voice_unavailableRetry after the voice seat is on. No voiced_text.
503luar_unavailableDo not ship. Retry when scoring is up.

Product LUAR floor is 0.60. A 200 with luar_below_floor: true still includes voiced_text — you decide whether to copy. Token use is returned on rewrite as usage. There is no auto-send and no spend dashboard on this contract.

Wire it in

  1. Set APOGRAPH_TENANT_API_KEY on the portal host and in the writing app.
  2. Set APOGRAPH_BASE_URL to localhost or https://apograph.ai.
  3. POST rewrite. Read voiced_text and luar.
  4. If luar_below_floor or luar_unavailable, do not send.
  5. Paste the voiced text. The human hits send in that app.