Skip to main content
Two things are counted, on two independent axes. Knowing which one your workload consumes is the difference between a predictable bill and a surprising one.
This page describes what is measured. Rates live on Billing modes and, canonically, on phonebase.co.

Active time

The unit for holding a device is active time: the span of the lease itself, from when your organization takes the device until you release it or its lease expires. Active time is the lease interval itself, integrated exactly: from when the device was taken until whichever comes first, the moment you released it or the moment its lease expired.

What takes a device, and so starts the clock

A lease starts in one of two ways, and they cost the same:
  • You take it explicitly with acquire_device (or POST /v1/devices/{deviceId}/lease).
  • You act on a device your organization does not hold. A gesture sent without a leaseId (tap, swipe, long_press, type_text, press_key, open_app, or POST /v1/devices/{deviceId}/actions) takes the device for you, and so does start_run. This needs a key with devices:lease; a key with only devices:act acts on a device your organization already holds and is otherwise refused lease_required, so it can never start a lease on its own.
If the gesture that took the device then fails, the lease it took is given back before the error reaches you: a refused tap does not leave you paying for a device. Watching never takes a device. screenshot with no leaseId, ui_snapshot, wake, list_devices, get_device and get_receipt start nothing, and ui_snapshot and wake refuse with lease_required rather than take one. To give back a device a gesture took for you, you need its lease id, which an MCP gesture result does not carry. Call acquire_device: on a device your organization already holds it returns that same lease unchanged, and release_device takes its leaseId. (The REST gesture route returns the leaseId in its response.) Or let it expire, ten minutes after it was taken. Read that literally. A lease that is held but untouched still accrues active time. Nothing watches for inactivity and nothing pauses the clock on your behalf. The thing that bounds a lease you forget to release is its own expiry, not idleness, so the bound is the lease TTL rather than the moment you stopped working. A lease expires 10 minutes after it is granted, and it can be renewed. That number is what this whole page turns on, so here it is rather than three pages away. A lease accrues active time until it expires. A client that has crashed stops renewing, so a lease forgotten that way accrues at most 10 minutes and then expires on its own. A client that goes on renewing goes on accruing, up to the 60 minute lifetime no lease may exceed, so 60 minutes and not 10 is the ceiling on any single lease. See Billing modes for what a minute costs and Spending controls for the limits you can set yourself. The practical consequence: release a device when you are done with it. Holding a lease open for convenience is a decision to pay for the time. Active time is measured in device minutes.

Agent steps

When a worker runs a task on your behalf, the unit is a step, and one step is one frame served to that worker. Steps are anchored to frames rather than to actions. A worker that takes one look and then performs five taps has consumed one step, not five. The sequence is issued by the control plane, not by the worker, so a worker cannot renumber or replay its way into a different count. A frame is counted before it is served. If the count cannot be recorded, the frame is not served, and you are not charged for it. The implication runs one way only: delivered implies billed, and billed does not imply delivered. See the list below. Every run carries a ceiling on the steps it may consume. Reaching that ceiling makes the next frame request fail; it does not end the run. The run stays alive against its own deadline, so a worker that has exhausted its budget should stop and report rather than keep trying.

What is not counted

Here is that list in full. Nothing in it adds to your bill.
  • Actions themselves. There is no per action rate on any tier. A tap, a swipe, a keystroke and an app launch all cost nothing beyond the active time the lease was already accruing. Holding a device for ten minutes costs the same whether you performed one gesture in it or two hundred.
  • A failed action. An action the device refused, or that failed on the way, is recorded so you can look it up, but it is not a billable event. Only an action the device actually committed counts as an actuation at all, and even then it is counted for the ledger rather than charged.
  • A refused action. An action rejected before it reached the device costs nothing, and there are several ways that happens: a capability the device does not have, a frame that went stale between your look and your tap, a lease you no longer hold. Nothing physical happened and nothing is billed.
  • A retry under the same idempotency key. The recorded outcome is replayed rather than re-executed, so a network retry never becomes a second charge.
  • A frame request that fails before its step is written. A 503 when metering is unavailable, a 503 when the frame carries no identity, and a 409 when the run is out of budget or parked for a person all cost nothing. The single exception is a connection you drop after the step was written but before you read the bytes, which costs that one step.
  • Time outside a lease. A device your organization does not hold accrues nothing. Listing devices, reading capabilities, looking up a receipt, and watching a screen are not metered, and none of them takes the device.
  • Screenshots as a separate unit. Driving a device yourself over MCP, a screenshot is an observation inside your lease, not a step. Steps are the agent tier’s unit, counted when a frame is served to a worker.
What is left is the short version: you pay for time a device was yours, and for frames served to a worker acting on your behalf. Nothing else.

The two axes are independent

Driving a device yourself over MCP consumes active time. Handing a goal to a worker consumes active time and steps, because the worker still holds a lease on the device while it works.

Reading your own usage

Every action can carry an idempotencyKey, and the outcome recorded under that key is retrievable afterwards with get_receipt. A retry that reuses the same key replays the recorded outcome instead of executing again, so a network retry does not become a second charge. That is a point lookup, for a key you already hold. To ask the broader question, the hosted control plane has two reads, both needing only devices:read: Usage is derived from that same recorded ledger rather than from a separate counter, which is why what you are billed for and what you can look up are the same events. GET /v1/usage reads the per-lease rows billing itself reads, so it is not a second opinion about your consumption. It reports settled leases only. A lease you are holding at this moment has not ended, so it is not in the numbers yet, and this read is an account of what has finished rather than a live meter. See Spending controls.