Maestrano currently provides four SDKs to facilitate the integration of Single Sign-On, Billing and Data Sharing. Current SDKs are: Java, PHP, Ruby and .NET.
If no SDKs are available in the language you currently use, then it may be necessary to revert to a SDK-free integration using our REST APIs directly. This guide explains how to proceed in such case.
1 - Metadata Endpoint REQUIRED
1.1 How does it work?
In order to understand your application and configure webhooks properly, Maestrano expects you to create a special "metadata" endpoint exposing the configuration of your application preferences in terms of Single Sign-On, data sharing subscriptions, webhooks etc.
Why a metadata endpoint?
Once setup, enter the URL of your metadata endpoint into your Maestrano App Provider dashboard then click on 'refresh metadata'.
1.2 What to include in the metadata endpoint?
The metadata endpoint should return a JSON document describing your configuration. Note that the call initiated by Maestrano to retrieve your metadata is authenticated via HTTP Basic authentication using your own API credentials (shared secret).
Below is a commented example of metadata document:
{ # ===> App Configuration # # => environment # The environment of your application. Common values are: # - "production", for your integration on a platform in a Production environment or UAT environment # - "production-sandbox", for the sandbox you use for your tests during the integration on maestrano.com # - "test", for the SSO test on the Sandbox "environment": "test", # => host (required) # This is your application host. For UAT and Production environments, it must be a publicly resolvable URL, you cannot use "http://localhost:3000" for instance. "app": { "host": "http://my-app.com" }, # "api": { # => id (required) # The id of your app. # For maestrano.com integration, it corresponds to the App ID of your Maestrano App Provider API Dashboard. # For other platform, we will send it to you with your API key. "id": "app-19op", # => host (required) # It corresponds to the platform host. # It changes with the tenant and the environment. We will provide you the correct host for the platform you are being connected to. "host": "http://api-sandbox.maestrano.io" }, # ===> SSO Configuration # "sso": { # => idm # By default we consider that the domain managing user identification is the same as your application host (see above config.app.host parameter). # If you have a dedicated domain managing user identification and therefore responsible for the single sign-on handshake (e.g: https://idp.my-app.com) then you can specify it below "idm": "https://idp.myapp.com", # => init_path (required) # This is the path in your application that allows users to initiate the Single Sign-On handshake. # Upon reaching this endpoint users your application will automatically create a SSO request and redirect the user to Maestrano. Maestrano will then authenticate and authorize the user. "init_path": "/maestrano/auth/saml/init.php", # This value can be changed on a per-tenant basis: # "init_path": "/maestrano/auth/saml/init.php?tenant=mytenant" # => consume_path (required) # This is your application path to the SAML endpoint that allows users to finalize SSO authentication. # During the 'consume' action your application sets users (and associated group) up and/or log them in. "consume_path": "/maestrano/auth/saml/consume.php", # This value can be changed on a per-tenant basis: # "consume_path": "/maestrano/auth/saml/consume.php?tenant=mytenant" # => idp (required) # It corresponds to the platform host. # It changes with the tenant and the environment. We will provide you the correct host for the platform you are being connected to. "idp": "https://maestrano.com", # => x509_fingerprint and x509_certificate # It changes with the tenant and the environment. We will provide you the correct host for the platform you are being connected to. "x509_fingerprint": "8a:1e:2e:76:c4:67:80:68:6c:81:18:f7:d3:29:5d:77:f8:79:54:2f" "x509_certificate": "-----BEGIN CERTIFICATE-----MIIDezCCAuSgAwIBAgIJAMzy+weDPp7qMA0GCSqGSIb3DQEBBQUAMIGGMQswCQYDVQQGEwJBVTEMMAoGA1UECBMDTlNXMQ8wDQYDVQQHEwZTeWRuZXkxGjAYBgNVBAoTEU1hZXN0cmFubyBQdHkgTHRkMRYwFAYDVQQDEw1tYWVzdHJhbm8uY29tMSQwIgYJKoZIhvcNAQkBFhVzdXBwb3J0QG1hZXN0cmFuby5jb20wHhcNMTQwMTA0MDUyMzE0WhcNMzMxMjMwMDUyMzE0WjCBhjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA05TVzEPMA0GA1UEBxMGU3lkbmV5MRowGAYDVQQKExFNYWVzdHJhbm8gUHR5IEx0ZDEWMBQGA1UEAxMNbWFlc3RyYW5vLmNvbTEkMCIGCSqGSIb3DQEJARYVc3VwcG9ydEBtYWVzdHJhbm8uY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+2uyQeAOc/irohCyT33RkkWfTGeJ8E/mu9F5ORWoCZ/h2J+QDuzuc69Rf1LoO4wZVQ8LBeWOqMBYzotYFUIPlPfIBXDNL/stHkpg28WLDpoJM+46WpTAgp89YKgwdAoYODHiUOcO/uXOO2i9Ekoa+kxbvBzDJf7uuR/io6GERXwIDAQABo4HuMIHrMB0GA1UdDgQWBBTGRDBTie5+fHkB0+SZ5g3WY/D2RTCBuwYDVR0jBIGzMIGwgBTGRDBTie5+fHkB0+SZ5g3WY/D2RaGBjKSBiTCBhjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA05TVzEPMA0GA1UEBxMGU3lkbmV5MRowGAYDVQQKExFNYWVzdHJhbm8gUHR5IEx0ZDEWMBQGA1UEAxMNbWFlc3RyYW5vLmNvbTEkMCIGCSqGSIb3DQEJARYVc3VwcG9ydEBtYWVzdHJhbm8uY29tggkAzPL7B4M+nuowDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAwRxg3rZrML//xbsS3FFXguzXiiNQAvA4KrMWhGh3jVrtzAlN1/okFNy6zuN8gzdKDYw2n0c/u3cSpUutIVZOkwQuPCMC1hoP7Ilat6icVewNcHayLBxKgRxpBhr5Sc4av3HOW5Bi/eyC7IjeBTbTnpziApEC7uUsBou2rlKmTGw==-----END CERTIFICATE-----" }, # ===> Data Sharing # This section describes how to configure the Account and Connec!™ webhooks # => connec.host (required) # It corresponds to the endpoint used to fetch data from. # It changes with the tenant and the environment. We will provide you the correct host for the platform you are being connected to. "connec": { "host": "https://api-connec.maestrano.com" } "webhook": { # # Maestrano will issue a DELETE request to the following paths to notify you # of any service cancellation (group deletion) or any user being removed from a group. # => groups_path (required) # => group_users_path (required) "account": { "groups_path": "/maestrano/account/groups/:id", "group_users_path": "/maestrano/account/groups/:group_id/users/:id" }, # ==> Connec Subscriptions/Webhook # The following section is used to configure the Connec!™ webhooks and which entities # you should receive via webhook. # # "connec": { # => notifications_path (required) # This is the path of your application where notifications (created/updated entities) will # be POSTed to. # You should have a controller matching this path handling the update of your internal entities # based on the Connec!™ entities you receive # "notifications_path": "/maestrano/connec/notifications", # => subscriptions (required) # This is the list of entities (organizations, people, invoices etc.) for which you want to be # notified upon creation/update in Connec!™ # "subscriptions": { "accounts": true, "company": true, "events": false, "event_orders": false, "invoices": true, "items": true, "journals": false, "organizations": true, "payments": false, "pay_items": false, "pay_schedules": false, "pay_stubs": false, "pay_runs": false, "people": true, "projects": false, "tax_codes": true, "tax_rates": false, "time_activities": false, "time_sheets": false, "venues": false, "work_locations": false } } } }
1.3 What are the required fields in my metadata?
Required fields in your metadata, depending on the SSO protocol you have chosen:
Field | Type | Required for OpenID SSO | Required for SAML SSO | Change with the tenant and the environment | Description |
---|---|---|---|---|---|
environment | string | - | - | Yes (with the env. only) | The environment of the platform your are integrated to; accepted values: |
app.host | string | Yes | Yes | Yes (with the env. only) | Your application host |
api.id | string | Yes | Yes | Yes | The id of your app |
api.host | string | Yes | Yes | Yes | The platform host |
sso.idm | string | - | - | - | Your Identity Domain Manager |
sso.init_path | string | - | Yes | your choice | Your application path that allows users to initiate |
sso.consume_path | string | - | Yes | your choice | Your application path to the SAML endpoint that allows |
sso.idp | string | Yes | Yes | Yes | The platform host |
sso.x509_fingerprint | string | - | Yes | Yes | |
sso.x509_certificate | string | - | Yes | Yes | |
connec.host | string | Yes | Yes | Yes | The Connec! endpoint used to fetch data from |
webhook.account.group_path | string | Yes | Yes | your choice | Your application path where a notification will be posted |
webhook.account.group_users_path | string | Yes | Yes | your choice | Your application path where a notification will be posted |
webhook.connec.notifications_path | string | Yes | Yes | your choice | Your application path where notifications |
wenhook.connec.subscriptions | hash | Yes | Yes | No | The list of entities (organizations, people, invoices etc.) |
2 - Single Sign-On REQUIRED
Maestrano provides two different Single Sign-On protocols: SAML 2.0 and OpenID. OpenID has become fairly more popular than SAML and is also more supported by the community. Chances are you will find a library handling OpenID out-of-the-box for your language of choice. A few examples:
- Node.js - http://passportjs.org/
- Go - https://github.com/yohcop/openid-go
- Scala/Play - https://www.playframework.com/documentation/2.0/ScalaOpenID
- Perl - http://search.cpan.org/~wrog/Net-OpenID-Consumer-1.16/lib/Net/OpenID/Consumer.pm
Our OpenID guide will give you all the details on the best way to integrate our OpenID provider into your application, just check it out here.
3 - Account Management API & Webhooks
Our account management API is a REST API allowing you to perform:
- Membership Management: get details about your Maestrano customers (memberships) and get notified of service cancellation actions via webhooks.
- Group/Organization
- User
- Groups Webhook
- Group Users Webhook - Mandatory
- Billing Management: create/retrieve/cancel bills or recurring bills for your Maestrano customers.
- Bill (Adhoc)
- RecurringBill
3.1 - Membership Management
Dev Sandbox endpoint: http://api-sandbox.maestrano.io/api/v1/account/
Production endpoint: https://maestrano.com/api/v1/account/
Groups (company/organization) API
> Retrieve your list of customers (= list of companies having selected your application on Maestrano)
# Request curl -u <my-app-id>:<my-app-secret> \ -H "Accept: application/json" \ https://maestrano.com/api/v1/account/groups # Response { "success":true, "errors":{}, "data":[ { "object":"account_group", "id":"cld-4", "created_at":"2014-05-21T04:04:53Z", "updated_at":"2014-05-21T04:04:53Z", "has_credit_card":true, "status":"running", "name":"Logistics Department - Sales", "free_trial_end_at":"2014-06-21T04:04:53Z", "email":"cld-4@example.com", "currency":"USD", "timezone":"America/Los_Angeles", "country":"US", "city":"Los Angeles" } ] }
> Retrieve a specific customer
# Request curl -u <my-app-id>:<my-app-secret> \ -H "Accept: application/json" \ https://maestrano.com/api/v1/account/groups/cld-4 # Response { "success":true, "errors":{}, "data": { "object":"account_group", "id":"cld-4", "created_at":"2014-05-21T04:04:53Z", "updated_at":"2014-05-21T04:04:53Z", "has_credit_card":true, "status":"running", "name":"Logistics Department - Sales", "free_trial_end_at":"2014-06-21T04:04:53Z", "email":"cld-4@example.com", "currency":"USD", "timezone":"America/Los_Angeles", "country":"US", "city":"Los Angeles" } }
Users API
> Retrieve the list of users with access to your application
# Request curl -u <my-app-id>:<my-app-secret> \ -H "Accept: application/json" \ https://maestrano.com/api/v1/account/users # Response { "success":true, "errors":{}, "data":[ { "object":"account_user", "id":"usr-2", "name":"John", "surname":"Doe", "email":"john.doe@gmail.com", "country":"AU", "sso_session":"d7kp1b5esnfgtz6xhiv9qwlja34yu8crm2o0", "created_at":"2014-05-21T00:37:34Z", "updated_at":"2015-03-09T06:37:28Z" } ] }
> Retrieve a specific user
# Request curl -u <my-app-id>:<my-app-secret> \ -H "Accept: application/json" \ https://maestrano.com/api/v1/account/users/usr-2 # Response { "success":true, "errors":{}, "data": { "object":"account_user", "id":"usr-2", "name":"John", "surname":"Doe", "email":"john.doe@gmail.com", "country":"AU", "sso_session":"d7kp1b5esnfgtz6xhiv9qwlja34yu8crm2o0", "created_at":"2014-05-21T00:37:34Z", "updated_at":"2015-03-09T06:37:28Z" } }
Groups Webhook - getting notified a of Group cancelling their subscription to your service REQUIRED
When a business decides to stop using your service Maestrano will issue a DELETE request to the webhook.account.groups_path endpoint on your side (e.g.: /webhooks/maestrano/groups/:id - see the metadata section above). The call is authenticated via HTTP Basic authentication using your own API credentials (shared secret).
The call is equivalent to issuing to the following cURL request on your service:
curl -u <my-app-id>:<my-app-secret> \ -X "DELETE" \ -H "Accept: application/json" \ https://my-cloud-application.com/webhooks/maestrano/groups/cld-4
Group > Users Webhook - getting notified a of user leaving a group REQUIRED
When a user is removed from a group, access should be disabled for that specific user. In such case Maestrano will issue a DELETE request to the webhook.account.group_users_path endpoint on your side (e.g.: /webhooks/maestrano/groups/:group_id/users/:id - see the metadata section above). The call is authenticated via HTTP Basic authentication using your own API credentials (shared secret).
The call is equivalent to issuing to the following cURL request on your service:
curl -u <my-app-id>:<my-app-secret> \ -X "DELETE" \ -H "Accept: application/json" \ https://my-cloud-application.com/webhooks/maestrano/groups/cld-4/users/usr-2
3.2 - Billing Management REQUIRED
Maestrano centralizes all billing functionalities. The goal is to provide to customers a single invoice at the end of the month summarising the expenses related to all the applications and services they have used during the month.
Our billing API allows you to report charges to be incurred to your Maestrano customers. Two types of bills are currently available:
- Bill: one-off charge to be incurred - e.g.: one-off purchase a specific module, template, service within your application
- RecurringBill: recurring charge - e.g.: weekly/monthly/annual user subscription
Bill - Adhoc charge
The command below shows how to create a $20 adhoc bill.
# Request curl -u <my-app-id>:<my-app-secret> \ -X "POST" \ -H 'Accept: application/json' \ -H "Content-type: application/json" \ -d '{"group_id":"cld-4", "price_cents":2000, "description":"Product purchase"}' \ https://maestrano.com/api/v1/account/bills # Response { "success":true, "errors":{}, "data":{ "object":"account_bill", "id":"bill-520", "group_id":"cld-4", "created_at":"2015-06-03T05:00:33Z", "updated_at":"2015-06-03T05:00:33Z", "price_cents":2000, "status":"submitted", "currency":"AUD", "units":null, "description":"Product purchase", "period_started_at":null, "period_ended_at":null } }
This command allows you to cancel a submitted bill. Only submitted bills can be cancelled - "invoiced" bills are not cancellable.
# Request curl -u <my-app-id>:<my-app-secret> \ -X "DELETE" \ -H 'Accept: application/json' \ https://maestrano.com/api/v1/account/bills/bill-520 # Response { "success":true, "errors":{}, "data":{ "object":"account_bill", "id":"bill-520", "group_id":"cld-4", "created_at":"2015-06-03T05:00:33Z", "updated_at":"2015-06-03T05:00:33Z", "price_cents":2000, "status":"cancelled", "currency":"AUD", "units":null, "description":"Product purchase", "period_started_at":null, "period_ended_at":null } }
Below is how to retrieve all your bills as well as a single bill:
# Retrieve all your bills curl -u <my-app-id>:<my-app-secret> \ -H 'Accept: application/json' \ https://maestrano.com/api/v1/account/bills # Retrieve a specific bill curl -u <my-app-id>:<my-app-secret> \ -H 'Accept: application/json' \ https://maestrano.com/api/v1/account/bills/bill-520
The table below summarises all the fields available on the Bill model:
Field | Mode | Type | Required | Default | Description |
---|---|---|---|---|---|
id | readonly | string | - | - | The id of the bill |
group_id | read/write | string | Yes | - | The id of the group you are charging |
price_cents | read/write | Integer | Yes | - | The amount in cents to charge to the customer |
description | read/write | String | Yes | - | A description of the product billed as it should appear on customer invoice |
created_at | readonly | Time | - | - | When the bill was created. Uses ISO 8601 format (e.g.: 2015-06-03T05:00:33Z) |
updated_at | readonly | Time | - | - | When the bill was last updated. Uses ISO 8601 format (e.g.: 2015-06-03T05:00:33Z) |
status | readonly | String | - | - | Status of the bill. Either 'submitted', 'invoiced' or 'cancelled'. |
currency | read/write | String | - | AUD | The currency of the amount charged in ISO 4217 format (3 letter code) |
units | read/write | Decimal(10,2) | - | 1.0 | How many units are billed for the amount charged |
period_started_at | read/write | Time | - | - | If the bill relates to a specific period then specifies when the period started. Both period_started_at and period_ended_at need to be filled in order to appear on customer invoice. Uses ISO 8601 format (e.g.: 2015-06-03T05:00:33Z) |
period_ended_at | read/write | Time | - | - | If the bill relates to a specific period then specifies when the period ended. Both period_started_at and period_ended_at need to be filled in order to appear on customer invoice. Uses ISO 8601 format (e.g.: 2015-06-03T05:00:33Z) |
RecurringBill - Recurring subscription fees
The command below shows how to create a $29.90 recurring bill for a user license.
# Request curl -u <my-app-id>:<my-app-secret> \ -X "POST" \ -H 'Accept: application/json' \ -H "Content-type: application/json" \ -d '{"group_id":"cld-4", "price_cents":2990, "description":"User license", "period": "Month", "start_date": "2015-08-27T23:22:37Z" }' \ https://maestrano.com/api/v1/account/recurring_bills # Response { "success":true, "errors":{}, "data":{ "object":"account_recurring_bill", "id":"rbill-523", "group_id":"cld-4", "created_at":"2015-06-03T05:02:19Z", "updated_at":"2015-06-03T05:02:19Z", "price_cents":2990, "status":"submitted", "currency":"AUD", "description":"User license", "start_date":"2015-08-27T23:22:37Z", "period":"month", "frequency":1, "cycles":null, "initial_cents":0, "last_execution_at":null, "next_execution_at":"2015-08-27T23:22:37Z", "remaining_cycles":null } }
This command allows you to cancel a recurring bill:
# Request curl -u <my-app-id>:<my-app-secret> \ -X "DELETE" \ -H 'Accept: application/json' \ https://maestrano.com/api/v1/account/recurring_bills/rbill-523 # Response { "success":true, "errors":{}, "data":{ "object":"account_recurring_bill", "id":"rbill-523", "group_id":"cld-4", "created_at":"2015-06-03T05:02:19Z", "updated_at":"2015-06-03T05:02:19Z", "price_cents":2990, "status":"cancelled", "currency":"AUD", "description":"User license", "start_date":"2015-08-27T23:22:37Z", "period":"month", "frequency":1, "cycles":null, "initial_cents":0, "last_execution_at":null, "next_execution_at":"2015-08-27T23:22:37Z", "remaining_cycles":null } }
Below is how to retrieve all your recurring bills as well as a single recurring bill:
# Retrieve all your recurring bills curl -u <my-app-id>:<my-app-secret> \ -H 'Accept: application/json' \ https://maestrano.com/api/v1/account/recurring_bills # Retrieve a specific recurring bill curl -u <my-app-id>:<my-app-secret> \ -H 'Accept: application/json' \ https://maestrano.com/api/v1/account/recurring_bills/rbill-523
The table below summarises all the fields available on the RecurringBill model:
Field | Mode | Type | Required | Default | Description |
---|---|---|---|---|---|
id | readonly | string | - | - | The id of the recurring bill |
group_id | read/write | string | Yes | - | The id of the group you are charging |
price_cents | read/write | Integer | Yes | - | The amount in cents to charge to the customer |
description | read/write | String | Yes | - | A description of the product billed as it should appear on customer invoice |
period | read/write | String | - | Month | The unit of measure for the billing cycle. Must be one of the following: 'Day', 'Week', 'SemiMonth', 'Month', 'Year' |
frequency | read/write | Integer | - | 1 | The number of billing periods that make up one billing cycle. The combination of billing frequency and billing period must be less than or equal to one year. If the billing period is SemiMonth, the billing frequency must be 1. |
cycles | read/write | Integer | - | nil | The number of cycles this bill should be active for. In other words it's the number of times this recurring bill should charge the customer. |
start_date | read/write | Time | - | Now | The date when this recurring bill should start billing the customer. Uses ISO 8601 format (e.g.: 2015-06-03T05:00:33Z) |
created_at | readonly | Time | - | - | When the recurring bill was created. Uses ISO 8601 format (e.g.: 2015-06-03T05:00:33Z) |
updated_at | readonly | Time | - | - | When the recurring bill was last updated. Uses ISO 8601 format (e.g.: 2015-06-03T05:00:33Z) |
currency | read/write | String | - | AUD | The currency of the amount charged in ISO 4217 format (3 letter code) |
status | readonly | String | - | - | Status of the recurring bill. Either 'submitted', 'active', 'expired' or 'cancelled'. |
initial_cents | read/write | Integer | - | 0 | Initial non-recurring payment amount - in cents - due immediately upon creating the recurring bill |
4. Connec!™ Data Sharing REQUIRED
The Connec!™ Data Sharing REST API documentation can be found at the following URL: http://maestrano.github.io/connec/
More high level resources can also be found on this wiki, under the Connec!™ API V2 section: Connec!™ API V2 documentation
groups_path