Updated: 2026-10-05. Applies to the eEKAS Ceph S3 implementation. The existing product API usage disclaimer also applies.
Use the configured HTTPS API listener, normally https://<server>:18443, and send X-API-Key on every request. Login credentials for the web GUI are not API keys. The listener must be enabled separately; the test listener was temporary. Validate the appliance certificate in production (--cacert <CA_FILE> where needed). Examples use placeholders, not appliance credentials.
Customer metadata and billing options below use URL query parameters. Percent-encode values with --data-urlencode. Supply a unique Idempotency-Key on retryable mutations; repeat the same request and key to replay its original response. Provisioning replays include the same secret-key response, so protect API responses. Do not place credentials in URLs. X-Correlation-ID is optional and is returned for tracing.
The s3-admin and admin roles can perform these mutations. A read-only key can read reports and tracking status but cannot provision, edit, collect or activate tracking. Product guards restrict these object-storage endpoints to applicable products.
| Method | Path | Result |
|---|---|---|
| GET | /api/v1/object-storage/customers |
Customer list; optional paired billing dates |
| POST | /api/v1/object-storage/customers |
Provision customer, user, bucket and quota; 201 |
| PATCH | /api/v1/object-storage/customers |
Change metadata, quota and billing settings |
| DELETE | /api/v1/object-storage/customers |
Remove registration; optional destructive purge |
| POST | /api/v1/object-storage/customers/usage |
Storage snapshots plus traffic collection |
| GET | /api/v1/object-storage/traffic |
Tracking state for all sites or one site |
| POST | /api/v1/object-storage/traffic |
Queue activation for required site; 202 |
| POST | /api/v1/object-storage/traffic/collect |
Traffic collection for all sites or one site |
| GET | /api/v1/object-storage/billing |
Per-customer JSON report |
| GET | /api/v1/object-storage/billing/export |
Same report with CSV text and filename |
| GET | /api/v1/object-storage/billing/users |
UID/site summary with CSV text and filename |
All billing dates use YYYY-MM-DD. Report endpoints require both period_start and period_end; the customer list accepts neither or both. Dates are inclusive in UTC and start must not exceed end. Reports and per-customer exports accept customer_id and uid; UID summary accepts uid.
Creation requires customer_id, customer_name and a positive integer quota_gb. Optional fields are customer_number, email, site, bucket, service_type (s3 or s3_nextcloud), currency, price_per_gb, minimum_charge, billing_status, charge_uploads, charge_downloads, upload_price_per_gb and download_price_per_gb. Site defaults to the backend default site; bucket defaults to the generated customer bucket. Currency defaults to EUR and storage prices to zero. Traffic flags accept lowercase true or false and prices must be nonnegative. On Ceph, upload charging defaults off, download charging defaults on, and both traffic prices default to zero. Enabling tracking and configuring a price are separate operations.
curl --cacert <CA_FILE> -X POST -G \
-H 'X-API-Key: <API_KEY>' -H 'Idempotency-Key: <REQUEST_ID>' \
--data-urlencode 'customer_id=example-001' \
--data-urlencode 'customer_name=Example Customer' \
--data-urlencode 'quota_gb=100' --data-urlencode 'site=<SITE>' \
--data-urlencode 'price_per_gb=0.20' --data-urlencode 'minimum_charge=5' \
--data-urlencode 'charge_uploads=false' --data-urlencode 'charge_downloads=true' \
--data-urlencode 'download_price_per_gb=0.05' \
'https://<server>:18443/api/v1/object-storage/customers'
Creation returns status, customer and credentials containing access_key and secret_key. Store the secret securely; customer lists do not return it. Use the separately configured S3 endpoint to transfer objects, not the management API port.
PATCH requires customer_id and accepts the creation billing/metadata fields except site and bucket. Omitted fields stay unchanged. Set a price to 0 or a flag to false explicitly to disable charging. Quota edits update the actual Ceph bucket quota; validate it through GET /api/v1/object-storage/quotas?quota_scope=bucket&bucket=<BUCKET> and inspect data.bucket_quota.enabled and max_size (bytes).
Billing statuses are active, suspended, trial, cancelled, and do_not_bill. Active and suspended are billable; the other three produce zero charges. These labels do not revoke S3 access. Changing current prices or billing status recalculates historical reports. Preserve approved billing exports.
DELETE requires customer_id. Without purge_data=true it removes registration; a purge also deletes customer S3 data and its user. Purging is destructive. Recreating an ID creates a new generation and does not inherit its previous storage peak.
curl --cacert <CA_FILE> -X POST -G \
-H 'X-API-Key: <API_KEY>' -H 'Idempotency-Key: <REQUEST_ID>' \
--data-urlencode 'site=<SITE>' \
'https://<server>:18443/api/v1/object-storage/traffic'
curl --cacert <CA_FILE> -G -H 'X-API-Key: <API_KEY>' \
--data-urlencode 'site=<SITE>' \
'https://<server>:18443/api/v1/object-storage/traffic'
Activation returns HTTP 202 with status=ok, phase=queued and a message. It configures RGW usage logging and may restart gateway services. Poll GET until the selected site is active; inspect failure messages rather than assuming that 202 means activation is complete. Repeating activation on an active site preserves its original accounting boundary.
GET returns status and sites. Each site contains site, phase (disabled, enabling, active, or error), start, last_collected, message and warnings. The two time fields are Unix epoch seconds; zero indicates no recorded boundary/collection. Warnings may be null or an array.
Tracking and newly registered customer traffic accounting begin at the next full UTC hour. Earlier traffic is not billed. The collector counts RGW request and response bytes, including supported failed operations; it does not measure NIC totals, replication or physical storage overhead. The latest hours are provisional while RGW logs flush. Initial historical backfill is bounded per collection and can require repeated runs.
POST /api/v1/object-storage/traffic/collect accepts optional site and returns status=ok on success. It uses the existing distributed lease and hourly ledger, so retries do not double-count bytes. A concurrent operation may temporarily fail to acquire the lease; retry later. The five-minute collector timer captures traffic only. Disabling tracking or clearing protected usage logs is intentionally unsupported, including through the API.
POST /api/v1/object-storage/customers/usage captures storage and also collects traffic. Its response includes count, error_count, collected, errors and traffic_error. HTTP 200 can include partial failures: check these fields. Schedule this endpoint at the storage sampling cadence you require. Writes and deletions between snapshots can be missed by sampled peak billing; the traffic timer does not supply storage snapshots.
curl --cacert <CA_FILE> -X POST \
-H 'X-API-Key: <API_KEY>' -H 'Idempotency-Key: <REQUEST_ID>' \
'https://<server>:18443/api/v1/object-storage/customers/usage'
curl --cacert <CA_FILE> -G -H 'X-API-Key: <API_KEY>' \
--data-urlencode 'period_start=2026-10-01' \
--data-urlencode 'period_end=2026-10-31' \
--data-urlencode 'customer_id=example-001' \
'https://<server>:18443/api/v1/object-storage/billing/export'
GB means 1,073,741,824 bytes. For a billable customer:
storage_amount = max(sampled_peak_GB * price_per_gb, minimum_charge)
amount = storage_amount + upload_amount + download_amount
Each monetary component rounds to three decimals. Upload/download amounts use measured traffic and their prices when their charging flags are enabled. The minimum charge applies to storage only. A range spanning several months uses one peak and one minimum; it is not the sum of separate monthly invoices. Current quota and current stored bytes are separate from the selected period peak.
Billing JSON contains status, billing_mode, period_start, period_end, total, total_amount and rows. Rows include customer metadata and pricing, peak_used_gb, billable_gb, latest_object_count, storage_amount, uploaded_gb, downloaded_gb, upload_amount, download_amount, amount, currency, traffic_coverage, traffic_warning, traffic_start_at and traffic_collected_at. The legacy actual_used_gb report field also represents the period peak; current sampled use is latest_used_gb on the customer list. Do not sum different currencies into an invoice without grouping them first.
Customer lists contain status, provider, s3_ready, total and customers; with billing dates the amount and billable storage refer to that range, while latest_used_gb remains the latest snapshot.
Inspect traffic_coverage and traffic_warning before approving charges. Coverage can be partial when activation starts inside the period, incomplete while logs/history are pending, stale when collection is overdue, or unavailable. Null traffic counters mean unavailable, not zero. traffic_start_at and traffic_collected_at are ISO UTC timestamps when available.
Exports remain JSON: /billing/export adds csv and filename to the per-customer report. /billing/users returns summary, csv and filename, grouping by UID and site with aggregate storage/traffic quantities and component amounts. Parse the JSON and write its csv string to a file; the HTTP body is not a raw CSV download.
The regenerated SDK includes traffic management, CSV export, period-aware customer lists and the four traffic pricing parameters. Python booleans are serialized as lowercase query values.
from euronas_api import EuroNasApi
api = EuroNasApi("https://<server>:18443", "<API_KEY>", ca_file="<CA_FILE>")
api.patch_api_v1_object_storage_customers(
customer_id="example-001", charge_uploads=False,
charge_downloads=True, download_price_per_gb=0.05)
report = api.get_api_v1_object_storage_billing_export(
period_start="2026-10-01", period_end="2026-10-31")
with open(report["filename"], "w", encoding="utf-8", newline="") as output:
output.write(report["csv"])
Invalid dates, unknown sites, invalid billing statuses, negative prices, invalid booleans and nonpositive quotas return HTTP 400. Missing/invalid keys return 401; denied mutations return 403; unsupported methods return 405. Backend failures may return 500. A queued activation can fail later; poll state and inspect its message. Use correlation IDs for diagnostics.
The October 2026 implementation was checked against the live HTTPS API on test appliance 192.168.178.21 with isolated temporary keys/listener. Tests cover authentication and read-only restrictions, tracking status and activation retry, collection, customer provisioning and purge, S3 transfer, storage snapshots, actual Ceph quota edits, traffic-price changes, all five billing statuses, period validation, JSON/CSV totals, idempotent provisioning and generated SDK behavior. Initial activation from disabled and cross-midnight/month accounting remain covered by existing collector/backend controlled tests; the live API activation test uses an already active site. A newly created customer before its next-hour boundary cannot demonstrate billable traffic yet; existing measured customer traffic was checked in report totals.
See the separate Customers and Billing administrator guide and white paper in /home/admin/manuals/customers_billing for illustrated GUI workflows.