Billing uses executor runtime, not the workflow clock in the UI. A job or workflow can look running for many hours after the executor has stopped. You are not charged for that extra wall-clock time.
This happens when a job record never reaches a terminal state. A parallel job is a common case: some shards finish, one shard never fully closes after a cancel, and the workflow stays running or failing with no stopped_at. Downstream jobs that stayed blocked did not start, so they did not consume compute either.
The job detail API is the source for billing. duration / build_time_millis and stopped_at on the job describe the executor. The workflow jobs list can still show running for the same job.
Confirm what was billed
Replace the project slug and job number:
curl -sS -H "Circle-Token: $CIRCLE_TOKEN" \ "https://circleci.com/api/v2/project/PROJECT_SLUG/job/JOB_NUMBER"
Check started_at, stopped_at, status, and duration. A duration of seconds or minutes, with steps that finished in that same window, means the long UI timer was not live compute.
If the workflow is still non-terminal after the executor has stopped, Support can close the leftover workflow record. After a hard refresh, the pipeline should leave the running state. You can also open the pipeline in a new tab.
Cancel in the UI is still the right first step when a job is actually running. The timer-versus-bill gap is the leftover record after compute has already stopped.
