RotorLab logo RotorLabDocs

API quickstart

The RotorLab API is a key-authenticated HTTP API over the same physics engine the app uses. You can analyze any build (multirotor, fixed wing, or VTOL), work out radio link budgets and center of gravity, read the parts catalog and airframe types, manage your saved builds, run log forensics, and file flight records, all from your own scripts and applications.

Every endpoint lives under one base URL, /api/v1 on the address you use RotorLab at. The Developer API page at https://rotorlab.app/developers and the OpenAPI file it links show that base URL, with every sample written for it:

https://rotorlab.app/api/v1

Get a key#

  1. Sign in and open My account, then the API access section.
  2. Type a label in the What will use this key? field and press Create API key.
  3. Copy the key immediately. It is displayed once, at creation, and only its SHA-256 hash is stored. The key looks like rl_....

Issue a separate named key for each integration, so revoking a compromised key does not affect the others. The list in API access shows each key's prefix, label, creation date, and when it was last used. Revoke removes one key; Revoke all keys removes every key on the account at once. See API access for the full key management page.

The API access section: the key creation field, the key list with prefixes and labels, and the base URL

Device credentials

Ground stations and other equipment use a device credential instead of a personal key. A device credential belongs to your organization rather than to an individual, so it stays valid after the person who created it leaves, and it reaches only the flight, checklist, pilot roster, and aircraft registry endpoints. A device that is re-keyed keeps those same limits. Because it is not a person, a device credential is not bound by a role, the two-factor deadline or Require SSO, which makes it the credential for unattended integrations.

Authenticate#

Send the key as a bearer token. The header X-API-Key is also accepted.

Authorization: Bearer rl_your_key

or

X-API-Key: rl_your_key

A missing or invalid key returns 401 with {"error": "Invalid or missing API key"}.

Your first call#

GET /version is free and unmetered, so it is the right endpoint to confirm your key works:

curl -H "Authorization: Bearer rl_your_key" \
  https://rotorlab.app/api/v1/version
{"name": "RotorLab", "version": "x.y.z", "author": "RotorLab.app"}

Then read your own quota with GET /usage, also free:

curl -H "Authorization: Bearer rl_your_key" \
  https://rotorlab.app/api/v1/usage

The response reports limit (requests per day from your plan), used, remaining, credits, the current UTC day, and a key object describing the key you called with: its label, prefix, areas, whether it is read only, its creation date, last use, and when it ends.

Metering in brief#

  • Every request spends one unit, except version and usage (so a blocked client can still read its own status), the record endpoints (flights, checklists, pilots, aircraft, missions, workorders, components, types, bulletins, health and ml/scores), because keeping your own records is never metered, and collecting a queued crash reading. A path that does not exist answers 404 and costs nothing.
  • A refused call spends nothing. Its body is checked whole before it is counted, and a call refused after that (a 4xx, such as a build that is not there) gives its unit back. The one exception is a crash log that is accepted and then cannot be read: it counts as one call.
  • Your plan sets a daily quota, spent first. It resets at 00:00 UTC.
  • Once the quota is gone, requests draw from your credit balance. Credits come included with some plans or can be purchased from My account.
  • When both are exhausted, the API returns 429 with "quota": "exhausted" and a Retry-After header giving the seconds until the daily reset.
  • A plan that includes no API calls, with no credits, answers 402 with "quota": "none" and no Retry-After: add credits or move to a plan that includes them.
  • Every metered response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Credits, so your client always knows where it stands without spending a request.
  • A key whose trial or billing period has ended is refused with 403 on metered endpoints; version and usage stay open.
  • A personal key acts with its holder's role: a call the holder's role does not see (reads) or manage (writes) is refused with 403 and a sentence naming the permission. It is also refused once its holder's two-factor deadline has passed without two-factor ("mfa_setup_required": true), and, in an organization that requires single sign-on, when its holder has not signed in through the identity provider within the SSO re-check period ("sso": true). version and usage stay open.

Worked example: analyze a build#

POST /analyze takes a build-parameters object and returns full performance results. Every field is optional; anything you leave out falls back to the example profile's defaults, so a minimal body is enough to get numbers.

curl#

curl -X POST https://rotorlab.app/api/v1/analyze \
  -H "Authorization: Bearer rl_your_key" \
  -H "Content-Type: application/json" \
  -d '{"airframe_type":"Quad X","motor_count":4,"prop_diameter_in":7,"motor_kv":1700}'

Python (standard library only)#

import json
import urllib.request

BASE = "https://rotorlab.app/api/v1"
KEY = "rl_your_key"

body = json.dumps({
    "airframe_type": "Quad X",
    "motor_count": 4,
    "prop_diameter_in": 7,
    "motor_kv": 1700,
}).encode("utf-8")

req = urllib.request.Request(
    f"{BASE}/analyze", data=body, method="POST",
    headers={"Authorization": f"Bearer {KEY}",
             "Content-Type": "application/json"})

with urllib.request.urlopen(req) as resp:
    result = json.load(resp)

out = result["out"]
print(f"AUW {out['auw_g']:.0f} g, TWR {out['twr']:.2f}, hover {out['hover_min']:.1f} min")

for level, message in result["checks"]:
    print(f"  [{level}] {message}")

Reading the response#

KeyWhat it holds
outHeadline numbers: auw_g, twr, hover_min, currents, top speed, sag and thermal margins, and for winged builds stall_speed_kmh, cruise_speed_kmh, climb_rate_ms, wing_loading_n_m2
chartsInline SVG chart strings, ready to embed
checks[level, message] pairs, where level is ok, warn, or bad
lintThe same findings as checks, machine readable
platformResolved platform description: airframe class, motor groups, layout
cgCenter of gravity and balance result

Which fields appear in out depends on the airframe: multirotors report hover figures, wings report stall, cruise, and climb, and VTOLs report both. Send a fixed-wing or VTOL airframe_type with your wing dimensions and the same endpoint returns the winged figures. GET /airframes lists every supported type.

Where to go next#