For the complete documentation index, see llms.txt. This page is also available as Markdown.

Connecting to Cloudflare

Connect your Cloudflare account to OneLens for cost intelligence, per-product and per-zone cost attribution, budget and anomaly alerting, and invoice reconciliation, using a read-only account-owned API token and Cloudflare's own billable usage data.

TL;DR

  • What this does: Pulls billed cost per Cloudflare product from the Billable Usage API, the same system that generates your invoice, so Cloudflare spend reports next to AWS, GCP, Azure, and OCI in OneLens.

  • Time required: ~10 minutes.

  • Who you need: A Super Administrator on the Cloudflare account. Only Super Administrators can create account-owned API tokens.

  • What OneLens reads: Billing records only, through exactly one read-only permission: Billing → Read. No traffic data, no analytics, no logs, no DNS records, no configuration, and nothing about how your services perform.

Before You Start: Is Your Account Supported?

Cloudflare bills two different ways, and only one of them exposes cost programmatically. Find your row before you do anything else.

Your account
What Cloudflare exposes
OneLens support

Pay-as-you-go (self-serve). You signed up with a card and pay metered charges for Workers, R2, D1, and similar products.

Full cost rows via the Billable Usage API, from the same system that generates your invoice

Fully supported

Enterprise (contract). You have a negotiated annual agreement with committed spend and custom rates.

No cost data at all. No contract rates, no commit, no monthly charge, no discounts

Not supported

Mixed. Some self-serve subscriptions sit alongside a contract.

Only the self-serve portion

⚠️ Partially supported. Self-serve spend only

Check in 30 seconds, no token needed. In the Cloudflare dashboard go to Manage Account → Billing → Billable Usage. A populated daily cost chart with per-product rows means you are on pay-as-you-go and this integration will work. An empty page, or one saying the account is not eligible, means you are on an Enterprise contract.

Why we can't work around this. Your negotiated rate card, commitment, and platform fee are not in any Cloudflare API. Most Enterprise spend is a flat negotiated fee with no meter behind it, so there is nothing to read and nothing to derive it from. Rather than show you an invented figure, we tell you the integration doesn't apply today. Cloudflare has said an Enterprise equivalent is in the works. When it ships, we will add it, and this page will change.

More than one Cloudflare account? This flow connects one account. Cloudflare's account-owned tokens are scoped to the account that owns them, so run these five steps once per account, each with its own token. OneLens reports across all of them together, so you still get one consolidated Cloudflare view. Coverage is decided per account, which matters if some of yours are on contracts.

What You'll Get Once Connected

Capability
What it does for you

Unified Cost Explorer

Cloudflare spend sits next to your AWS, GCP, Azure, and OCI cost in one view, on the same date and currency basis

FOCUS-aligned ingestion

Cloudflare's billing fields are modelled on the FinOps Open Cost & Usage Specification, the same schema OneLens uses for AWS, GCP, and Azure, so it lands with little custom mapping. Cloudflare does not yet claim full FOCUS conformance, so OneLens fills the gaps rather than assuming them

Per-Product Cost Breakdown

Daily billed cost for each product you use, from Workers and R2 through to Zero Trust seats and Images

Per-Zone Cost

Where Cloudflare attributes a charge to a specific domain, OneLens reports it against that zone. This is billed cost from Cloudflare, not an estimate

Free Allowance Visibility

Cloudflare reports metered quantity and billable quantity separately, so you can see how much of your usage the free tier absorbed and how close a product is to becoming a real line item

Discount Visibility

List cost and billed cost arrive as separate fields, so any difference between rate card and what you paid is visible rather than buried

Anomaly Detection

Alerts when a product's daily spend breaks its own pattern, so you find the spike inside the month instead of on the invoice

Budget Tracking

Set Cloudflare budgets with OneLens alerting, at account or product level

Multi-Account Reporting

Connect each Cloudflare account you own and OneLens reports across all of them, converted into one currency

Invoice Reconciliation

Billed cost comes from the system that generates your invoice, so OneLens totals tie out to what you actually pay, minus the flat fees noted in step 4

Security at a Glance

This is a cost-only integration, which makes the security story short: OneLens reads your bill and nothing else.

Question
Answer

