Using Python with the CSP API to automate customer onboarding

You are probably a Microsoft CSP partner if you are reading this, so you most likely already know that it stands for Cloud Solutions Provider. And you probably know too that you can interact with it over the Partner Center GUI, or through the Partner Center APIs.

Have you automated the deployment of customers, their Azure subscriptions and Azure services? If not, you might find this article useful.

Now there are a already a bunch of Partner Center SDKs out there: C#, Java, and even PowerShell. I am more the Python sort of person, so I decided to start up a Python module for interacting with the CSP Partner Center. Here you have the link to my Github repository. Have a look at the documentation in the repository, since it explains the process to create the customer, add a subscription to it, and enable that subscription for app-based ARM login.

This module is far for being complete, but it rather tries to demonstrate how to use the partner center APIs. It includes a command-line shell with which you can try out things. One of the interesting things of this shell is that you can use the –verbose option for any command, which will show you exactly the REST API call and its corresponding response. For example, to create a new subscription:

sandbox> add subscription -v
VERBOSE - *************** REST API CALL - BEGIN ***************
VERBOSE - HEADERS: {"Content-Type": "application/json", "Accept": "application/json", "Authorization": "Bearer <removed>"}
VERBOSE - PAYLOAD "{\"LineItems\": [{\"Friendly Name\": \"New offer\", \"PartnerIdOnRecord\": null, \"OfferId\": \"MS-AZR-0146P\", \"Attributes\": {\"ObjectType\": \"OrderLineItem\"}, \"LineItemNumber\": 0, \"SubscriptionId\": null, \"Quantity\": 1}], \"ReferenceCustomerId\": \"0b99aff9-6c7e-4d66-b3c7-d438bb80a0d2\", \"BillingCycle\": \"unknown\", \"Attributes\": {\"ObjectType\": \"Order\"}, \"CreationDate\": null, \"Id\": null}"
VERBOSE - ANSWER: {"id":"45c4298d-852d-4c51-bda3-13c24148057d","referenceCustomerId":"0b99aff9-6c7e-4d66-b3c7-d438bb80a0d2","billingCycle":"monthly","lineItems":[{"lineItemNumber":0,"offerId":"MS-AZR-0146P","subscriptionId":"E433773A-ED07-4FCD-B7A2-5453D64704EC","friendlyName":"Microsoft Azure","quantity":1,"links":{"subscription":{"uri":"/customers/0b99aff9-6c7e-4d66-b3c7-d438bb80a0d2/subscriptions/E433773A-ED07-4FCD-B7A2-5453D64704EC","method":"GET","headers":[]}}}],"creationDate":"2017-06-25T13:27:27.33-07:00","links":{"self":{"uri":"/customers/0b99aff9-6c7e-4d66-b3c7-d438bb80a0d2/orders/45c4298d-852d-4c51-bda3-13c24148057d","method":"GET","headers":[]}},"attributes":{"etag":"eyJpZCI6IjQ1YzQyOThkLTg1MmQtNGM1MS1iZGEzLTEzYzI0MTQ4MDU3ZCIsInZlcnNpb24iOjF9","objectType":"Order"}}
VERBOSE - *************** REST API CALL - END ***************

One application of using the Partner Center API is offering a self-service portal to potential customers, so that you can provision automatically the customer, an Azure subscription, and resources in that subscription.

As I wrote here, you would need to run a couple of PowerShell commands on the newly created subscriptions in order to allow app-based ARM authentication. In order to automate that process, I created an Azure Function that can be called with a POST request, some data in the body, and the Azure Function will then create the service principal and a new role assignment in the newly created subscription.

If you want to know how this Azure function works, you can use again the –verbose option of the command-line app:

sandbox> add role -v
Please enter password for user
VERBOSE - *************** REST API CALL - BEGIN ***************
VERBOSE - DATA: {"subscription": "CCB8BB34-AD6F-43FE-9017-4B9720A66D40", "password": "removed", "user": "", "appId": "6fba93c9-7ea3-4cf2-9a56-ef806a702dcb", "tenantId": "edae5676-508e-4380-bd6d-fa16fd1d0c8b"}
Calling REST API...
VERBOSE - RESPONSE {"servicePrincipal":"New service principal successfully created, OID d7a1b9b3-308a-4208-8509-1b210bbfe68a","roleAssignment":"Role Contributor successfully assigned to service principal"}
VERBOSE - *************** REST API CALL - END ***************
New service principal successfully created, OID d7a1b9b3-308a-4208-8509-1b210bbfe68a
Role Contributor successfully assigned to service principal

I haven’t been able to figure out how to do the above (enabling app-based ARM login in a customer subscription) via native REST API Graph, PartnerCenter or ARM calls, if you have a hint about how to do this I would be very grateful.

Whenever I get time, I will try to put this in a nice Web App, of course hosted in Azure.

Thanks for reading down to here!

Update: my esteemed colleague Paulo Ramos made me aware of an alternative way of  getting a valid ARM token for the newly created customer subscription. Essentially, it involves using app+user authentication for the ARM API, providing as application ID a special GUID (1950a258-227b-4e31-a9cf-717495945fc2) that corresponds to Powershell, which is preconsented for every ARM subscription. You would send a POST request to the URL{{CustomerId}}/oauth2/token with this body:



10 thoughts on “Using Python with the CSP API to automate customer onboarding

  1. John Lavallee

    Great Article for Microsoft’s Direct CSP’s to automate the on-boarding and set up of indirect (T2) partners. Thanks!


    1. Thanks John! That is not only to onboard T2 partners though, but to onboard customers too


  2. […] Update: if you want to use this PowerShell code as an Azure Function, as well as automate the creation of the customer subscription, you might want to read this post. […]


  3. Hello dear Jose,

    Thank you very much for the nice article and useful script! Looking forward to use it with our Azure CSP subscription.

    Could you, please, clarify the following: then trying to run almost any command within “csp” shell script provides, I always get this exception:

    Quote begins
    csp> show variables
    EXCEPTION of type ‘AttributeError’ occurred with message: ”list’ object has no attribute ‘split”
    To enable full traceback, run the following command: ‘set debug true’
    Quote ends

    A lot of thanks in advance!

    Kind regards,
    Alexander Fershtein


    1. Hey Alexander,

      Thanks for using the script! You are probably using Python 3.x, I tested my script with 2.7. I dont know when I am going to have time to thoroughly test the code for Python 3.x, in the meantime is there any chance you can run this on a machine with Python 2.7?



      1. Hey Jose,

        Thank you for your kind answer!
        Will try running your script with python 2.7.x, and will update you with results.

        Warmest regards,


      2. Hi dear Jose,

        I’ve tried running your great script with Python 2.7.5 in CentOS 7, and with Python 2.7.3 in Debian 7 – the same behavior, – “EXCEPTION of type ‘AttributeError’ occurred with message: ”list’ object has no attribute ‘split””.
        Seems like that the command -line argument being passed are interpreted as a list, and not a string.

        Could you, please, advise?

        Thanks a lot.

        Best regards,


  4. Hey Alex,

    you are actually so right. I just did a new commit to the Github repo, could you change whether it works now?



  5. eduardomourar

    Jose, you might be interested on this (not MS official) python SDK for Partner Center (


    1. Thanks Eduardo! Indeed, this looks nice, I wish I had had this two years ago 🙂 Thanks for sharing!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: