ampr docs

CDRs

Charge Detail Records (immutable billing receipts)

GET /cdrs List charge detail records

Parameters

Name In Type Required Description
page query integer
per_page query integer
charger_id query string
start_date query string format: date-time
end_date query string format: date-time
payment_reference query string Return only CDRs reconciled to this CPO-supplied PSP transaction reference. Org-scoped; a reference may map to several CDRs (a booking spanning sessions), so more than one result is legitimate.
payment_provider query string Return only CDRs with a reconciliation from this PSP (open set).

Responses

200 CDR list

PropertyTypeRequiredDescription
dataarray<CDR>
PropertyTypeRequiredDescription
idstringrequired
session_idstringrequired
tariff_idstringnullable
currencystringrequired
start_timestringformat: date-time
end_timestringformat: date-time
total_energy_whintegerrequiredTotal energy consumed
total_time_sintegerrequiredTotal session duration in seconds
total_costnumberformat: doublerequiredTotal cost calculated from tariff
line_itemsarray<CDRLineItem>
PropertyTypeRequiredDescription
typeenum
  • ENERGY
  • TIME
  • PARKING_TIME
  • FLAT
required
descriptionstringnullable
quantitynumberrequiredUnits consumed (kWh for energy, hours for time)
unit_pricenumberrequired
costnumberformat: doublerequired
statusenum
  • valid
  • unbillable
`valid` = priced CDR suitable for downstream billing / OCPI export. `unbillable` = session completed but no usable tariff — CDR is kept as a data record but total_cost is zero. Driver-payment state (if the CPO runs their own collection) is tracked outside Ampr.
payment_referencesarray<PaymentReferenceView>CPO-supplied PSP transaction references reconciled to this CDR (the CPO's own Payter/Viva terminal id or Stripe PaymentIntent id). Attached via the payment-reference endpoints; joined from a separate annotation table so the immutable CDR row is never mutated. Often empty — the CPO commonly attaches its reference after the CDR is generated. NEVER a driver identifier / OCPP idTag.
PropertyTypeRequiredDescription
referencestringrequiredOpaque PSP transaction id from the CPO's own rails.
providerstringrequiredThe PSP the reference belongs to. Open set — `payter`, `viva`, `stripe`, `other`, and any future provider (no enum constraint).
billing_decisionBillingDecision | nullWhy this CDR was billed the way it was, for sessions where the underlying meter data was incomplete (e.g. a dropped StopTransaction). `null` for CDRs generated the normal way with no billing decision recorded. Only present on the single-CDR detail endpoint. See `GET /cdrs/{cdr_id}/billing-decision` for the full audit record (including the correction chain).
  • PropertyTypeRequiredDescription
    outcomeenum
    • billed
    • recovered_partial
    • unbillable
    required`billed` = normal complete-data billing. `recovered_partial` = billed from a recovered/last-known meter reading after missing data. `unbillable` = insufficient evidence to bill; CDR kept as a data record only.
    reason_codestringrequiredMachine-readable reason, e.g. `missing_stop_recovered`.
    explanationstringrequiredHuman-readable explanation of the billing outcome.
    evidenceobjectrequiredStructured evidence supporting the decision (meter register snapshot, missing frame types, source message references), including a `frameRef` tying the decision back to the originating OCPP transaction/message for audit traceability.
  • null
created_atstringformat: date-timerequired
paginationPagination
PropertyTypeRequiredDescription
totalintegerrequired
pageintegerrequired
per_pageintegerrequired
has_morebooleanrequired

401 Missing or invalid API key application/problem+json

PropertyTypeRequiredDescription
typestringformat: urirequired
titlestringrequired
statusintegerrequired
detailstringnullable
instancestringnullable

Request example

curl -X GET "https://api.ampr.dev/v1/cdrs" \
  -H "Authorization: Bearer $AMPR_API_KEY"
Note
This endpoint requires an API key. Send it as a Bearer token in the Authorization header.

GET /cdrs/{cdr_id} Get charge detail record

Parameters

Name In Type Required Description
cdr_id path string required

Responses

200 CDR detail

PropertyTypeRequiredDescription
dataCDR
PropertyTypeRequiredDescription
idstringrequired
session_idstringrequired
tariff_idstringnullable
currencystringrequired
start_timestringformat: date-time
end_timestringformat: date-time
total_energy_whintegerrequiredTotal energy consumed
total_time_sintegerrequiredTotal session duration in seconds
total_costnumberformat: doublerequiredTotal cost calculated from tariff
line_itemsarray<CDRLineItem>
PropertyTypeRequiredDescription
typeenum
  • ENERGY
  • TIME
  • PARKING_TIME
  • FLAT
required
descriptionstringnullable
quantitynumberrequiredUnits consumed (kWh for energy, hours for time)
unit_pricenumberrequired
costnumberformat: doublerequired
statusenum
  • valid
  • unbillable
`valid` = priced CDR suitable for downstream billing / OCPI export. `unbillable` = session completed but no usable tariff — CDR is kept as a data record but total_cost is zero. Driver-payment state (if the CPO runs their own collection) is tracked outside Ampr.
payment_referencesarray<PaymentReferenceView>CPO-supplied PSP transaction references reconciled to this CDR (the CPO's own Payter/Viva terminal id or Stripe PaymentIntent id). Attached via the payment-reference endpoints; joined from a separate annotation table so the immutable CDR row is never mutated. Often empty — the CPO commonly attaches its reference after the CDR is generated. NEVER a driver identifier / OCPP idTag.
PropertyTypeRequiredDescription
referencestringrequiredOpaque PSP transaction id from the CPO's own rails.
providerstringrequiredThe PSP the reference belongs to. Open set — `payter`, `viva`, `stripe`, `other`, and any future provider (no enum constraint).
billing_decisionBillingDecision | nullWhy this CDR was billed the way it was, for sessions where the underlying meter data was incomplete (e.g. a dropped StopTransaction). `null` for CDRs generated the normal way with no billing decision recorded. Only present on the single-CDR detail endpoint. See `GET /cdrs/{cdr_id}/billing-decision` for the full audit record (including the correction chain).
  • PropertyTypeRequiredDescription
    outcomeenum
    • billed
    • recovered_partial
    • unbillable
    required`billed` = normal complete-data billing. `recovered_partial` = billed from a recovered/last-known meter reading after missing data. `unbillable` = insufficient evidence to bill; CDR kept as a data record only.
    reason_codestringrequiredMachine-readable reason, e.g. `missing_stop_recovered`.
    explanationstringrequiredHuman-readable explanation of the billing outcome.
    evidenceobjectrequiredStructured evidence supporting the decision (meter register snapshot, missing frame types, source message references), including a `frameRef` tying the decision back to the originating OCPP transaction/message for audit traceability.
  • null
created_atstringformat: date-timerequired

401 Missing or invalid API key application/problem+json

PropertyTypeRequiredDescription
typestringformat: urirequired
titlestringrequired
statusintegerrequired
detailstringnullable
instancestringnullable

404 Resource not found application/problem+json

PropertyTypeRequiredDescription
typestringformat: urirequired
titlestringrequired
statusintegerrequired
detailstringnullable
instancestringnullable

Request example

curl -X GET "https://api.ampr.dev/v1/cdrs/cdr_example" \
  -H "Authorization: Bearer $AMPR_API_KEY"
Note
This endpoint requires an API key. Send it as a Bearer token in the Authorization header.

POST /cdrs/{cdr_id}/payment-reference Attach a payment reference to a CDR

Record a CPO-supplied PSP transaction reference against a CDR that already exists (a terminal often finalizes its settlement id after the session ends). Requires the `operator` role or higher. Idempotent per `(session, reference)`. The immutable CDR row is NEVER mutated — the reference is stored as a separate annotation. The reference MUST be the CPO's own PSP id, never a driver identifier / OCPP idTag.

Parameters

Name In Type Required Description
cdr_id path string required

Request body

PropertyTypeRequiredDescription
payment_referencestringrequiredOpaque PSP transaction id from the CPO's own payment rails. Stored verbatim. MUST NOT be a driver identifier / OCPP idTag.
payment_providerstringrequiredThe PSP the reference belongs to (open set: payter | viva | stripe | other | any future provider).

Responses

200 Reference already attached (idempotent no-op)

PropertyTypeRequiredDescription
dataPaymentReference
PropertyTypeRequiredDescription
idstringrequired
session_idstringrequired
cdr_idstringnullableThe CDR the reference is linked to, once one exists.
payment_referencestringrequired
payment_providerstringrequired
created_atstringformat: date-timerequired

201 Reference attached

PropertyTypeRequiredDescription
dataPaymentReference
PropertyTypeRequiredDescription
idstringrequired
session_idstringrequired
cdr_idstringnullableThe CDR the reference is linked to, once one exists.
payment_referencestringrequired
payment_providerstringrequired
created_atstringformat: date-timerequired

400 Invalid request parameters application/problem+json

PropertyTypeRequiredDescription
typestringformat: urirequired
titlestringrequired
statusintegerrequired
detailstringnullable
instancestringnullable

401 Missing or invalid API key application/problem+json

PropertyTypeRequiredDescription
typestringformat: urirequired
titlestringrequired
statusintegerrequired
detailstringnullable
instancestringnullable

403 Authenticated but not authorized for this action (insufficient role) application/problem+json

PropertyTypeRequiredDescription
typestringformat: urirequired
titlestringrequired
statusintegerrequired
detailstringnullable
instancestringnullable

404 Resource not found application/problem+json

PropertyTypeRequiredDescription
typestringformat: urirequired
titlestringrequired
statusintegerrequired
detailstringnullable
instancestringnullable

Request example

curl -X POST "https://api.ampr.dev/v1/cdrs/cdr_example/payment-reference" \
  -H "Authorization: Bearer $AMPR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_reference": "pi_3QabcXYZ",
    "payment_provider": "stripe"
  }'
Note
This endpoint requires an API key. Send it as a Bearer token in the Authorization header.

GET /cdrs/{cdr_id}/billing-decision Get the authoritative billing-decision audit record for a CDR

Regulator/auditor surface: an immutable, frame-traceable record of why this CDR billed the way it did. Returns the CURRENT decision for this CDR plus the full decision chain for its session (newest-first), so a correction (a superseding decision) is visible as history rather than silently replacing the original. Purely a read over immutable `billing_decisions` rows — deterministic, same input always returns the same output.

Parameters

Name In Type Required Description
cdr_id path string required

Responses

200 Billing-decision audit record

PropertyTypeRequiredDescription
dataobjectrequired
PropertyTypeRequiredDescription
cdr_idstringrequired
session_idstringrequired
decisionBillingDecision | nullrequiredThe current decision for this CDR, or `null` if none was recorded.
  • PropertyTypeRequiredDescription
    outcomeenum
    • billed
    • recovered_partial
    • unbillable
    required`billed` = normal complete-data billing. `recovered_partial` = billed from a recovered/last-known meter reading after missing data. `unbillable` = insufficient evidence to bill; CDR kept as a data record only.
    reason_codestringrequiredMachine-readable reason, e.g. `missing_stop_recovered`.
    explanationstringrequiredHuman-readable explanation of the billing outcome.
    evidenceobjectrequiredStructured evidence supporting the decision (meter register snapshot, missing frame types, source message references), including a `frameRef` tying the decision back to the originating OCPP transaction/message for audit traceability.
  • null
chainarray<BillingDecisionChainEntry>requiredEvery decision recorded for this CDR's session, newest-first — the original plus any corrections.
PropertyTypeRequiredDescription
outcomeenum
  • billed
  • recovered_partial
  • unbillable
required`billed` = normal complete-data billing. `recovered_partial` = billed from a recovered/last-known meter reading after missing data. `unbillable` = insufficient evidence to bill; CDR kept as a data record only.
reason_codestringrequiredMachine-readable reason, e.g. `missing_stop_recovered`.
explanationstringrequiredHuman-readable explanation of the billing outcome.
evidenceobjectrequiredStructured evidence supporting the decision (meter register snapshot, missing frame types, source message references), including a `frameRef` tying the decision back to the originating OCPP transaction/message for audit traceability.
supersedesstringnullablerequiredThe id of the billing_decision row this one supersedes (a correction). `null` for the original decision.
created_atstringformat: date-timerequired

401 Missing or invalid API key application/problem+json

PropertyTypeRequiredDescription
typestringformat: urirequired
titlestringrequired
statusintegerrequired
detailstringnullable
instancestringnullable

404 Resource not found application/problem+json

PropertyTypeRequiredDescription
typestringformat: urirequired
titlestringrequired
statusintegerrequired
detailstringnullable
instancestringnullable

Request example

curl -X GET "https://api.ampr.dev/v1/cdrs/cdr_example/billing-decision" \
  -H "Authorization: Bearer $AMPR_API_KEY"
Note
This endpoint requires an API key. Send it as a Bearer token in the Authorization header.