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.
Coverage limit, read this first. This integration supports pay-as-you-go (self-serve) Cloudflare accounts only. Cloudflare's billable usage endpoints cover self-serve subscriptions only, so OneLens cannot ingest cost for accounts on an Enterprise contract. Cloudflare has said Enterprise support is in the works, with no published date. See Before You Start: Is Your Account Supported? to check which you have in under a minute.
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.
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.
What You'll Get Once Connected
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.
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.
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:
GET /accounts/{account_id}/billable-usage/infoto confirm the account still returns billing data.GET /accounts/{account_id}/billable-usagefor 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.
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.
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.
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
Note on API maturity. Cloudflare labels its billing usage endpoints Version 1, Alpha, with a Version 2, Alpha, Restricted successor. Alpha means Cloudflare can change the shape without a deprecation cycle. Cloudflare's billing index also lists each billable-usage path twice, once plain Alpha and once marked Deprecated, so if you go browsing the reference yourself, expect to meet a deprecated twin of the exact path above. OneLens builds on the v1 endpoints because they are the ones open to self-serve accounts today, we monitor the reference for changes, and absorbing a schema change is our job rather than yours. We flag it because it is the one part of this integration that depends on an interface Cloudflare has not frozen.
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: Readis 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 ReadnorWorkers R2 Storage Readis 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 → Readis 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/.curlandjqon the machine you run the validation calls from.
Validate and Connect
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.
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.
Under Custom token, select Get started.
Name it something traceable, such as
onelens-cost-readonly.Add one permission row, and only this one:
Account
Billing
Read
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.
Leave Zone Resources unset. This integration needs no zone-scoped permission, because zone names arrive inside the billing records.
Under TTL, set an expiry matching your rotation policy. 90 days is common. Leave blank for no expiry.
Select Continue to summary, review, then Create Token.
Copy the token immediately. Cloudflare shows it once and never again.
Do not use a Global API Key. It grants full read and write access to every resource on every account and zone your user can reach, and it carries none of the scoping, IP filtering, or TTL that the token flow above gives you. OneLens will not accept one.
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
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:
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:
Fixed plan fees are not in here. These endpoints return usage-based charges. Your flat monthly fees, meaning Pro or Business plans and per-zone add-ons like Bot Management, are not included. This total will read lower than your invoice by the sum of those fees. That is expected, not a bug, and step 5 covers how to represent them.
Connect to OneLens
Provide the following, either through the OneLens dashboard or by emailing support@astuto.ai.
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
Share the token securely. Never send an API token over email or chat. Use a validated secure sharing tool such as Password.link.
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.
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
Need Help?
Cloudflare official docs:
OneLens support: support@astuto.ai
Last updated

