Browse the docs

Developers

Updrone API

Build on the Updrone platform. The API moves captures, scenes, deliverables, customers, and jobs between your own tools and ours, and lets you react to what happens with webhooks. Updrone is the software underneath; your business stays the professional of record for its own flights, pilots, airspace, and accuracy sign-off.

Base URL /api/v1 · 88 live endpoints · v1 is frozen additively

Quickstart#

Issue a token under Settings → API tokens (the secret is shown once, at creation), then three calls take you from “what am I allowed to do” to a write that is safe to retry.

# 1 — check what your token can do
curl -H "Authorization: Bearer $TOKEN" https://app.updrone.com/api/v1/me

# 2 — find a project
curl -H "Authorization: Bearer $TOKEN" "https://app.updrone.com/api/v1/projects?q=rodriguez"

# 3 — file a punch item against it (exactly-once: retry returns the original)
curl -X POST https://app.updrone.com/api/v1/projects/PROJECT_ID/records \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Agent-Run-Id: my-run-001" \
  -d '{"kind":"punch","title":"Handrail loose at stair 2","opId":"my-run-001-p1"}'

A token acts as its role through the same permission gate as the portal UI — narrowed per kind and per verb, restricted to specific projects, bound to a member, and time-boxed. It can never exceed the role it was issued against.

What you can build#

Push captures into a project

Send images, video, or a finished capture from your own client or device into a project, where it joins the queue for processing.

Pull processed scenes & deliverables

Fetch the 3D scene, exports, and deliverables once processing finishes. Measurements and derived quantities come through with the tolerance bands your capture inputs support — your team reviews and signs off on accuracy, never us.

Sync customers and jobs

Read and write the customer record and the job spine so the scene, the proposal, and the invoice stay on one object across your stack and ours.

Subscribe to webhooks

Get notified the moment something happens — lead captured, scene ready, proposal signed, payment received — so your systems react without polling.

Built for automated callers#

The surface is designed for something that plans, acts, and has to be accountable for what it did — whether that is your integration or a model driving it.

The contract is machine-readable
GET /api/v1/openapi.json returns OpenAPI 3.1 generated from the same source the reference renders; add ?format=tools and you get an LLM tool manifest. No hand-written spec to drift.
A token can tell you what it may do
GET /api/v1/capabilities answers per endpoint for your credential, including why a call would be refused — so an agent plans before it acts instead of discovering a 403 three steps in.
Errors are codes, not sentences
Every failure carries a stable code and a retryable flag. A dead credential is a 401, an out-of-scope call is a 403, and the response names the scope you are missing.
Writes are exactly-once and audited
Send opId or Idempotency-Key and a retry replays instead of duplicating. Every write lands in the tenant’s tamper-evident audit trail against your token, and the response discloses what left the system.
A consequential call pauses and asks
An operation marked irreversible or binding — sending a proposal, issuing an invoice, sealing a design — answers 409 confirmation_required the first time, with a confirmToken and a willDo sentence naming what it is about to do and to whom. Re-send with x-updrone-confirm to perform it. The token binds that exact payload, so it cannot be replayed against a different one.
Consequences have their own budget
Separately from the request limit, what LEAVES the system is capped per hour, per token, per kind — email, SMS, charges, publishes and metered compute. One request can carry many consequences, and a caller comfortably inside 20 writes a minute can still reach forty of your customers. Exhausting one kind names that kind, so the rest of the run keeps working.
You can rehearse the ones that compute money
Send x-updrone-dry-run: 1 and a supporting endpoint computes the effects and applies nothing. An endpoint that cannot rehearse refuses the header rather than ignoring it — a rehearsal that silently applies is the one outcome it must never produce.
State changes go through a machine
A deal, a project, a proposal and an invoice each move through a declared transition table. An illegal trigger is a 409 listing what is legal from here, so you re-plan from one response instead of probing — and a trigger whose destination the record is already in answers 200 with replayed: true, because a retry after a lost response is not a failure.
Measurements carry their uncertainty
Every measured figure ships with its ± tolerance band, its unit, and a fraction rather than an ambiguous percentage. The band is part of the number — carry it through, and your team stays the professional of record for what they deliver.

Consequences#

Most calls here are reversible and need no ceremony. A few are not — sending a proposal to a customer, issuing an invoice, sealing a design — and those pause and tell you what they are about to do before they do it. The pause is not “are you sure”; it is a sentence you can evaluate.

# 1 — ask. The server refuses, and tells you what it would have done.
curl -X POST https://app.updrone.com/api/v1/proposals/PROPOSAL_ID/send \
  -H "Authorization: Bearer $TOKEN"

# → 409
# {
#   "ok": false,
#   "code": "confirmation_required",
#   "confirmToken": "1753728000000.9f3c…",
#   "confirmHeader": "x-updrone-confirm",
#   "willDo": {
#     "summary": "EMAIL k***@example.com the proposal \"Roof scan + solar\" for 12400.00 USD. There is no un-send.",
#     "effect": "irreversible",
#     "recipient": "k***@example.com",
#     "totalCents": 1240000
#   }
# }

# 2 — confirm. The SAME request, plus the token. Changing the body invalidates it.
curl -X POST https://app.updrone.com/api/v1/proposals/PROPOSAL_ID/send \
  -H "Authorization: Bearer $TOKEN" \
  -H "x-updrone-confirm: 1753728000000.9f3c…" \
  -H "X-Agent-Confirmed-By: ops@yourcompany.com"

