Developer Documentation

Integrate Appfora's Legal and Support APIs into your application. Get your API key, make your first call, and ship.

Quick Start

  1. 1Create an account and scan your repository
  2. 2Navigate to your product → API KeysCreate key
  3. 3Copy the key (af_live_...) — shown only once
  4. 4Pass it as Authorization: Bearer af_live_...

Working Examples

Complete examples covering connection, every API scope, and cleanup. Replace YOUR_PRODUCT_ID and af_live_YOUR_KEY with your actual values.

import requests

BASE_URL  = "https://gateway.appfora.io/api/v1"
PRODUCT   = "YOUR_PRODUCT_ID"
API_KEY   = "af_live_YOUR_KEY"
HEADERS   = {"Authorization": f"Bearer {API_KEY}"}

# ── legal:read ─────────────────────────────────────────────────────
docs = requests.get(f"{BASE_URL}/{PRODUCT}/api/legal/documents", headers=HEADERS)
print("Legal docs:", docs.json())

single = requests.get(
    f"{BASE_URL}/{PRODUCT}/api/legal/documents/privacy-policy", headers=HEADERS)
print("Privacy Policy:", single.json())

config = requests.get(f"{BASE_URL}/{PRODUCT}/api/legal/config", headers=HEADERS)
print("Legal config:", config.json())

# ── legal:generate ─────────────────────────────────────────────────
gen = requests.post(f"{BASE_URL}/{PRODUCT}/api/legal/generate",
    headers=HEADERS, json={"trigger": "api"})
print("Generate:", gen.json())

regen = requests.post(f"{BASE_URL}/{PRODUCT}/api/legal/regenerate",
    headers=HEADERS, json={"trigger": "api"})
print("Regenerate:", regen.json())

requests.put(f"{BASE_URL}/{PRODUCT}/api/legal/config",
    headers=HEADERS,
    json={"company_name": "Acme Ltd", "dpo_email": "[email protected]"})

# ── legal:approve ──────────────────────────────────────────────────
drafts = requests.get(
    f"{BASE_URL}/{PRODUCT}/api/legal/documents/drafts", headers=HEADERS)
print("Drafts:", drafts.json())

doc_id = "DRAFT_DOC_ID"
requests.put(f"{BASE_URL}/{PRODUCT}/api/legal/documents/{doc_id}/publish",
    headers=HEADERS)
requests.put(f"{BASE_URL}/{PRODUCT}/api/legal/documents/{doc_id}/reject",
    headers=HEADERS)

# ── support:articles ───────────────────────────────────────────────
articles = requests.get(
    f"{BASE_URL}/{PRODUCT}/api/support/articles", headers=HEADERS)
print("Articles:", articles.json())

# ── support:ask ────────────────────────────────────────────────────
answer = requests.post(f"{BASE_URL}/{PRODUCT}/api/support/ask",
    headers=HEADERS,
    json={"question": "How do I reset my password?"})
print("Answer:", answer.json())

# ── support:regenerate ─────────────────────────────────────────────
requests.post(f"{BASE_URL}/{PRODUCT}/api/support/generate",
    headers=HEADERS, json={"trigger": "api"})

# ── support:approve ────────────────────────────────────────────────
requests.post(f"{BASE_URL}/{PRODUCT}/api/support/kb/rebuild",
    headers=HEADERS)
requests.put(f"{BASE_URL}/{PRODUCT}/api/support/articles/ART_ID/review",
    headers=HEADERS, json={"approved": True})

# ── Cleanup ────────────────────────────────────────────────────────
# Keys are long-lived — there is no "session close" call.
# Revoke from the Appfora dashboard (Products → API Keys → Revoke)
# or rotate via the management API when no longer needed.
# The gateway invalidates the cached session instantly via pub/sub.
print("Done — revoke or rotate the key when no longer needed.")

API Endpoints

All endpoints are under https://gateway.appfora.io/api/v1/{product_id}

Legal — Live & Test

GET/api/legal/documents
GET/api/legal/documents/{slug}
GET/api/legal/config

Legal — CI / CD

POST/api/legal/generate
POST/api/legal/regenerate
PUT/api/legal/config
GET/api/legal/documents/drafts
PUT/api/legal/documents/{id}/publish
PUT/api/legal/documents/{id}/reject

Support — Live & Test

POST/api/support/ask
GET/api/support/articles

Support — CI / CD

POST/api/support/generate
PUT/api/support/articles/{id}/review
PUT/api/support/qa/{id}/feedback
POST/api/support/kb/rebuild

Scopes Reference

Assign the minimum scopes needed for each integration.

ScopeCategoryAllows
legal:readLive & TestRead generated legal documents (ToS, Privacy, AUP, etc.)
legal:generateCI / CDRegenerate legal documents and update legal config
legal:approveCI / CDList drafts, publish or reject legal document versions
support:askLive & TestAsk support questions in real-time
support:articlesLive & TestRead Help Centre articles and FAQs
support:regenerateCI / CDRegenerate Help Centre FAQ articles from scan data
support:approveCI / CDApprove articles, approve/reject Q&A, rebuild KB

Error Handling

All errors return:

{ "detail": "Human-readable message" }
401Invalid or expired API key
403Wrong product or missing scope
429Rate limit or hard cap exceeded
413Request body too large (max 1 MB)
502Product container unreachable

Rate Limits & Caps

Per-Key Rate Limit

Default 60 req/min, configurable up to 1,000,000. Editable inline from the API Keys page.

Soft Cap

Warning email sent to all org members. Requests continue.

Hard Cap

Returns 429 — all subsequent requests blocked until billing cycle resets or cap is raised.

Retry Strategy

Exponential backoff on 429: wait 1s, 2s, 4s, 8s, then fail.

Ready to Integrate?

Create your account, scan your first repo, and start making API calls in minutes.

Get Started Free