Skip to main content
Skip table of contents

API Guide for Billing Integration

Overview

This document provides an overview of the billing integration process between the Cloudmore platform and ERP or financial systems.

Billing integration is the most common use case on Cloudmore and is generally straightforward, often requiring only a single API call to retrieve the necessary data.

While billing is generated monthly, the exact dates vary by service.

For example, Microsoft NCE data is available between the 6th and 8th of each month, while legacy Microsoft services follow different, partner-specific schedules.

For most organizations, retrieving billing data once or twice a month is sufficient.

The document outlines the available Cloudmore API endpoints for exporting billing data and refers to the Cloudmore Swagger documentation for complete technical details.

Available API Calls

API Endpoint

Data Returned

Note

…/billing/reports/MonthlyBillingPerOrganizationAsync

All services

Recommended API Call

…/billing/reports/MonthlyBillingPerOrganization
and
…/billing/reports/MonthlyBillingPerService

NOTE! Not for Production!

All Services

This API should only be used for testing. This API returns the same data as the asynchronous call, but has a limit on the amount of data that can be returned.

…/billing/azurereports/AzureOneTimeInvoice/

Microsoft Data

  • 365 NCE

  • Azure NCE

  • Perpetual Licences

  • Software Subscriptions

  • Marketplace Items

Returns detailed Microsoft information for all services under the New Commerce Experience (NCE).

This data is based on Microsoft’s “Recurring and one-time purchases” invoice.

…/billing/cspreports/MonthlyBillingPerOrganization

Microsoft O365 Legacy

Detailed report for Microsoft Legacy services. This data is based on Microsoft’s “Recurring” invoice.

…/billing/azurereports/InvoiceOverview

Microsoft Azure Legacy billing data

Detailed report for Microsoft Legacy services. This data is based on Microsoft’s “Recurring” invoice.

…/billing/azureonetimeusage/AzureOneTimeInvoice

Microsoft Azure Usage data

Microsoft Azure usage data report. Please note that the Microsoft usage report may slightly differ from the Microsoft Azure billing report because of rounding and transformations made by Microsoft.

Recommendation

Cloudmore strongly advises using the …/billing/reports/MonthlyBillingPerOrganizationAsync API endpoint to access billing information. This endpoint provides comprehensive billing data across all services available in Cloudmore and is designed to be future-proof. By using this API, you can avoid having to update your billing integration when expanding from Microsoft services to other offerings within Cloudmore.

This guide will walk you through how to use the …/billing/reports/MonthlyBillingPerOrganizationAsync API and help you understand the structure and content of the data it returns.

How to call the API

  1. Get Authentication Key. For detailed instructions on how to authenticate with the Cloudmore API, please refer to the <Authentication documentation>.

  2. Once you get an authentication token, you have to send a POST call to start generating the data.

    BASH
    curl -v POST https://api.cloudmore.com/api/resellers/{ResellerId}/billing/reports/MonthlyBillingPerOrganizationAsync \
    -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IkMzRERCQ...' \
    -H 'Accept: application/json' \
    -H 'Content-Type: application/json' \
    -d '{ 
      "startDate": "2023-01-01", 
      "endDate": "2023-02-01", 
    }'
  3. In the response header, look for the location property.

    HTML
    < HTTP/1.1 201 Created
    < content-length: 0
    < date: Mon, 20 Mar 2023 16:48:38 GMT
    < server: envoy
    < location: https://api.cloudmore.com/api/resellers/{ResellerId}/billing/reports/MonthlyBillingPerOrganizationAsync/2cf155ea-3a06-4765-a3e0-9178ec67263
    < request-context: appId=cid-v1:1aebea94-e93f-48c4-9742-65cff419d034
    < x-powered-by: ASP.NET
    < x-envoy-upstream-service-time: 204
  4. Then make a GET request to the location URL.

    BASH
    curl -X GET https://api.cloudmore.com/api/resellers/{ResellerId}/billing/reports/MonthlyBillingPerOrganizationAsync/2cf155ea-3a06-4765-a3e0-9178ec6b67263 \
    -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IkMzRERCQ...' \
    -H 'Accept: application/json' \
    -H 'Content-Type: application/json'
  5. If the data is not ready yet, the response will have a status of 0(zero) in the status property.

    JS
    {"status":0,"data":null}
  6. Once the report generation is done, the status will be 5(five), and the data property will be filled with the billing report data.

Response Details

The response data is structured as shown in the figure.

Billing_Response.drawio.svg

A sample response data is shown below for reference.