The token binds the tenant, the credential, the operation and the exact payload, and expires in ten minutes — so a confirmation for one proposal can never be spent on another. Set X-Agent-Confirmed-By to record who authorised it; that is stored as a claim the caller made, not as proof, and the server-issued token is the actual control.

Underneath that sits a separate ceiling on what can leave the system, counted per hour, per token, per kind: 30 emails, 20 SMS, 10 charges, 10 publishes, 20 metered compute runs. It is deliberately not the request limit — one request can carry many consequences, and a caller well inside 20 writes a minute could still reach forty of your customers. Exhausting one kind returns a 429 naming that kind, so the parts of a run that are still allowed keep working.

Machine-readable contract#

Do not hand-write a manifest from these pages. The same registry that renders the reference emits the contract, so the two cannot disagree.

  • GET /api/v1/openapi.json — OpenAPI 3.1. No token needed.
  • GET /api/v1/openapi.json?format=tools — the same surface as an LLM tools[] array. This is the ONLY sanctioned tool manifest; a hand-written one reintroduces exactly the drift the generated contract exists to prevent. Pin a digest of what you fetched and re-check it on deploy — the surface is additive-only, so a changed digest means new capability, never a removed one.
  • GET /api/v1/capabilities — what your token may call, which is narrower than what exists.

Next steps#

Project records

Punch items, RFIs, incidents and daily logs — the field-integration write path, with retraction that can itself be undone.

GETPOSTGETPATCHPOSTPOST

Deliverables & measurements

Pull a processed artifact down, and read the measured quantities a scene produced — each figure with the ± band that belongs to it.

GETGET

Leads & customers

Demand before it is a customer, and the customer once it is. Capture a lead, move it through its status machine, convert it into a real record — and read the whole relationship back in one call.

GETGETPOSTPATCHPOSTPOSTGETGETPOSTPATCH

Deals & pipeline

The pipeline as data rather than as a board: cents and currency codes, the stage machine's legal triggers stated up front, and moves that refuse illegally rather than silently doing nothing.

GETGETPOSTPOSTPOST

Projects

The unit of delivery work: the list, one project with its scenes and deliverable manifests, and its computed schedule.

GETGETGETGETGETGETPOSTPATCHPOSTPOSTPOSTPOSTPOSTGETGETPOSTGET

Client pages & exports

Getting work out of Updrone. Client pages are assembled rather than stored — every project and customer always has one — and a tenant export is queued, swept and polled, because archiving a whole tenant is not something to hold a socket open for.

GETPOSTGETGET

Saved reports

What a tenant has chosen to keep watching. A report is config-backed — it stores the figures and the queries, not their values, and the board is re-derived every time it is opened — so these calls describe what a report IS, and the numbers stay where they are computed. Reports are private to the member who saved them, which is why an unbound token is refused rather than shown an empty shelf.

GETGET

Invoices

Asking to be paid. A draft asks nobody for anything; issuing one puts a live payment page in front of a customer, so it is confirmed. Refunds and payment itself are not here — returning money and paying are human acts.

GETGETPOSTPOSTPOSTGET

Proposals

Winning the work. Drafts are inert and freely editable; sending one is irreversible, confirmed and budgeted, because it puts a document in front of a named human who can act on it.

GETGETPOSTPATCHPOSTPOSTPOSTPOST

Scenes & geometry

The reconstructions themselves: what is ready, what each one produced, and the plane-detection kernel that turns a dense point cloud into a roof you can design on.

GETGETPOSTGETGETPOSTDELETEGETPOST

Capture & processing

Getting pixels in and turning them into a scene: the presigned upload handshake where the server owns every key, the reconstruction kick, and the poll target that says which stage a run is on and why it stopped.

GETGETPOSTPOST

Templates & geocoding

The pieces a project is assembled from: the document templates every invoice, proposal and client page renders through, and the address lookup that turns a street line into the coordinate every downstream kernel needs.

GETGETGETPUT

Discovery & sync

Find things, and learn what moved since you last looked — the calls that replace re-reading every collection and diffing it.

GETGETGET

Token & capabilities

Introspection. Ask what your own credential is and what it may do, before you act rather than after a 403.

GETGET

Bookings

Requests customers have made, and the two acts that answer them. A `requested` row HOLDS its slot against every other customer until you do — so this is work, not history. Confirming re-checks the window and refuses a clash with alternatives rather than double-booking; declining carries a reason the customer reads. There is deliberately no endpoint that confirms a booking on a rule or a schedule: confirmation is a human act or the tenant's own recorded instant-book policy, and nothing else.

GETPOSTPOST

The day

What a given day holds and how prepared it is: each visit's site, the age of its imagery, whether a roof is marked, whether a draft flight plan exists, and whether a human has reviewed the drafts. `readiness` describes the PREPARATION and never the flight — there is no go/no-go here, and nothing in this product authorizes one.

GET

Tasks

Operational tasks for the member a token is bound to — read them, and file new ones. Both verbs need that binding: a task owned by a credential rather than by a person is one no human would ever be shown.

GETPOST

Building something? Email support@updrone.com and we will help.