Does OneLens read our traffic, requests, or responses?

No. OneLens reads billing records. It does not request analytics permissions of any kind, so traffic data is not reachable with this token.

Does OneLens read our usage or performance data?

No. Request counts, CPU time, cache hit ratios and the like are analytics, and analytics is out of scope for this integration. The only quantities OneLens sees are the billable quantities printed on your bill.

Does OneLens read our raw logs?

No. The Logs: Read scope is not on the token, so Logpull, Logpush, and Instant Logs are all out of reach.

Can OneLens see or change our DNS records?

No. The token carries no zone-scoped permission at all. Zone names arrive inside the billing records, so OneLens never needs to read your zone configuration.

Can OneLens change our configuration, routing, or WAF rules?

No. The single scope on the token is Read. No write, edit, or admin permission is granted anywhere.

Can OneLens change our plan or payment method?

No. That requires Billing → Write. OneLens requests Billing → Read only.

Does OneLens see our billing address or card details?

No. OneLens reads the billable usage endpoints, not the billing profile. Card metadata and address are not ingested.

Can OneLens reach our other Cloudflare accounts?

No. An account-owned token is scoped to the account that owns it. A token you create in one account cannot read another, even one you also own.

What authentication is used?

An account-owned scoped API Token created by you, carrying a single read permission. It is a service principal rather than a credential tied to a person. OneLens never asks for your Global API Key.

Can I restrict the token by IP?

Yes. Cloudflare supports Client IP Address Filtering on the token itself, which makes it unusable from anywhere else. If your security policy requires it, ask support@astuto.ai for our current egress ranges before you create the token. We do not publish them here because they change, and a stale list in a document breaks working integrations.

Can I set the token to expire?

Yes. Cloudflare tokens support a TTL. Set one to match your rotation policy, and OneLens will alert you before expiry.

How is data transmitted and stored?

All API calls use HTTPS/TLS 1.2+. The token is encrypted at rest in OneLens using GCP KMS.

What is the data retention policy?

OneLens retains ingested data for 12 months by default, configurable. On disconnection or a deletion request, data is purged within 30 days with confirmation.

Where does the data live?

OneLens infrastructure runs on GCP. See the OneLens Trust & Security page for region details, SOC 2 report, and DPA.

Cost of the Integration

OneLens does not create any infrastructure in your Cloudflare account. Cloudflare does not charge for Billable Usage API calls, and OneLens makes two per day.

Item
What it is
Typical cost

Cloudflare API calls

Billing API calls are not metered or billed by Cloudflare

$0

Compute in your account

None. No Worker deployed, no agent installed, no container run

$0

Data egress

JSON responses, typically well under 1 MB/day. API responses are not billed as egress

$0

Storage in your account

None. OneLens stores ingested data in its own infrastructure

$0

Estimated total

Sum of the above

$0/month

How It Works

Cloudflare's Billable Usage API (/accounts/{account_id}/billable-usage) returns one row per product per charge period. Each row carries the billed cost, the list cost, the billable quantity, and the unit it was priced in. The data comes from the same system that generates your monthly invoice, so the totals reconcile to what you actually pay rather than to an estimate.

The fields are modelled on the FinOps Open Cost & Usage Specification (FOCUS), the same schema OneLens already uses for AWS, GCP, and Azure. Cloudflare states it is not yet claiming full FOCUS conformance, so treat the shape as close but not identical. OneLens fills the gaps rather than assuming them.

OneLens calls two things, once a day:

  1. GET /accounts/{account_id}/billable-usage/info to confirm the account still returns billing data.

  2. GET /accounts/{account_id}/billable-usage for the cost rows themselves.

That is the whole integration. There is no agent, no webhook, no data pushed from your side.

What granularity you get, and what you don't

Cost arrives at product level, plus zone level wherever Cloudflare attributes a charge to a specific domain. Zone-scoped charges such as domain plans and per-zone add-ons carry a zone ID and name in the billing record, so those report against the right domain automatically.

Account-level products do not break down further. Workers arrives as Workers, not per script. R2 arrives as R2 storage and R2 operations, not per bucket. The same applies to D1, KV, Durable Objects, and Queues. Cloudflare does not attribute those charges below the product, and this integration reads only what Cloudflare bills, so OneLens does not estimate a split.