JS
[
  {
    "status": "5",
    "data": [
      {
        "billingDate": "2023-01-19T23:59:59",
        "billingContentStartDate": "2023-01-19T23:59:59",
        "billingContentEndDate": "2023-01-19T00:00:00",
        "organizations": [
          {
            "name": "Contoso Organization",
            "customerNumber": "12345",
            "orgId": "720b40a2-f8d1-4dbb-a115-0193215c3721",
            "organizationGroups": [
              "Large Customers"
            ],
            "services": [
              {
                "serviceName": "Microsoft 365 CSP Direct Legacy",
                "serviceId": "881ae94a-b03a-4da5-8e67-21ea8d77dfb5",
                "totalResellerPrice": "45.00",
                "totalCustomerPrice": "54.00",
                "currencyCode": "EUR",
                "customerCurrencyCode": "EUR",
                "items": [
                  {
                    "itemName": "Microsoft Defender for Office 365 (Plan 2)",
                    "subscriptionId": "9ff279d7-00f3-4277-9d03-ef10b52b8273",
                    "poNumber": "12345689",
                    "quantity": 10.0,
                    "totalResellerPrice": "45.00",
                    "totalCustomerPrice": "54.00",
                    "resellerPricePerUnit": "4.50",
                    "customerPricePerUnit": "5.40",
                    "products": [
                      {
                        "productName": "Microsoft Defender for Office 365 (Plan 2)",
                        "productId": "efe1183a-8fa0-4138-bf0a-5ae271ab6e3c",
                        "itemCode": "EFE1183A-8FA0-4138-BF0A-5AE271AB6E3C",
                        "quantity": 10.0,
                        "resellerPricePerUnit": "4.50",
                        "customerPricePerUnit": "5.40",
                        "totalResellerPrice": "45.00",
                        "totalCustomerPrice": "54.00",
                        "itemDetails": "Cycle fee. Charge for upcoming period from 1/1/2023 to 1/31/2023"
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
]

Information related to the fields

  1. Status: A post-call will initiate a report generation, which can take several minutes before the report is ready. The status property returns the status of the report generation. When the report generation is running, a status of 0 (zero) will be returned. Please wait at least 30 seconds and then call the API again. Once completed, the status property will return a status of 5 (five), and the data property will be filled with the data. For additional statuses that could be returned, please see the Swagger document.

  2. Billing Date: The billing date indicates when the billing data was generated. This date can vary across different services within Cloudmore. For example, Microsoft NCE typically generates billing between the 6th and 8th of each month, depending on when Microsoft releases its billing information. Microsoft Legacy services may have different billing dates for different partners. Additionally, other services in Cloudmore can be configured to produce billing data on specific dates.

  3. Billing Content Start & End Date: When generating a billing report, you’ll need to define a start and end date. Cloudmore will then return billing records where the billingDate falls within that specified range. The fields billingContentStartDate and billingContentEndDate in the response will reflect the exact start and end dates you provided in the POST request.

  4. Organizations: A list of all end customers included in the billing report.

  5. Name: The display name of each organization.

  6. Customer Number: A unique identifier assigned by the Broker (reseller), useful for linking to external systems.

  7. Org ID (Organization ID): A permanent, unique identifier for the organization in Cloudmore.

  8. Organization Groups: Groups the organization belongs to, which can be used for categorization (e.g., cost centers, account managers).

  9. Services: Contains all services billed to the organization, along with cost and sales summaries.

  10. Service Name: The name of the service (e.g., Microsoft 365 CSP Direct).

  11. Service ID: A permanent, unique identifier for the service in Cloudmore.

  12. Total Reseller Price: The total cost incurred by the reseller for the service.

  13. Total Customer Price: The total amount billed to the customer. The difference from totalResellerPrice represents the margin.

  14. Currency Code: The currency used by the Broker to purchase the service.

  15. Customer Currency Code: The currency used by the Organization to buy the service. Usually matches currencyCode, except for custom services.

  16. Items: A list of subscriptions under each service.

  17. Item Name: The name of the subscription.

  18. Subscription ID: A permanent, unique identifier for the subscription.

  19. PO Number: An optional purchase order number provided by the Broker.

  20. Quantity: The number of licenses or seats billed.

  21. Products: Billing lines under each subscription. Multiple lines may appear if there are changes or multiple products.

  22. Product Name: The name of the product within the subscription.

  23. Product ID: A permanent, unique identifier for the product.

  24. Item Code: Vendor-provided item code.

  25. Item Details: Additional information about the billing line.

Example Code

This is a Python example that demonstrates how to retrieve an access token and fetch billing report data. Please note that this sample lacks error handling and is not suitable for use in a production environment.

PY
import requests
import json
import base64
import time
# Define constants
RESELLER_ID = '11111111-2222-3333-4444-555555555555' # Replace with you Broker ID
CLIENT_ID = 'ro.customer.client'
API_SECRET = 'MySecret' # Replace with your API Secret
USERNAME = 'username@broker.com' # Replace with your username
PASSWORD = 'MyPassword' # Replace with your password
START_DATE = '2023-01-01' # Replace with the start date you want
END_DATE = '2023-01-31' # Replace with the end date you want
SAVE_TO_FILE = f'BillingReport_{START_DATE}_{END_DATE}_json.txt'
# Base64 encode the API secret
client_decoded = f'{CLIENT_ID}:{API_SECRET}'
b64_secret = base64.b64encode(client_decoded.encode()).decode()
# Get Access Token
token_url = 'https://api.cloudmore.com/connect/token'
token_headers = {'Authorization': f'Basic {b64_secret}'}
token_data = {
    'client_id': 'ro.customer.client',
    'grant_type': 'password',
    'username': USERNAME,
    'password': PASSWORD,
    'scope': 'api'
}
token_response = requests.post(token_url, headers=token_headers, data=token_data)
token = token_response.json().get("access_token")
print('Access Token received:', token)
# Start generating Billing Report
billing_url = f'https://api.cloudmore.com/api/resellers/{RESELLER_ID}/billing/reports/MonthlyBillingPerOrganizationAsync'
billing_headers = {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'Authorization': f'Bearer {token}'
}
billing_data = json.dumps({'startDate': START_DATE, 'endDate': END_DATE})
billing_response = requests.post(billing_url, headers=billing_headers, data=billing_data)
location = billing_response.headers['location']
print('Billing Report generation started')
print('Endpoint to retrieve billing report:', location)
# Get billing report (try until status 5)
def get_billing_report():
    while True:
        response = requests.get(location, headers=billing_headers)
        report_status = response.json()['status']
        if report_status != 5:
            print('Billing Report not ready... waiting 5 seconds.')
            time.sleep(5)
        else:
            print('Billing Report Done!')
            return response
billing_response = get_billing_report()
# Write JSON to file
with open(SAVE_TO_FILE, 'w') as file:
    json.dump(billing_response.json(), file)
JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.