How It Works
Cloudflare AI Gateway writes one encrypted Logpush record per request to an S3 bucket you own. Vantage decrypts those records with the private key you provide, normalizes them into a common usage index, and joins that index to your provider costs during each provider’s cost ingestion. The enrichment pipeline runs through the following steps:How Cost Rows Are Split
For each matched cost row, the cost is allocated proportionally across the tag slices present in your logs, weighted by token usage: Splits are additive: the sum of the enriched rows always equals the original cost row to the cent. Existing provider-level reports continue to show the same totals; enrichment only makes new dimensions available on the underlying rows.gpt-5.2-2025-12-11 is $100 for the day, covering 100M input tokens. Your gateway logs for that day group into these tag slices:$100 row becomes three rows:$100. The leftover row carries the portion of the cost row’s tokens that your logs do not cover; it keeps the provider’s existing tags and the vntg:ai:model tag but none of the slice tags, so totals always reconcile and no dollars are lost. Cost rows with no matching logs pass through without allocation splits.If your logs instead report more usage than the provider billed, Vantage still allocates only the billed cost, split across your tag slices in proportion to each slice’s usage. The surplus does not create additional cost, and there is no leftover row in that case.Data Freshness and Backfill
Enrichment runs as part of each provider’s existing cost ingestion, so it follows that provider’s refresh cadence. Recent days are reprocessed within a rolling three-day window so late-arriving logs are picked up. See the provider data refresh documentation for per-provider timing. A billing period is enriched whenever it is processed while an active source exists, for as long as the matching logs remain in your bucket. Late-arriving logs for recent days are picked up automatically within the rolling three-day window. For older periods, Vantage re-enriches a day when the set of log objects for that day changes (files are added or removed) or when a full rebuild is triggered; replacing the contents of an existing object under the same key does not, on its own, re-trigger enrichment. Re-enrichment reads the already-normalized cost data, so it does not require a full cost re-import.Prerequisites
Before you begin, make sure:- An active cost integration exists for at least one supported provider: OpenAI, Anthropic, or Azure.
- An active AWS integration (cross-account IAM role) exists for the account that owns the S3 bucket. Vantage reads the bucket through this role, so it is required even when the model-provider costs you enrich are not themselves on AWS.
- Cloudflare AI Gateway Workers Logpush is available to you (it requires the Workers Paid plan), and logging is enabled on the gateway whose traffic you want to attribute.
- You have an S3 bucket you own where Cloudflare AI Gateway delivers (or will deliver) your Logpush logs.
- You have an RSA key pair for Workers Logpush encryption: the public key is uploaded to your AI Gateway settings, and you have the matching PEM-encoded private key to provide to Vantage.
- You have a Vantage Organization Owner or Integration Owner role. See Role-Based Access Control.
Set Up Cloudflare AI Gateway Enrichment
Setup has two steps: configure Cloudflare AI Gateway Logpush to your S3 bucket and connect the source in Vantage, where you select the bucket, provide your decryption key, grant Vantage read access, and then review which providers Vantage detected.Step 1: Configure Cloudflare AI Gateway Logpush
In Cloudflare, turn on logging for the gateway, then create a Logpush job for your AI Gateway that delivers logs to your S3 bucket. When you create the job, select the AI Gateway dataset so Vantage receives gateway logs rather than another log type.- Destination: point the job at the S3 bucket you own, and enable Organize logs into daily subfolders in the destination setup (or include
{DATE}in the destination path if you configure the job through the API). This produces the day-partitioned path Vantage requires; without it, Vantage cannot discover your logs. Vantage expects the day partition and gzip log objects at the end of the path:
- Timestamp format: in the Logpush job’s advanced options, keep the timestamp format as RFC3339 (the default). Unix (epoch seconds) is also accepted, but do not use UnixNano. Vantage reads those values as seconds, which produces invalid dates, so those records will not be enriched.
- Encryption: generate an RSA key pair and upload the public key to your AI Gateway settings, as described in Workers Logpush. Uploading the public key is what enables Workers Logpush; Cloudflare then encrypts the
Metadata,RequestBody, andResponseBodyfields of each record, and Vantage decrypts them with the private key you provide in Step 2. The private key is required. - Custom metadata: attach custom metadata to your gateway requests to drive allocation. Cloudflare saves up to five metadata entries per request (extra entries are dropped), accepts only string, number, and boolean values, and reserves keys beginning with
cf.. Each saved entry that Vantage considers safe becomes a tag on the enriched costs (see the Enrichment Tag Reference). Prefer stable keys with a limited set of values, such asteam,environment, andpurpose.
gpt-5.2-2025-12-11) while your gateway logs may use dated or undated names (gpt-5.2); Vantage prefers the dated form and normalizes undated names to match.Step 2: Connect the Source in Vantage
In Vantage, go to the Integrations page. Under LLM Enrichment, add Cloudflare AI Gateway, then select the S3 bucket (or buckets) that hold your Logpush logs and paste your decryption key. The connect screen walks you through granting read access and validating it, and connecting then scans your recent logs so you can review which providers were found. Connecting reuses your existing AWS cross-account IAM role, adding read-only access to the bucket that holds your logs. It does not create a new role or require new credentials.Select the bucket and provide your decryption key
Grant Vantage read access
- AWS Console
- AWS CLI
- Terraform
VantageCrossAccountRole: the name of your existing Vantage cross-account IAM role.CustomLlmEnrichmentBuckets: a comma-separated list of bucket ARNs, each asarn:aws:s3:::your-bucket/*.
s3:ListBucket and s3:GetBucketLocation. The grant above adds only object read on the log bucket (s3:GetObject, and the generated policy always includes s3:GetObjectAcl).kms:Decrypt separately. See KMS-Encrypted Buckets. This is separate from Cloudflare Logpush log encryption, which Vantage handles with the private key you provide.Check permissions and connect
YYYYMMDD/*.log.gz layout, or a private key that cannot decrypt the sample) are shown as errors you must resolve before connecting. Then click Connect. Vantage confirms the source and immediately scans your recent gateway logs, from the first day of the previous calendar month through today, to detect which providers and provider accounts appear in the bucket. You are taken to a Scanning gateway logs page that refreshes on its own; a large bucket can take several minutes.Review detected providers and confirm
resource_account_id (the Metadata.resourceAccountId value after decryption) or Account identifiers not found: … when account IDs could not be matched to a cost integration. Logs found for unsupported providers appear in a separate banner, not the Notes column. If more than 75% of the scanned rows failed validation, a warning (“N% of scanned log rows failed validation”) suggests confirming that your objects use the expected YYYYMMDD/*.log.gz format and contain provider, model, usage, and status data.Choose which connected cost integrations should receive token enrichment from this bucket, then select Confirm. Vantage enriches costs for the selected integrations on each provider’s next data refresh. You can change the selection later from the source’s Edit screen.Manage Cloudflare AI Gateway Enrichment Sources
Manage your connected buckets from the Cloudflare AI Gateway integration page. The sources table lists each bucket with its AWS account, creation date, and Status (for example, Pending before an import starts, Importing while one runs, Stable once all imports succeed, Warning if only some imports fail, Error if a scan or all imports fail, or Paused if the source is stopped). A shared-bucket warning icon appears next to the bucket name when sibling integrations requireresourceAccountId; error details appear beneath the status. Each row has a primary button, Review, Edit, or Resume, depending on the source’s state, and a ⋮ (More actions) menu with View import history and, for sources that are not paused, Stop.
Choose Which Integrations Are Enriched
After a scan finishes, select Review on the source to choose which connected cost integrations receive enrichment (see Step 2). To change that selection later, select Edit in the source’s row. The edit screen lists each provider integration with its import status (for example, Stable, Pending, Importing, Warning, Error, Paused, or Unenriched), and for a provider with multiple accounts shows a count like 2 of 3 accounts enabled. It lets you enable or disable enrichment per integration. Disabling an integration here stops going-forward enrichment for it but leaves its existing enriched history in place.View Import History
In the sources table, open the row’s ⋮ (More actions) menu and select View import history to open the source’s Import History. The screen lists one row per provider cost integration and billing period that ran enrichment, with columns for the Integration (with its account beneath), Status, Billing Period, Last Enriched At, Log Match Rate, Logs Parsed, and Logs Skipped. When a run needs attention (for example, a shared bucket whose logs lackresourceAccountId), the reason appears in the Status column. Lifecycle changes also appear as marker rows: Added when enrichment is first enabled for an integration, and Paused or Resumed when you stop, disable, resume, or re-enable it.
Stop a Source
To stop a source, open the row’s ⋮ (More actions) menu and select Stop, then confirm in the Stop enrichment source dialog. This is a soft deactivation, not a hard delete: Vantage stops enriching new cost data for that bucket, but your existing enriched history is left unchanged, and the source stays visible in the list so you can bring it back at any time.Resume a Source
To resume a stopped source, select Resume in its row. Resuming restarts going-forward enrichment for the integrations that were active when you stopped the source (integrations you had already disabled individually stay disabled) and opens the Edit screen so you can adjust the selection. A stopped bucket cannot be re-added through the connect wizard; use Resume instead.View Enriched Costs on Cost Reports
Once enrichment runs, a single provider cost line is split into multiple rows, each carrying enrichment tags. You can filter and group by these tags anywhere tags are supported: Cost Reports, Virtual Tags, Budgets, and Cost Alerts. Because enrichment splits (allocates) your provider costs, enrichment tags behave like Vantage’s cost allocation tags: you can build a Virtual Tag on them, but a cost can be allocated only once, so an enrichment tag can belong to only one allocation chain. Allocated values show the allocated badge (calculator icon) in the console.Enrichment Tag Reference
vntg:ai: prefix (for example, vntg:ai:model); this keeps them distinct from your keys and consistent with the AI tags Vantage applies to provider costs. Because a key like team is not provider-namespaced, it lines up across OpenAI, Anthropic, and Azure, so you can group your entire AI stack by one team tag.
Two normalization rules are worth knowing when you choose metadata key names:
- Keys are lowercased and snake_cased before they become tags. So
userEmail,UserEmail, anduser_emailall collapse touser_email, and any keys that normalize to the same string are merged into one tag. - Keys that normalize to a Vantage-managed name are re-emitted under
vntg:ai:instead of staying bare. Those names aremodel,provider_region,service_tier,user_email,user_name,user_id,is_batch,endpoint, andapi_key_id(andresource_account_id, which is dropped rather than tagged). For example, theuserkey in the Use Cases table below stays bare asuser, but auserIdkey would silently move tovntg:ai:user_id. - A metadata key can overwrite a gateway-context tag. The
gateway,cached, andrate_limitedtags come from the top-level gateway fields, but a metadata key that normalizes to one of those names replaces the gateway-derived value. Avoid reusing those names in your metadata. Metadata.timestampdoes double duty. It is used to pick the billing day and, because it is not a reserved key, also becomes atimestamptag. Since a timestamp is high-cardinality, avoid emitting it as metadata unless you want it as a tag.
- To group: open the Group By menu, select Tag, and choose the tag key, for example
vntg:ai:model(values likegpt-5.2-2025-12-11) or a metadata key such asteam. - To filter: open the Filters menu, click New Rule, select Tag, choose the Tag Key, then pick an operator and one or more values.
vntg:ai:* tags (such as vntg:ai:model); split rows also carry the tags from their usage slice. When a slice tag and an existing tag use the same key, the enrichment value wins. The leftover row (usage not covered by logs) keeps the provider’s existing tags and the applicable vntg:ai:* tags but carries none of the slice tags. Request identifiers and resourceAccountId are never turned into tags.Troubleshooting
Most errors are displayed when you click Check Permissions or Connect. The tables below list the messages you may see, their cause, and how to resolve them. Expand a section for the relevant category.Permission and access errors
Permission and access errors
Decryption errors
Decryption errors
Bucket and log errors
Bucket and log errors
My costs are not being split
My costs are not being split
- There is no active Cloudflare AI Gateway source for the account, or the logs have not been ingested for that billing period.
- The cost row’s model or token type could not be matched to a logged request for that provider, date, and token kind.
- Records were skipped during ingestion because the decrypted
Metadatawas missing or not an object, theProviderwas blank or unsupported, the model was blank or could not be matched to your provider cost data, the request was not successful (a missing or empty response body, a non-2xx status, a rate-limited request, or a response error), or no usage value was a positive integer.
My totals changed after enabling enrichment
My totals changed after enabling enrichment
KMS-Encrypted Buckets
If your log bucket is encrypted with AWS Key Management Service (KMS), Check Permissions reports a decryption error until Vantage can read the objects. Either remove encryption on the bucket, or grant the cross-account rolekms:Decrypt for the encrypting key and allow that role in the KMS key policy. The CloudFormation, CLI, and Terraform options in Step 2 grant S3 read access only, so KMS access must be added separately. This is distinct from Cloudflare Logpush log encryption, which Vantage handles with the private key you provide.
Use Cases
Each row below shows example metadata to emit on your gateway requests and what that attribution enables in Vantage. The key names are examples; you choose your own, and Vantage surfaces whatever metadata you send. All rows assume logs are delivered to a connected bucket.Frequently Asked Questions
Which providers are supported?
Which providers are supported?
Do I need a Cloudflare cost integration?
Do I need a Cloudflare cost integration?
Do I still need Custom LLM Enrichment?
Do I still need Custom LLM Enrichment?
What Vantage permissions do I need to enable this?
What Vantage permissions do I need to enable this?
What access does Vantage gain in my AWS account?
What access does Vantage gain in my AWS account?
s3:GetObject, s3:ListBucket, s3:GetBucketLocation, and kms:Decrypt for KMS-encrypted objects (generated policies may also include s3:GetObjectAcl). The policy attaches to your existing cross-account role; no new role is created. See Step 2: Connect the Source in Vantage.Does Vantage have write access to Cloudflare or my S3 bucket?
Does Vantage have write access to Cloudflare or my S3 bucket?
Why does Vantage need a private key?
Why does Vantage need a private key?
Metadata, RequestBody, and ResponseBody fields of each record with your public key. Vantage decrypts those fields with the matching private key you provide so it can read the provider, model, token counts, and your custom metadata. The private key is stored securely and used only for decryption.Will this change my totals or break existing reports?
Will this change my totals or break existing reports?
Does Vantage store my prompt content?
Does Vantage store my prompt content?