Why we don't estimate the split. Cloudflare's analytics API can tell you how many requests each Worker served, and we could apportion the product's cost across scripts in proportion. We don't, for two reasons. Cloudflare's own documentation warns that analytics datasets "should not be used as a measure for usage that Cloudflare uses for billing purposes", because they count traffic that billing excludes. And an apportioned number does not reconcile to an invoice line, which makes it a liability the moment someone builds a chargeback on it. Every figure in this integration is one Cloudflare billed you.

Cloudflare's billing data also carries no tag dimension. Resource Tagging exists, in public beta on all plans, and Cloudflare lists billing attribution among its purposes, but the tags do not appear as a field in the billable usage response the way an activated AWS cost allocation tag appears as a CUR column. Group your Cloudflare accounts and zones into cost centres in OneLens instead.

What OneLens Will Access

One permission. That is the whole request.

Scope
Level
Access
Why OneLens needs it

Billing

Account

Read

Every cost figure in the integration. Cloudflare describes this scope as granting "read access to billing profile, subscriptions, and access to fetch invoices and entitlements", which covers the cost rows and the subscription data behind the coverage check

Nothing else is requested. Not analytics, not account settings, not zone permissions, not logs. If OneLens ever asks you for a second Cloudflare permission, ask us why before granting it.

Endpoints

Both calls are covered by that single scope, and Cloudflare lists Billing as supported for account-owned tokens.

API call
Purpose

GET /accounts/{account_id}/billable-usage

Billed cost and billable quantity per product per charge period (the cost source)

GET /accounts/{account_id}/billable-usage/info

Coverage check, confirming the account returns billing data. Its response also carries the account's subscription IDs and billing cycle anchor

What OneLens Will NOT Access

  • Analytics of any kind. No analytics permission is on the token, so request counts, CPU time, bandwidth, and cache statistics are unreachable

  • Raw logs. Logs: Read is not requested, so Logpull, Logpush, and Instant Logs are out of reach

  • DNS records and zone configuration. The token carries no zone-scoped permission at all

  • Worker source code and R2 object contents. Neither Workers Scripts Read nor Workers R2 Storage Read is requested

  • Your billing profile. OneLens reads the billable usage endpoints, not /billing/profile, so address and card metadata are not ingested

  • Account settings and membership. Account Settings → Read is not requested, so OneLens cannot list your accounts, members, or account-level features

  • Your other Cloudflare accounts. An account-owned token cannot reach beyond the account that owns it

  • Any write, edit, or admin scope. The one permission on the token is Read

  • Billing writes. OneLens cannot change your plan, add-ons, subscriptions, or payment method

  • Your Global API Key. OneLens will refuse it if offered

Prerequisites

  • A Cloudflare account on a pay-as-you-go (self-serve) subscription. Confirm via Before You Start: Is Your Account Supported?.

  • A Super Administrator on that account. Account-owned tokens can only be created and managed by Super Administrators.

  • Your Account ID, the 32-character string in the dashboard URL after dash.cloudflare.com/.

  • curl and jq on the machine you run the validation calls from.

Validate and Connect

1

Create the Account-Owned API Token

Create an account-owned token, not a personal one. Account-owned tokens are service principals: they belong to the account rather than to you, so the integration keeps working when you change roles or leave the company. A user token dies with its owner's access.

  1. In the Cloudflare dashboard, go to Manage Account → API Tokens → Create Token. Creating the token from the account's own API Tokens page, rather than from My Profile, is what makes it account-owned.

  2. Under Custom token, select Get started.

  3. Name it something traceable, such as onelens-cost-readonly.

  4. Add one permission row, and only this one:

Dropdown 1
Dropdown 2
Dropdown 3

Account

Billing

Read

  1. Under Account Resources, leave the selection on this account. An account-owned token is scoped to its owning account, so there is nothing to widen here.

  2. Leave Zone Resources unset. This integration needs no zone-scoped permission, because zone names arrive inside the billing records.

  3. Under TTL, set an expiry matching your rotation policy. 90 days is common. Leave blank for no expiry.

  4. Select Continue to summary, review, then Create Token.

  5. Copy the token immediately. Cloudflare shows it once and never again.

