Getting Started

Requirements

For you to start using the AppNotch API for multi-tenant, you need few things setup before even going through this document, first you need to contact AppNotch to be able to publish a live (public/private) Multi-Tenant App, once the app is live and ready to be used by the API, AppNotch will then give you four properties that you will need in order for you to start calling the API endpoints.

  1. App Id - Master App Id
  2. Subject - API subject
  3. Security Key - API Security Key
  4. Identity Id - For creating/updating Tenant Members

API Workflow diagram

For you to start using the AppNotch API for multi-tenant, this flow diagram will help you to easily understand the multi-tenant feature and its implementation.

  1. JWT Nuget Package - Allows us to generate a valid JWT from our code.
  2. Json.NET - Easily converts our object into json strings.


Authorization - POSTv2/Auth

For you to start calling the AppNotch API endpoints, you need to generate your own JWT and include your generated token on your call to the API endpoints. you can take a look at our C# implementation of our API to understand how we generate the JWT Token dynamically here in GitHub

var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.appnotch.com/v2/auth"); httpWebRequest.ContentType = "application/json"; httpWebRequest.Method = "POST"; using (var writer = new StreamWriter(httpWebRequest.GetRequestStream())) { #region Json Obj string jsonPost = JsonConvert.SerializeObject(new { subject = "<Subject>", key = "<APIKEY>"}); #endregion JsonObj writer.Write(jsonPost); } string result = ""; var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse(); using (var reader = new StreamReader(httpResponse.GetResponseStream())) result = reader.ReadToEnd(); return result;
public string GetToken() { DateTime UNIX_EPOC = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); DateTime utcVal; DateTime dt = DateTime.UtcNow; if (dt.Kind == DateTimeKind.Utc) { utcVal = dt; } else { utcVal = dt.ToUniversalTime(); } var diff = utcVal - UNIX_EPOC; var unixTimestamp = Convert.ToInt64(diff.TotalSeconds); // setup payload var payload = new { iss = "appnotch.com", sub = "SUBJECT", iat = unixTimestamp, jti = Guid.NewGuid().ToString("N") }; IJwtAlgorithm algorithm = new HMACSHA256Algorithm(); IJsonSerializer serializer = new JsonNetSerializer(); IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder(); IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder); // convert the secret to base64 string and use as key var base64Secret = Convert.FromBase64String("SECURITY KEY"); var token = encoder.Encode(payload, base64Secret); return token; }
$curl = curl_init(); $params = ["Subject" => "<Subject>", "Key" => "<APIKEY>"]; //parameters to be passed curl_setopt_array($curl, array( CURLOPT_URL => "https://api.appnotch.com/v2/auth", //url to which request has to be sent CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode($params), CURLOPT_HTTPHEADER => array( "Cache-Control: no-cache", "Content-Type: application/json", ), )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; }
$.ajax({ type: 'POST', url: "https://apiqa.appnotch.com/v2/auth", data: '{ "Subject" : "<Subject>", "Key" : "<Key>" }', dataType: 'application/json', beforeSend: function(xhr){ xhr.setRequestHeader('Content-Type', 'application/json'); }, 'success': function (response) { token=response; }

CREATE Tenant - POST v2/apps/{appId}/tenants

This call will allow the users to create their tenant using the API, to get more information about this endpoint click here to see the documentation.

var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.appnotch.com/v2/apps/{AppId}/tenants"); httpWebRequest.ContentType = "application/json"; httpWebRequest.Method = "POST"; httpWebRequest.Headers.Add("Authorization", "Bearer " + GetToken()); using (var writer = new StreamWriter(httpWebRequest.GetRequestStream())) { #region Json Obj string jsonPost = JsonConvert.SerializeObject(new { appId = <MASTER APP ID>, displayName = "Bob's Plumbing", iconUrl = "http://imagehosting.com/AGOEN32SDSAE392DSAJ", splashUrl = "http://imagehosting.com/AOEUHGDEG832KGd", url = "http://bobdoesplumbing.com/", disabled = false, hidden = false, displayOrder = 4, description = "some description", firstName = "First Name", lastName = "Last Name", phone = "222-111-4444", supportEmail = "sample@test.com", supportSite = "http://mysupportsite.com", tag = "My Custom Tag", socialDescription = "My Social Description usually set by the master app", rollOverId = 0, footer = new { footerType = 1, footerData = new[] { new { title = "Home", url = "http://myhomepage.com", image = "glyphicon glyphicon-home", fColor = "000000", bColor = "ffffff", sTabColor = "ffffff", type = "Home" }, new { title = "Phone", url = "tel:314-433-3222", image = "fa fa-phone-square", fColor = "000000", bColor = "ffffff", sTabColor = "ffffff", type = "phone" }, new { title = "Push Log", url = "native:pushlog", image = "fa fa-comments-o", fColor = "000000", bColor = "ffffff", sTabColor = "ffffff", type = "message" } } } }); #endregion JsonObj writer.Write(jsonPost); } string result = ""; var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse(); using (var reader = new StreamReader(httpResponse.GetResponseStream())) result = reader.ReadToEnd(); return result;
$curl = curl_init(); $params = [ "appId" => <MASTER_APP_ID>, "displayName" => "Bob's Plumbing", "iconUrl" => "http://imagehosting.com/AGOEN32SDSAE392DSAJ", "splashUrl" => "http://imagehosting.com/AOEUHGDEG832KGd", "url" => "http://bobdoesplumbing5.com/", "disabled" => false, "hidden" => false, "displayOrder" => 4, "description" => null, "firstName" => "first name", "lastName" => "last name", "phone" => null, "supportEmail" => null, "supportSite" => null, "footer" => null, "tag" => "My Custom Tag", "socialDescription" => null, "rollOverId" => 0, "landingPage" => null, "facebookUrl" => null, "twitterUrl" => null, "linkedInUrl" => null, "googlePlusUrl" => null, "ionicTemplateId" => null, "source" => "Dashboard", "category" => null ]; //parameters to be passed curl_setopt_array($curl, array( CURLOPT_URL => "https://api.appnotch.com/v2/apps/<MASTER_APP_ID>/tenants", //url to which request has to be sent CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode($params), CURLOPT_HTTPHEADER => array( "Cache-Control: no-cache", "Content-Type: application/json", "Authorization: Bearer <TOKEN>"), )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; }
var postData={ appId : , displayName : "Bob's Plumbing", iconUrl : "http://imagehosting.com/AGOEN32SDSAE392DSAJ", splashUrl : "http://imagehosting.com/AOEUHGDEG832KGd", url : "http://bobdoesplumbing.com/", disabled : false, hidden : false, displayOrder : 4, description : "some description", firstName : "First Name", lastName : "Last Name", phone : "222-111-4444", supportEmail : "sample@test.com", supportSite : "http://mysupportsite.com", tag : "My Custom Tag", socialDescription : "My Social Description usually set by the master app", rollOverId : 0, footer : { footerType : 1, footerData : [{ title : "Home", url : "http://myhomepage.com", image : "glyphicon glyphicon-home", fColor : "000000", bColor : "ffffff", sTabColor : "ffffff", type : "Home" }, { title : "Phone", url : "tel:314-433-3222", image : "fa fa-phone-square", fColor : "000000", bColor : "ffffff", sTabColor : "ffffff", type : "phone" }, { title : "Push Log", url : "native:pushlog", image : "fa fa-comments-o", fColor : "000000", bColor : "ffffff", sTabColor : "ffffff", type : "message" }] } } $.ajax({ type: 'POST', url: "https://apiqa.appnotch.com/v2/apps/{{appid}}", data: postData, dataType: 'application/json', beforeSend: function(xhr){ xhr.setRequestHeader('Content-Type', 'application/json'); xhr.setRequestHeader('Authorization', 'Bearer '+token); }, 'success': function (response) { console.log(response); } });

{            
    "appId": <MASTER APP ID>,
    "displayName": "Bob's Plumbing",
    "iconUrl": "http://imagehosting.com/AGOEN32SDSAE392DSAJ",
    "splashUrl": "http://imagehosting.com/AOEUHGDEG832KGd",
    "url": "http://bobdoesplumbing.com/",
    "disabled": false,
    "hidden": false,
    "displayOrder": 4,
    "description": null,
    "firstName": "First Name",
    "lastName": "Last Name",
    "phone": "222-111-4444",
    "supportEmail": "sample@test.com",
    "supportSite": "http:mysupportsite.com",
    "footer": {},
    "tag": "My Custom Tag",
    "socialDescription": "My Social Description usually set by the master app",
    "rollOverId": 0
}
                        
{                
    "id": <TENANT ID>,
    "appId": <MASTER APP ID>,
    "firstName": "First Name",
    "lastName": "Last Name",
    "phone": "222-111-4444",
    "supportEmail": "sample@test.com",
    "supportSite": "http:mysupportsite.com",
    "footer": {},
    "tag": "My Custom Tag",
    "socialDescription": "My Social Description usually set by the master app",
    "displayName": "Bob's Plumbing",
    "iconUrl": "http://imagehosting.com/AGOEN32SDSAE392DSAJ",
    "splashUrl": "http://imagehosting.com/AOEUHGDEG832KGd",
    "url": "http://bobdoesplumbing.com",
    "disabled": false,
    "hidden": false,
    "displayOrder": 4,
    "createDate": "2017-04-29T15:11:24.8336543Z",
    "footerUrl": "http://app.appnotch.com/converter/footer/tenant/412",
    "shareContent": "https://a2bc.app.link/ag7GFe26dE",
    "branchUrl": "https://a2bc.app.link/ag7GFe26dE",
    "description": "Some description regarding the tenant app"
}
                        

Error Codes :

Code Desciption
400 Bad Request :
  • If any of the required properties is not set
  • If tenant request's AppId did not match the endpoint's AppId
  • If the app that you are trying to use is not a Multi-tenant App
  • If the url you use to create the tenant is not an absolute url
403 Forbidden :
You do not have access to call this endpoint, contact AppNotch to check the configuration of your api credentials.
404 Not Found :
The App that you are trying to create this Tenant does not exists.
409 Conflict :
Another tenant exists with the same url under the Master App.


CREATE Tenant Member - POST v2/tenantmember

This call will create a new Tenant Member (Admin for the Tenant), so that they can login to Tenant Dashboad and be able to modify their app themselves, or send in push notifications.

NOTE : Tenant Members are global scoped, This means that if the email is already been used by a member of the other Multi-Tenant, thant email will be flagged as used.

var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.appnotch.com/v2/tenantmember"); httpWebRequest.ContentType = "application/json"; httpWebRequest.Method = "POST"; httpWebRequest.Headers.Add("Authorization", "Bearer " + GetToken()); using (var writer = new StreamWriter(httpWebRequest.GetRequestStream())) { #region Json Obj string jsonPost = JsonConvert.SerializeObject(new { email = "email address", password = "password", createdBy = <IDENTITY ID>, name = "sample string 4", phoneNumber = "sample string 5" }); #endregion JsonObj writer.Write(jsonPost); } string result = ""; var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse(); using (var reader = new StreamReader(httpResponse.GetResponseStream())) result = reader.ReadToEnd(); return result;
$curl = curl_init(); $params = [ "email" => "email address", "password" => "password", "createdBy" => <IDENTITY ID>, "name" => "sample string 4", "phoneNumber" = "sample string 5" ]; //parameters to be passed curl_setopt_array($curl, array( CURLOPT_URL => "https://api.appnotch.com/v2/tenantmember", //url to which request has to be sent CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode($params), CURLOPT_HTTPHEADER => array( "Cache-Control: no-cache", "Content-Type: application/json", "Authorization: Bearer <TOKEN>" ), )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response;
var postData={ email : "email address", password : "password", createdBy : <IDENTITY ID>, name : "sample string 4", phoneNumber : "sample string 5" }; $.ajax({ type: 'POST', url: "https://api.appnotch.com/v2/tenantmember", data: postData, dataType: 'application/json', beforeSend: function(xhr){ xhr.setRequestHeader('Content-Type', 'application/json'); xhr.setRequestHeader('Authorization', 'Bearer '+token); }, 'success': function (response) { console.log(response); } });

{
    "email": "sample@email.com",
    "password": "myPassword",
    "createdBy": <IDENTITY ID>,
    "name": "My Name",
    "phoneNumber": "222-111-5555"
}
                        
{                        
    "id": 1,
    "email": "sample@email.com", 
    "createdBy": <IDENTITY ID>,
    "name": "My Name",
    "phoneNumber": "222-111-5555"
}
                        

Error Codes :

Code Desciption
400 Bad Request :
  • If any of the required properties is not set
  • If email address is invalid
  • If password provided is empty
  • If the url you use to create the tenant is not an absolute url
403 Forbidden :
You do not have access to call this endpoint, contact AppNotch to check the configuration of your api credentials.
409 Conflict :
Member with the given email address already exists


Tenant to Tenant Member Association - POST v2/tenantmember/{id}/associate/{tenantId}

This call will associate a Tenant Member to a Tenant. when the association is completed, the tenant app will then be listed in his/her Tenant Dashboard.

NOTE : One Tenant Member can be associated to multiple Tenants.

var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.appnotch.com/v2/tenantmember/{id}/associate/{tenantId}"); httpWebRequest.ContentType = "application/json"; httpWebRequest.Method = "POST"; httpWebRequest.Headers.Add("Authorization", "Bearer " + GetToken()); httpWebRequest.ContentLength = 0; string result = ""; var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse(); using (var reader = new StreamReader(httpResponse.GetResponseStream())) result = reader.ReadToEnd(); return result;
$curl = curl_init(); $params = [ ]; //parameters to be passed curl_setopt_array($curl, array( CURLOPT_URL => "https://api.appnotch.com/v2/tenantmember/<MEMBER_ID>/associate/<TENANT_ID>", //url to which request has to be sent CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode($params), CURLOPT_HTTPHEADER => array( "Cache-Control: no-cache", "Content-Type: application/json", "Authorization: Bearer <TOKEN>" ), )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; }
$.ajax({ type: 'POST', url: "https://api.appnotch.com/v2/tenantmember/{id}/associate/{tenantId}", data: {}, dataType: 'application/json', beforeSend: function(xhr){ xhr.setRequestHeader('Content-Type', 'application/json'); xhr.setRequestHeader('Authorization', 'Bearer '+token); }, 'success': function (response) { console.log(response); } });

{                        
    "id": 1,
    "email": "sample@email.com", 
    "createdBy": <IDENTITY ID>,
    "name": "My Name",
    "phoneNumber": "222-111-5555"
}
                    

Error Codes :

Code Desciption
404 Not Found :
  • If Tenant Member Id is not in the database
  • If Tenant Id is not in the database
403 Forbidden :
You do not have access to call this endpoint, contact AppNotch to check the configuration of your api credentials.
409 Conflict :
Member has already access to this tenant.



Push Notification

Other end-points that you might be interested in using, This allows api users to Get/Send push notification to an existing Tenant.


Get Push Notification - GET v2/apps/{appId}/tenants/{tenantId}/push

This call will get all the push notification specific to tenant.

var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://api.appnotch.com/v2/apps/{appId}/tenants/{tenantId}/push"); httpWebRequest.ContentType = "application/json"; httpWebRequest.Method = "GET"; httpWebRequest.Headers.Add("Authorization", "Bearer " + GetToken()); httpWebRequest.ContentLength = 0; string result = ""; var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse(); using (var reader = new StreamReader(httpResponse.GetResponseStream())) result = reader.ReadToEnd(); return result;
$curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://api.appnotch.com/v2/apps/{appId}/tenants/{tenantId}/push", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => array( "Cache-Control: no-cache", "Content-Type: application/json", "Authorization: Bearer <TOKEN>" ), )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; }
$.ajax({ type: 'GET', url: "https://api.appnotch.com/v2/apps/{appId}/tenants/{tenantId}/push", data: {}, dataType: 'application/json', beforeSend: function(xhr){ xhr.setRequestHeader('Authorization', 'Bearer '+token); }, 'success': function (response) { console.log(response); } });

[
    {
        "id": 34,
        "title": "Welcome to our app",
        "url": "",
        "message": "Use the Coupon Code APP2016 to get $10 off you purchase.",
        "dateSent": "2017-04-26T18:19:58.7502416Z",
        "isGeo": false,
        "previewerOnly": true,
        "isExternalLink": false,
        "mediaImage": null
    },
    {
        "id": 42,
        "title": "Save a Ton with This Coupon!",
        "url": "http://www.appnotch.com/CouponCodeGenerator",
        "message": "Use the Coupon Code ABC123 For a 20% Discount this week only!",
        "dateSent": "2017-05-04T18:19:58.7507424Z",
        "isGeo": false,
        "previewerOnly": false,
        "isExternalLink": false,
        "mediaImage": null
    },
    {
        "id": 45,
        "title": "We have a new location near you!",
        "url": "http://www.mystore.com/stlouislocation/",
        "message": "St Louisians, There is a new Store Located in Soulard",
        "dateSent": "2017-05-06T18:19:58.7507424Z",
        "isGeo": true,
        "previewerOnly": false,
        "isExternalLink": false,
        "mediaImage": null
    }
]
                        

Error Codes :

Code Desciption
403 Forbidden :
You do not have access to call this endpoint, contact AppNotch to check the configuration of your api credentials.
404 Not Found :
  • The App that you are trying to send the push does not exists.
  • The Tenant App that you are trying to send the push does not exists.


Send Push Notification - POST v2/apps/{appId}/tenants/{tenantId}/push

This call will send a push notification directly to the tenant and will be recieved by the end-users who installs the app.

var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.appnotch.com/v2/apps/{appId}/tenants/{tenantId}/push"); httpWebRequest.ContentType = "application/json"; httpWebRequest.Method = "POST"; httpWebRequest.Headers.Add("Authorization", "Bearer " + GetToken()); using (var writer = new StreamWriter(httpWebRequest.GetRequestStream())) { #region Json Obj string jsonPost = JsonConvert.SerializeObject(new { title = "Testing The Previewer", message = "This is a Test push to Make sure this is working...", url = "", previewerOnly = true, isExternalLink = false }); #endregion JsonObj writer.Write(jsonPost); } string result = ""; var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse(); using (var reader = new StreamReader(httpResponse.GetResponseStream())) result = reader.ReadToEnd(); return result;
$curl = curl_init(); $params = [ "title" => "Testing The Previewer", "message" => "This is a Test push to Make sure this is working...", "url" => "", "previewerOnly" => true, "isExternalLink" => false ]; //parameters to be passed curl_setopt_array($curl, array( CURLOPT_URL => "https://api.appnotch.com/v2/apps/{appId}/tenants/{tenantId}/push", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode($params), CURLOPT_HTTPHEADER => array( "Cache-Control: no-cache", "Content-Type: application/json", "Authorization: Bearer <TOKEN>" ), )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; }
var postData={ title : "Testing The Previewer", message : "This is a Test push to Make sure this is working...", url : "", previewerOnly : true, isExternalLink : false }; $.ajax({ type: 'POST', url: "https://api.appnotch.com/v2/apps/{appId}/tenants/{tenantId}/push", data: postData, dataType: 'application/json', beforeSend: function(xhr){ xhr.setRequestHeader('Content-Type', 'application/json'); xhr.setRequestHeader('Authorization', 'Bearer '+token); }, 'success': function (response) { console.log(response); } });

{
    "title": "Testing The Previewer",
    "message": "This is a Test push to Make sure this is working...",
    "url": "",
    "previewerOnly": true,
    "isExternalLink": false
}
                        
{
    "id": 34,
    "title": "Welcome to our app",
    "url": "",
    "message": "Use the Coupon Code APP2016 to get $10 off you purchase.",
    "dateSent": "2017-04-26T18:06:13.8778073Z",
    "isGeo": false,
    "previewerOnly": true,
    "isExternalLink": false,
    "mediaImage": null
}
                        

Error Codes :

Code Desciption
400 Bad Request :
If any of the required properties is not set
403 Forbidden :
You do not have access to call this endpoint, contact AppNotch to check the configuration of your api credentials.
404 Not Found :
  • The App that you are trying to send the push does not exists.
  • The Tenant App that you are trying to send the push does not exists.