# Inference API, access approval and rate limits Start: `.\.venv\Scripts\python.exe serve_models.py`. Open http://127.0.0.1:8766/docs. Default startup requires approved API keys. For local testing without a key, add `--allow-anonymous`; anonymous traffic still has shared limits. The server binds only to localhost. Uploading code to Hugging Face does not deploy a hosted API. ## How you approve requests Developers use the Request API access form on `/docs`, or POST `/v1/access-requests` with `{"app_name":"My app","contact":"developer@example.com"}`. They receive a request ID and a key shown once. The key is pending until you approve it. Contact information is self-reported; no emails are verified or sent. Run owner commands locally: ```powershell .\.venv\Scripts\python.exe api_access.py list .\.venv\Scripts\python.exe api_access.py approve REQUEST_ID --rpm 10 --daily 500 .\.venv\Scripts\python.exe api_access.py deny REQUEST_ID .\.venv\Scripts\python.exe api_access.py revoke REQUEST_ID ``` Approval/revocation is immediate, without restart. Re-running approve changes limits. The applicant keeps the same key; lost keys need a new application and revocation of the old ID. Owner administration is a local CLI, not a public admin endpoint. Keys are random and stored only as SHA256 hashes. Private database: `outputs/api-private/access.sqlite3`. Keep it private and back it up; it contains contacts, statuses and usage timestamps, not inference text or plaintext keys. No automatic account-deletion portal is provided. ## Requests and endpoints ```powershell $key = Read-Host 'Approved API key' $body = @{text='Thank you for helping me!'; mode='sliding'; window_size=128; overlap=32} | ConvertTo-Json Invoke-RestMethod http://127.0.0.1:8766/v1/emotions -Method Post -ContentType 'application/json' -Headers @{Authorization="Bearer $key"} -Body $body ``` | Method | Path | Purpose | | --- | --- | --- | | GET | /docs | Interactive inference and access form | | GET | /health | Status, cached models, authentication mode | | GET | /v1/models | Task routes and token limits | | POST | /v1/access-requests | Pending application; returns key once | | POST | /v1/emotions | Emotion classification | | POST | /v1/morals | Moral framing | | POST | /v1/sensations | Target-in-context sensory associations | Sensations requires a mentioned target: `{"text":"The aroma of bread filled the bakery.","target":"aroma"}`. Other tasks omit target. Fields: text, optional mode (sliding/chunks), window_size and overlap. Defaults: emotions/sensations 128/32, morals 256/64; chunks have zero overlap. Minimum total window 16, maximum the trained limit. Overlap is capped at half usable context. Body limit 100,000 bytes; text 20,000 characters; at most 128 evaluated windows. Responses include per-window evidence and exploratory max/mean summaries. Existing thresholds were calibrated on short inputs, not document decisions. See WINDOWING_GUIDE.md. Models are cached after first use; first requests include loading time. ## Enforced limits - Approved keys default to **10 requests per rolling 60 seconds and 500 per UTC day**, shared across all three inference routes. Owner can customize each key. - API-access applications: **3 per rolling hour and 10 per UTC day per peer IP**. - All POST requests: **60 per minute and 10,000 per UTC day per peer IP**, including bad-key traffic. Forwarded headers are not trusted. - Anonymous demo calls share 10/minute and 500/day. Supplying a pending or invalid key still fails in demo mode. - **429** includes Retry-After seconds. Persistent transactional counts survive restart. UTC daily reset is 08:00 Singapore time. - Only one inference runs at a time; busy requests receive **503**, Retry-After 1, rather than an inference queue. Authorized invalid-input/busy requests consume quota. These are request quotas, not token billing. - Missing/invalid keys: **401**. Pending, denied or revoked keys: **403**. Invalid body/input: **400**. The earlier OPEN_MODELS_API_KEY single-secret setting has been replaced with the approval database. Tests: `python test_api_access.py` checks pending/approved/revoked access, hashed storage, concurrent atomic rate enforcement, daily reset and HTTP 429/Retry-After. Quota HTTP tests mock inference; actual model inference was tested separately. ## Deployment and downloads Download serve_models.py, api_access.py, api_demo.html, predict_windows.py, the documented environment and model files. This server uses the original `outputs//...` checkpoint layout described in the learning guide. For custom checkpoint paths, the standalone window CLI supports --model. This is a single-process local stdlib service, with no cross-origin browser access, public HTTPS hosting, verified email, billing or distributed quotas. A public deployment needs a production HTTPS front end with network/time/concurrency controls and an explicit proxy/IP policy. Peer-IP limits otherwise apply to the proxy as a whole. Developer backends must hold keys; do not put them in public browser JavaScript. Quotas govern this server, not the publicly downloadable weights. `--model-dir` can override downloaded checkpoint paths without recreating the original project layout. Example: `python serve_models.py --model-dir open-emotions=./downloaded-model`. Repeat for each model; unconfigured tasks use the local project defaults. Download config.json, model.safetensors, tokenizer files, thresholds.json and training_run.json for each directory. ## Gemma classifier releases Run Gemma adapters in the Gemma-capable environment described in GEMMA_CLASSIFIERS_GUIDE.md. Download adapter_config.json, adapter_model.safetensors, classifier_head.safetensors, classifier_config.json, tokenizer files, thresholds.json, training_run.json and gemma_classifier.py. The custom loader obtains the pinned public Gemma base. These adapters use the same routes and response fields as the RoBERTa family. Example in WSL, with downloaded directories under the current working directory: ```bash /opt/open-gemma-venv/bin/python serve_models.py --port 8767 \ --access-db outputs/api-private/gemma-access.sqlite3 \ --model-dir open-emotions=./gemma-emotions \ --model-dir open-morals=./gemma-morals \ --model-dir open-sensations=./gemma-sensations ``` Open http://127.0.0.1:8767/docs. Each server instance should have its own private approval database; `--access-db` selects it. Owner commands use the matching `api_access.py --db outputs/api-private/gemma-access.sqlite3 ...` path. First calls include base download/loading and may take several minutes on this machine; allow a generous client timeout (for example 600 seconds with a cached base). Later calls reuse loaded models. Approval and the default 10/minute, 500/day limits still apply. Hugging Face publication makes weights downloadable; it does not provision a hosted API endpoint.