2

Verify the Token

Confirm the token is active before testing anything else.

Expected:

A success: false with code 6111 means the token string is wrong.

3

Confirm Your Account Is Covered

This is the decisive call. It tells you whether the Billable Usage API will return anything at all for this account.

Expected on a supported account:

covered value

What it means

What to do

true

The account has self-serve subscriptions and returns billing data

Continue to step 4

false

The account is entirely on an Enterprise contract

Stop. This integration cannot ingest cost for this account. Contact support@astuto.ai

If you are connecting several accounts, check each one. Coverage is a property of the account, not of your organization, and a mixed result is normal. It is especially common if an Enterprise account sits alongside self-serve ones.

4

Validate the Cost Data

Pull last month's billed cost. Omitting from and to defaults to the current billing period, which may be nearly empty early in a cycle, so a closed month is the better test.

Each row represents one product over one charge period:

What to check before moving on:

Field
What good looks like

Row count

More than zero. An empty result array on a covered: true account usually means no metered charges in the window, so widen the range

ServiceName spread

Should list the products you actually pay for, such as Workers, R2, D1, Images, Stream, and Zero Trust

BilledCost

Non-zero, and summing close to your invoice for that month. Small differences are normal until a period closes

PricingQuantity vs ConsumedQuantity

These differ where a free allowance applies. PricingQuantity is post-allowance and is what you are charged on

ListCost vs BilledCost

A gap means a discount or credit was applied. Both are ingested so the difference stays visible

ZoneId / ZoneName

Populated on zone-scoped charges such as domain plans, and null on account-level products like Workers. Both are expected

BillingCurrency

Matches your invoice currency

Sanity-check the total against your invoice:

5

Connect to OneLens

Provide the following, either through the OneLens dashboard or by emailing support@astuto.ai.

Field
Value
Example

API Token

The token from step 1. Share securely, see note below

Xy7...

Cloudflare Account ID

The 32-character ID from the dashboard URL

023e105f4ecef8ad9ca31a8372d0c353

Account label

Optional. A friendlier name than the raw ID

acme-production

Verification. Once OneLens confirms the connection, typically within 24 hours, check the OneLens dashboard for:

  • Cloudflare appearing as a cost source with a non-zero total for the last closed month

  • A per-product breakdown listing the products you saw in step 4

  • A total that matches your invoice once the flat fees are added

If you are connecting more than one account, repeat these five steps for each, then confirm all of them appear as separate sources in OneLens.

Data Refresh Schedule

  • Billable usage is pulled once daily. Cloudflare updates billing data daily, so polling more often returns the same numbers.

  • Coverage check re-runs weekly. This is how OneLens notices if the account moves onto an Enterprise contract, at which point cost ingestion will stop returning data and we will tell you rather than silently reporting zero.

  • New accounts are added when you send us a token for them. OneLens holds no permission to list your accounts and its token cannot reach beyond the one that owns it, so it cannot discover them on its own.

Current-period figures shift until the billing period closes. Cloudflare also issues corrections against closed periods, so OneLens re-reads the previous period for several days after close and restates if a correction lands.

Data Privacy & Security

  • Cost data only. No analytics permission is on the token, so traffic, performance, and usage telemetry are unreachable by design rather than by policy.

  • One read scope. Billing → Read, and nothing else. No analytics, no account settings, no zone permissions, no logs.

  • Scoped to one account. An account-owned token cannot reach any account other than the one that owns it.

  • API-only. No agent, no Worker deployed, no SSH, no database credentials, nothing installed in your environment.

  • No content. No request or response bodies, no Worker source, no R2 objects, no DNS records, no logs.

  • No billing profile. Address and card metadata are not ingested.

  • Not tied to a person. An account-owned token is a service principal, so no employee's departure silently breaks or extends access.

  • Expiring credentials. Set a token TTL matching your rotation policy, and OneLens alerts before expiry.

  • TLS in transit. All calls use HTTPS/TLS 1.2+.

  • Encrypted at rest. The token and ingested data are encrypted at rest using GCP KMS.

  • Data retention. 12-month default, configurable. Deletion within 30 days on request, with confirmation.

Troubleshooting

