LeafAI API v1

Build against LeafAI with confidence.

This documentation is generated from a single OpenAPI contract and reflects implemented backend routes only: no placeholder endpoints, no hidden auth APIs.

99.9% uptime

Status:All systems operational. View live status.

Base URL (Local)

http://localhost:8080

Base URL (Prod)

https://leafai-api-v2.adityamehrotra.com

Auth

Authorization: Bearer <firebase_id_token>

Quickstart in 60 seconds

  1. Get a Firebase ID token from your signed-in user session.
  2. Send it as Authorization: Bearer <token>.
  3. Call POST /predict with multipart file image.
  4. Use GET /history and DELETE /history/{history_id} to manage records.

Authentication

All endpoints except `GET /health` require a Firebase ID token. The backend validates token signature, expiry, and UID. Use this exact header format:

Authorization: Bearer <firebase_id_token>

If the header is missing or invalid, API responds with `401` and one of these messages: `Missing or invalid Authorization header.`, `Missing Firebase ID token.`, or `Invalid or expired Firebase ID token.`

Rate limits

`POST /predict` is rate limited per authenticated user UID. Default backend thresholds are:

Per minute

10

Per hour

25

Per day

50

On limit hit, API returns `429` plus `Retry-After` header and JSON body fields: `code`, `scope`, `window`, and `retryAfterSeconds`.

Endpoint examples

Copy and run these snippets directly. Replace placeholder values before execution.

Example Language

Applies to all endpoint snippets below.

GET/health
JavaScript
const response = await fetch("http://localhost:8080/health");
const data = await response.json();
console.log(data.status);
POST/predict
JavaScript
const formData = new FormData();
formData.append("file", fileInput.files[0]);

const response = await fetch("http://localhost:8080/predict", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${firebaseIdToken}`,
  },
  body: formData,
});

const data = await response.json();
if (!response.ok) throw new Error(data.message);
console.log(data);
GET/history
JavaScript
const response = await fetch("http://localhost:8080/history", {
  headers: { Authorization: `Bearer ${firebaseIdToken}` },
});

const items = await response.json();
console.log(items);
DELETE/history/{history_id}
JavaScript
const response = await fetch("http://localhost:8080/history/<HISTORY_ID>", {
  method: "DELETE",
  headers: { Authorization: `Bearer ${firebaseIdToken}` },
});

const payload = await response.json();
console.log(payload);
GET/uploads/{relative_path}
JavaScript
const response = await fetch("http://localhost:8080/uploads/<UID>/<IMAGE_FILE>", {
  headers: { Authorization: `Bearer ${firebaseIdToken}` },
});

if (!response.ok) throw new Error("Unable to fetch file");
const blob = await response.blob();

Interactive reference

Use the in-browser API console below to inspect schemas and test endpoints against your selected server.

Loading interactive reference...

Common errors

StatusWhen it happensMessage
400Bad upload requestMissing upload field `file` / No file selected / Unsupported image type
401Missing or invalid bearer tokenMissing or invalid Authorization header / Invalid or expired Firebase ID token
413Image exceeds max upload sizeThis image is too large to upload. Please choose a file smaller than <MAX_UPLOAD_MB>MB.
422No detectable leafCannot detect a leaf in this image.
429Prediction limit exceededRate limit reached for predictions. Limit is 10/minute, 25/hour, 50/day.
500Model or server failurePrediction failed. Please try again. / Unexpected response from prediction model.

Changelog

v1.0 · 2026-03-05

Initial public API docs for implemented LeafAI backend endpoints with interactive testing.

Contract source of truth: /openapi/leafai.openapi.yaml. Any backend endpoint change must update this spec in the same pull request.