feat(invoice): feature cost
This is a PoC to help understand the cost behind invoice line items and break them down by meter dimensions. This is useful to understand the invoiced cost of individual users, workspaces, etc.
TODO
- [ ] Finalize API
- [ ] Move into service
- [ ] Add tests
Invoice Feature Cost
GET /api/v1/billing/invoices/01K3M32GV47W7RD1XR93091X2Y/lines/01K3M32GVCEZ8BTG62DX0NVBQH/cost?windowSize=MINUTE&groupBy=model
{
"costPerUnit": "0.01",
"currency": "USD",
"from": "2025-08-26T21:03:19Z",
"rows": [
{
"cost": "1",
"groupBy": {
"model": "gpt-3"
},
"usage": "100",
"windowEnd": "2025-08-26T21:10:00Z",
"windowStart": "2025-08-26T21:09:00Z"
},
{
"cost": "1",
"groupBy": {
"model": "gpt-3"
},
"usage": "100",
"windowEnd": "2025-08-26T21:15:00Z",
"windowStart": "2025-08-26T21:14:00Z"
},
{
"cost": "1",
"groupBy": {
"model": "gpt-4"
},
"usage": "100",
"windowEnd": "2025-08-26T21:15:00Z",
"windowStart": "2025-08-26T21:14:00Z"
}
],
"to": "2025-09-26T21:03:19Z",
"totalCost": "3",
"totalUsage": "300"
}
Invoice
GET /api/v1/billing/invoices/01K3M32GV47W7RD1XR93091X2Y
{
"collectionAt": "2025-09-26T21:03:19Z",
"createdAt": "2025-08-26T21:03:19.396259Z",
"currency": "USD",
"customer": {
"id": "01K3M32BS0MCA6ZCZQS60EA5CT",
"name": "Customer 2",
"usageAttribution": {
"subjectKeys": [
"customer-2"
]
}
},
"id": "01K3M32GV47W7RD1XR93091X2Y",
"lines": [
{
"children": [
{
"category": "regular",
"createdAt": "2025-08-26T14:20:30.396154-07:00",
"currency": "USD",
"id": "01K3M41ZNW07N1NZM67DF4DZT8",
"invoice": {
"id": "01K3M32GV47W7RD1XR93091X2Y"
},
"invoiceAt": "2025-09-26T21:03:19Z",
"managedBy": "system",
"metadata": null,
"name": "AI Tokens: usage in period",
"paymentTerm": "in_arrears",
"perUnitAmount": "0.01",
"period": {
"from": "2025-08-26T21:03:19Z",
"to": "2025-09-26T21:03:19Z"
},
"quantity": "300",
"rateCard": {
"price": {
"amount": "0.01",
"paymentTerm": "in_arrears",
"type": "flat"
},
"quantity": "300"
},
"status": "detailed",
"totals": {
"amount": "3",
"chargesTotal": "0",
"discountsTotal": "0",
"taxesExclusiveTotal": "0",
"taxesInclusiveTotal": "0",
"taxesTotal": "0",
"total": "3"
},
"type": "flat_fee",
"updatedAt": "2025-08-26T14:20:30.396154-07:00"
}
],
"createdAt": "2025-08-26T21:03:19.404195Z",
"currency": "USD",
"featureKey": "ai_tokens",
"id": "01K3M32GVCEZ8BTG62DX0NVBQH",
"invoice": {
"id": "01K3M32GV47W7RD1XR93091X2Y"
},
"invoiceAt": "2025-09-26T21:03:19Z",
"managedBy": "subscription",
"metadata": null,
"name": "AI Tokens",
"period": {
"from": "2025-08-26T21:03:19Z",
"to": "2025-09-26T21:03:19Z"
},
"price": {
"amount": "0.01",
"type": "unit"
},
"quantity": "300",
"rateCard": {
"featureKey": "ai_tokens",
"price": {
"amount": "0.01",
"type": "unit"
}
},
"status": "valid",
"subscription": {
"billingPeriod": {
"from": "2025-08-26T21:03:19Z",
"to": "2025-09-26T21:03:19Z"
},
"item": {
"id": "01K3M32GQAE770PXQH2D2AFF3X"
},
"phase": {
"id": "01K3M32GQC65X37KRT5AY3CCAN"
},
"subscription": {
"id": "01K3M32GQET6ZS9ZCX5WG2K6BR"
}
},
"totals": {
"amount": "3",
"chargesTotal": "0",
"discountsTotal": "0",
"taxesExclusiveTotal": "0",
"taxesInclusiveTotal": "0",
"taxesTotal": "0",
"total": "3"
},
"type": "usage_based",
"updatedAt": "2025-08-26T21:03:19.404195Z"
}
],
"metadata": null,
"number": "GATHER-CU2-USD-1",
"period": {
"from": "2025-08-26T21:03:19Z",
"to": "2025-09-26T21:03:19Z"
},
"quantitySnapshotedAt": "2025-08-26T14:20:30.354639-07:00",
"status": "gathering",
"statusDetails": {
"availableActions": {
"invoice": {}
},
"extendedStatus": "gathering",
"failed": false,
"immutable": false
},
"supplier": {
"addresses": [
{
"country": "US"
}
],
"name": "OpenMeter"
},
"totals": {
"amount": "3",
"chargesTotal": "0",
"discountsTotal": "0",
"taxesExclusiveTotal": "0",
"taxesInclusiveTotal": "0",
"taxesTotal": "0",
"total": "3"
},
"type": "standard",
"updatedAt": "2025-08-26T21:03:19.42197Z",
"workflow": {...}
}
[!IMPORTANT]
Review skipped
Draft detected.
Please check the settings in the CodeRabbit UI or the
.coderabbit.yamlfile in this repository. To trigger a single review, invoke the@coderabbitai reviewcommand.You can disable this status message by setting the
reviews.review_statustofalsein the CodeRabbit configuration file.
✨ Finishing touches
🧪 Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
- [ ] Commit unit tests in branch
feat/invoice-cost
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.