Since August 2026, Cloudflare's 403 responses include a documentation_url field pointing at the endpoint's reference page with its role requirements. Read that field first on any permission error, then come back to this table.

#
Symptom
Cause
Fix

1

403 with code 9109 on any call

The token has Client IP Address Filtering set, and the call came from an IP outside that list

Run from an allowlisted IP, or edit the token's IP filter in the dashboard. If you set a filter, make sure it includes OneLens's egress ranges as well as your own testing machine

2

403 on /billable-usage but /user/tokens/verify succeeds

Token is valid but missing Billing → Read

Edit the token and add the Account → Billing → Read row

3

covered: false from /billable-usage/info

The account is entirely on an Enterprise contract

Not fixable from either side today, since Cloudflare's usage endpoints are self-serve only. Contact support@astuto.ai

4

success: true but result is an empty array

No metered charges in the window, or the products in use are all on contract subscriptions

Widen the date range to a full closed month. Cross-check Manage Account → Billing → Billable Usage in the dashboard

5

403 when calling a different account with the same token

An account-owned token is scoped to the account that owns it

Expected. Create a separate token in that account and connect it as its own source

6

You cannot find the option to create the token

Account-owned tokens can only be created by Super Administrators, and only from Manage Account → API Tokens, not My Profile

Ask a Super Administrator on the account to create it

7

429 Too Many Requests

Cloudflare's REST limit is 1,200 requests per 5 minutes per user, applied cumulatively across the dashboard, API keys, and tokens

OneLens backs off automatically. If it persists, a script of yours or your own dashboard use is sharing the quota, since Cloudflare counts all three together

8

OneLens total is lower than the invoice

Fixed plan fees and per-zone add-ons are not usage-based and are not returned by these endpoints

Expected. Send us your plan mix per step 5 so OneLens represents the flat charges alongside the metered ones

9

Workers or R2 shows as a single line, not per script or bucket

Cloudflare bills those at product level and attributes nothing below it

Working as intended. This integration reports only what Cloudflare bills, and does not estimate a split

10

Backfill returns less history than you asked for

Cloudflare does not document a retention window for billable usage, and in practice the API stops returning rows past a certain depth

Not fixable from our side. OneLens persists every daily pull, so your history grows forward from the connection date regardless

11

Data stopped arriving after working fine

Token TTL expired, or the token was revoked

Check Manage Account → API Tokens for status. Create a replacement and send it to OneLens

12

Costs changed for a month that already closed

Cloudflare issued a correction or re-bill

Expected. OneLens restates the period to match

Frequently Asked Questions

Can OneLens see our traffic, requests, or logs?

No, and not because of a policy commitment. The token carries exactly one permission, Billing → Read, which grants no access to analytics or logs. Traffic data is not reachable with this credential even if someone tried.

You can verify this yourself: open the token in Manage Account → API Tokens and confirm that is the only row on it.

Is Billing Read really the only permission you need?

Yes. Cloudflare describes that scope as granting "read access to billing profile, subscriptions, and access to fetch invoices and entitlements", and both calls this integration makes are covered by it.

We considered asking for Account Settings → Read as well, because it would let us call GET /accounts and discover your accounts instead of you telling us. We decided the convenience wasn't worth a permission you don't need. If a future OneLens release wants another Cloudflare permission, it will be in this document with a reason attached, and it will be your decision.

Why an account-owned token rather than a personal one?

Because a personal token is only as durable as its owner's access. User tokens act on behalf of a particular user and inherit a subset of that user's permissions, so when the person who created it changes role or leaves, the integration can break without anyone noticing until a cost report goes empty.

An account-owned token is a service principal. It belongs to the account, has its own permission set independent of any employee, and survives staff changes. Cloudflare confirms Billing is among the products that support account-owned tokens, so there is no functional trade-off here.

The one thing to know is that creating and managing them requires Super Administrator on the account.

We have several Cloudflare accounts. How does that work?

Run the five steps once per account, each producing its own token, and connect each as its own source. OneLens reports across all of them together and converts into a single currency, so you still get one consolidated Cloudflare view.

The reason it is per account rather than one token for all of them is that Cloudflare scopes an account-owned token to the account that owns it. We prefer that boundary: a token that can only read one account's bill is a smaller blast radius if it ever leaks, and it means revoking access to one account does not disturb the others.

Coverage is also decided per account, so check each one at step 3 rather than assuming they behave alike.

We're on an Enterprise contract. Can we use this integration?

Not today. Cloudflare's billable usage endpoints are self-serve only, and they expose none of what makes up an Enterprise bill: not the negotiated rate card, not the commitment, not the monthly platform fee, not discounts or credits. The API returns covered: false and no rows for a pure-contract account.

There is also no way to reconstruct it. Most Enterprise spend is a flat negotiated fee with no meter behind it, so no amount of other data derives it. Cloudflare has said an Enterprise equivalent is in the works, but it is not available now and we have no ship date. If you are on Enterprise, contact support@astuto.ai and we will tell you honestly what a manual arrangement would involve.

How do I tell which kind of Cloudflare account we have?

Fastest way, no token needed. In the dashboard go to Manage Account → Billing → Billable Usage. A populated daily cost chart means pay-as-you-go. An empty or ineligible page means Enterprise contract.

Programmatically, GET /accounts/{account_id}/billable-usage/info returns a covered boolean.

Why is Workers a single line instead of per script?

Because that is how Cloudflare bills it. Workers is an account-level product, and the billing record attributes the charge to the product, not to individual scripts. The same is true of R2 buckets, D1 databases, KV namespaces, and Durable Objects.

We could estimate a split from Cloudflare's analytics API, and we deliberately don't. Cloudflare's own documentation warns those datasets should not be used to measure billing usage, because they count traffic billing excludes. An estimated split also cannot be reconciled to an invoice line, which makes it dangerous the moment someone charges a team for it. Every number in this integration is one Cloudflare billed you.

Can we allocate Cloudflare cost to teams or cost centres?

At account and zone level, yes. Zone-scoped charges carry a zone ID and name, so domain-level cost is real billed cost, and you can group accounts and zones into cost centres in OneLens.

Below that, no. Cloudflare's billing data has no tag dimension. Resource Tagging exists in public beta and Cloudflare lists billing attribution among its purposes, but tags do not yet appear as a field in the billable usage response. If that changes we will pick it up. If your allocation needs to reach individual Workers or buckets, tell us during onboarding so we can be clear about what is and is not possible before you design a chargeback around it.

Can OneLens change our DNS, WAF rules, plan, or payment method?

No. The one permission on the token is Read, so there is no write, edit, or admin capability anywhere on it. Changing a plan or payment method needs Billing → Write, which we do not request. The token also carries no zone-scoped permission at all, so DNS and WAF configuration are not even readable.

Will this impact our Cloudflare performance or count against our limits?

Performance, no. These are read calls against Cloudflare's billing system, nothing in your request path.

Limits, marginally. Cloudflare's REST limit is 1,200 requests per 5 minutes, and OneLens makes two calls per day. Worth knowing: Cloudflare applies that limit cumulatively across the dashboard, API keys, and tokens, so heavy automation of your own contends with ours. If you are already close to the limit, tell us and we will stagger our pull window.

How do I rotate the token?

Create a replacement token with the same single scope, send it to OneLens securely, confirm ingestion continues on the next daily pull, then delete the old token in Manage Account → API Tokens. Overlapping them means no ingestion gap.

Cloudflare also supports rolling a token in place from the token list, which keeps the same token ID but issues a new secret. Either approach works, and the new secret still has to reach OneLens.

How do I disconnect OneLens?

Delete or roll the API token in Manage Account → API Tokens. Ingestion stops on the next attempted pull, immediately and unilaterally, so you do not need OneLens to act. Historical data already ingested remains in OneLens until you request deletion, which is completed within 30 days with confirmation.

Why is our OneLens Cloudflare total lower than our invoice?

These endpoints return usage-based charges only. Flat monthly fees are not usage-based and are not in the API, which covers Pro and Business plans and per-zone add-ons like Bot Management. Your OneLens total will read lower by the sum of those fees.

Send us your plan mix during step 5 and OneLens represents those flat charges alongside the metered ones, so the total matches your invoice.

Need Help?

Cloudflare official docs:

OneLens support: support@astuto.ai

Last updated