Cyan Web API Help Page (API Version: 1)


Cyan API Version 1 Overview:

The Cyan Web API is an HTTP-based REST API for accessing resources in Cyan Server.

The API attempts to follow REST conventions wherever possible. You should expect to get back meaningful HTTP response status codes and messages on every HTTP call.


Response Status Codes

In general, the Cyan Web API will return the following status codes:

You may get other response status codes, but the ones below are the most likely response codes for most requests.

  • 200 - OK - request was successful
  • 201 - Created - a request to create a resource (e.g. POST) was successful.
  • 202 - Accepted - a request was successfully accepted by the server for processing, but the final result is not yet known (async processing
  • 204 - No Content - a request was successful, but there is no content to return.
  • 400 - Bad Request - a request was rejected due to invalid or missing information on the request.
  • 401 - Unauthorized - a request was rejected because the user's authentication or authorization failed, or the user does not have permission to complete the request.
  • 403 - Forbidden - a request was rejected because the user does not have permission to complete the request.
  • 404 - Not Found - a request was rejected because a requested resource was not found.
  • 500 - Internal Server Error - a request failed due to an error in the Cyan Server.

User Authentication

The Cyan Web API uses HTTP Basic authenication, along with a set of custom HTTP headers to handle authentication and authorization.

Every request to the Cyan Web API should contain the following headers:

  1. Authorization: Basic {base64(username:password)}

    username:password is a plain-text username/password for a valid Cyan user account.

    {base64(...)} specifies that the username:password be base-64 encoded for inclusion in the header.

  2. X-Api-Version: {cyanApiVersion}

    {cyanApiVersion} should be set to a valid Cyan Web API version (e.g. 1, 2, etc.)

    The only real API version supported at this time is version 1.

  3. X-Cyan-TenantAccessKey: {myCyanTenantAccessKey}

    {myCyanTenantAccessKey} should be set to a valid Cyan Tenant Access Key

  4. X-Cyan-Signature: {myCyanSignature}

    X-Cyan-Signature is not yet supported, and is not required on requests.


User Authorization (Resource Permissions)

Some Cyan Web API resources are protected by role-based permissions. If you are getting a HTTP 401 response for a request, it could be that your authentication credentials are bad, or it could also mean that your API user does not have permissions to access the resource.


Content Negotiation (Request/Response Content-Types)

The Cyan Web API generally supports the following request/response Content-Types:

JSON: application/json or text/json

XML: application/xml or text/xml

All HTTP requests should specify an Accept header to tell the server what the desired response format is.

Accept: application/json

Any HTTP request that contains content in the request body should always specify the Content-Length and Content-Type headers at a minimum. Failure to specify these headers may result in unexpected errors.

Content-Type: application/json
Content-Length: 12345

JSON is the preferred format for all requests, please use JSON if possible.

Certain services may support other mime types, see API documentation for details.

In the future, it is likely that a custom SQLite mime type (e.g. application/x-sqlite3) may be supported for certain resources.

Accept: application/x-sqlite3


Compression/Encoding

The Cyan Web API current supports GZIP-encoding of responses. To request that the HTTP responses are encoded using GZIP, include the following header in your HTTP requests:

Accept-Encoding: gzip

Compression is only supported on responses, do not send compressed/GZIP-encoded content in your HTTP request.


Hypermedia

Most Cyan API responses will contain a section in the response called Links. These links provide your application with references to other resources of interest that are related to the resource in the response. The links can be explored using the conventional GET/POST/PUT/DELETE HTTP methods.


Common Use Cases

Client Engine - Register a new Device

To register a device, the engine should show a form that requires the user to specify a Cyan Tenant Access Key, a Cyan Username, and a Cyan password. Once validated, the Tenant Access Key, Username, Password, along with a few other fields should be persisted locally on the device for later use.

  1. Validate the existence of the Cyan user using: GET api/users/?userName={myCyanUserName} This call will verify that the credentials are valid, and return back information about the specified User/UserGroup/Tenant/etc..
  2. From the User response, the engine should persist the following fields for later use: UserId, UserGroupId, TenantId
  3. Register (create) a new Device resource using: POST api/devices
  4. From the create Device response, the engine should persist the following fields for later use: DeviceId, DeviceGroupId

Client Engine - Get the list of available applications for a Tenant.

Once the user is validated and the device is registered, the next step in the on-boarding process is to get the list of applications available for the specified tenant. The Engine UI should allow the user to choose which application to continue with, or just automatically pick an application to use.

  1. Get the TenantApplications using: GET api/tenantApplications The "TenantApplication" shows licensing information about the application and tenant.
  2. Once you know which applications are available to the tenant, you can get the associated Application resources using Get api/applications/{applicationId}
  3. If a single app is available, the engine can assume this is the one to use, otherwise, show a UI to the user to allow the user to choose which application they want.
  4. From the get Application response, the engine should persist the following fields for later user: ApplicationId

Client Engine - Get the list of ApplicationVersions for an Application.

Once the engine or user has chosen an Application, the engine must get the list of ApplicationVersions available for that Application. The client web application package download URL is associated with the ApplicationVersion.

  1. Query the ApplicationVersions using: GET api/applicationVersions?applicationId={myApplicationId}
  2. The engine should determine the most recent version (based on version # or created date), and prompt the user if they will need to upgrade from a previously-installed version.
  3. The new application package can be downloaded using the URL specified by this field on the ApplicationVersion: PackageUrl
  4. From the ApplicationVersion, the engine should persist the folliwng fields for later use: ApplicationVersionId, PackageUrl

Client Engine - Take a Device license for an application.

In order to use an application, the device must first get a license for it. The Tenant may or may not have any licenses available for the chosen application.

  1. Create a new DeviceApplication (license) record using: POST api/deviceApplications?deviceId={myDeviceId}&applicationId={myApplicationId} In the body of the POST, specify IsLicensed = true
  2. If the call succeeds, the device has successfully taken a license for the application in this tenant.

Client Engine - Download an ApplicationVersion package.

  1. Use the "PackageUrl" on the ApplicationVersion resource as the URI from which to download the application package.

Client Application - Authenticate a User via Cyan Server

The client login is done through the messaging Web API. The reason for this is because some applications will simply authenticate against the Cyan membership store, but other applications may require that the login request be (synchronously) forwarded to an external system's authentication mechanism. The messaging API takes advantage of a request router, which allows for this conditional routing of login requests from the client.

  1. To submit a login request, submit a message via: POST api/messages
  2. The message's MessageTypeId should be set to the MessageTypeId corresponding to the "Login" MessageType
  3. To get the MessageTypeId to use for the POST, use GET api/messageTypes
  4. The message's Body should be set to a serialized instance of the "Login" message body. To see an example of the Login message body, use GET api/messageBodies/Login
  5. The other message header fields should be populated from information that was previously stored by the client engine during the registration process (e.g. UserId, UserGroupId, DeviceId, ApplciationId, etc. These fields are used by the server to route the login request to the right destination.

Client Application - Download an application dataset from Cyan Server (re-init or incremental sync)

A client-initiated synchronization (i.e. data download) is performed in a series of steps.

  1. The first step is to create a SyncToken resource on the server, using POST api/syncTokens
  2. Once the SyncToken is obtained, use the SyncTokenId to initiate a data request via GET api/sync?syncTokenId={mySyncTokenId}&pageSize={myPageSize}&pageNumber={myPageNumber}
  3. pageSize and pageNumber should be set to the number of records you want to receive per page, and the page number, starting from 1 as the first page.
  4. The data set may span multiple pages, and in each paged response body, the links section of the response includes a link to use to access the next page of data: (rel: next). The client can continually issue GET requests to the "next" link in each response, until a page is reached which contains 0 records, indicated by a recordCount of 0 in the response.

Client Application - Submit a Transaction to Cyan Server

Client-initiated transactions are submitted to the server through the messaging API

  1. To submit a transaction, use: POST api/messages The MessageTypeId should be set to the MessageTypeId corresponding to the "Transaction" MessageType. MessageTypes can be viewed using GET api/messageTypes
  2. Transactions are typically processed asynchronously, so you should not expect to get back the final status of the message immediately upon submission. The client will need to check back later to re-retrieve the audit trail for the message, until the client is satisfied with the resolution of the message.
  3. The message header can be retrieved from the server using: GET api/messages/{myMessageId}
  4. The audit trail for the message can be retrieved using: GET api/messageAudits?messageId={myMessageId}

Client Application - Check the status of a Transaction in Cyan Server

Transactions are submitted via the messaging API, and status is tracked using the MessageAudit resource.

  1. To check the status of a message, issue a: GET api/messageAudits?messageId={myMessageId}
  2. There may be one or more MessageAudit resources returned, so it's best to sort by the CreatedDateUtc value on the MessageAudit to determine the ordering of the audit trail.

System Integration - Upload data into Cyan Server

Data can be uploaded in several different ways into the Cyan system:

  1. "Integration Direct-to-Datastore"
    • In this scenario, the integration worker can pull or receive data from an external system, transform it into the Cyan data storage format (Nodes/NodeRoutes/NodeIndices), and save the data directly to the Cyan database.
    • This integration scenario provides the integration worker with the most flexibility and control over how the data is submitted to Cyan.
    • This downside of this scenario is that the integration worker must implement the logic to manage error handling and re-tries itself, whereas the other scenarios may provide some of the these mechanims as part of the Cyan infrastructure.
  2. "Integration to Node/NodeIndex/NodeRoute Web API Resources"
    • In this scenario, the integration worker can pull or receive data from an external system, transform it into the Cyan storage format (Nodes/NodeRoutes/NodeIndices), and submit the data to Cyan via the Node Web API methods. POST api/nodes, POST api/nodeRoutes, POST api/nodeIndices.
    • The Node-related Web API resources are synchronous, and single-item oriented (e.g. you can only submit one item at a time).
    • This type of integration is useful if the data is received from the external system in small, incremental chunks, that can be easily submitted to Cyan via single web API calls.
    • This integration also has an ease-of-use benefit in that it's synchronous, so the integration knows immediately if the request failed, and can be retried later.
  3. "Integration to Messaging Web API Resources"
    • This scenario allows batches of data to be submitted to Cyan for distributed processing.
    • To submit a batch data set for processing, use: POST api/messages The MessageTypeId should be set to the MessageTypeId for the PutData MessageType.
    • This allows for the most efficient use of resources on the server, but has the disadvantage of being an asynchronous process, which requires additional logic in the integration to manage, compared to a synchronous method, like "Direct-to-Datastore" or "Node Web API".

System Integration - Download data from Cyan Server

  1. TBD

System Integration - Submit system command message into Cyan Server for handling

Other types of messages can be submitted into the Cyan system for processing.

  1. Use MessageType RunIntegration to submit a request for an integration run.
  2. TBD

API Documentation


Resource: AccessTokens

HTTP TemplateDescription
POST api/accessTokens

                    Creates a new access token for use in Cyan Web API request authentication/authorization.
             The POST body is empty, and there are no URL/query string args, but use a POST here because
             the server is creating something and we want to maintain good REST semantics
             (no caching for POST/idempotency/etc.)
            
             The resulting access token can be used as an alternative to HTTP Basic Authentication for
             accessing the Cyan Web API.
             
             For HTTP Basic authentication, the Web API caller normally adds a request header like this:
             
             Authorization: Basic {base64 encoded username:password}
            
             To use the Cyan access token authentication, you must first request a new token by invoking
             this API (using HTTP Basic Authentication credentials).  Once you have obtained the token, you can
             substitute the HTTP Basic Authentication header in successive requests with the following:
            
             Authorization: CyanAccessToken {base64 encoded token, provided by this API}
            
             Access tokens are set to expire after a fixed interval, and do not automatically renew or
             "slide" the expiration time with each use.  After a token has expired, the caller must
             request a new token using this API.
                    


Resource: Applications

HTTP TemplateDescription
GET api/applications?{lookupKey}

                    Gets an Application by LookupKey.
                    

GET api/applications/{applicationId}

                    Gets a single Application.
                    

GET api/applications

                    Gets all Applications.
                    

POST api/applications

                    Creates an Application.
                    


Resource: ApplicationVersions

HTTP TemplateDescription
GET api/applicationVersions?{applicationId}&{version}

                    Gets an ApplicationVersion by ApplicationId and Version
                    

GET api/applicationVersions/{applicationVersionId}

                    Gets an ApplicationVersion.
                    

GET api/applicationVersions?{applicationId}

                    Gets ApplicationVersions for a specific Application.
                    

GET api/applicationVersions

                    Gets all ApplicationVersions.
                    

POST api/applicationVersions

                    Creates an ApplicationVersion.
                    


Resource: Custom

HTTP TemplateDescription
POST api/custom/kagexport

No documentation available.


Resource: DataTypes

HTTP TemplateDescription
GET api/dataTypes/{dataTypeId}

                    Gets a DataType by DataTypeId.
                    

GET api/dataTypes?{lookupKey}

                    Gets a DataType by LookupKey
                    

GET api/dataTypes

                    Gets all DataTypes.
                    


Resource: DeviceApplications

HTTP TemplateDescription
GET api/deviceApplications?{deviceId}&{applicationId}

                    Gets a DeviceApplication.
                    

GET api/deviceApplications

                    Gets all DeviceApplications.
                    

POST api/deviceApplications

                    Creates a DeviceApplication.
                    

PUT api/deviceApplications?{deviceId}&{applicationId}

                    Updates a DeviceApplication.
                    


Resource: DeviceGroupApplicationVersions

HTTP TemplateDescription
GET api/deviceGroupApplicationVersions?{deviceGroupId}

                    Gets the DeviceGroupApplicationVersions for a specific DeviceGroup
                    

GET api/deviceGroupApplicationVersions

                    Gets all DeviceGroupApplicationVersion records
                    

POST api/deviceGroupApplicationVersions

                    Creates a device group application version.
                    

DELETE api/deviceGroupApplicationVersions?{deviceGroupId}&{applicationVersionId}

                    Deletes a device group application version
                    


Resource: DeviceGroups

HTTP TemplateDescription
GET api/deviceGroups

                    Gets all DeviceGroups.
                    

GET api/deviceGroups/{deviceGroupId}

                    Gets a DeviceGroup.
                    

POST api/deviceGroups

                    Creates a DeviceGroup
                    


Resource: Devices

HTTP TemplateDescription
GET api/devices?{manufacturerDeviceId}

                    Gets a device by the ManufacturerDeviceId.  This is an identifier which originates on the device -
            it might be a serial number, hardware identifier, MAC address, or some other type of identifier which
            is intended to uniquely identify the device.
            This field is not guaranteed to be globally unique across all devices, so this method will just return the first matching
            device resource within the request Tenant.  If the client is unable to determine a unique identifier for itself, it
            should attempt to assign itself a unique identifier using a UUID/GUID, or a combination of potentially unique fields.
                    

GET api/devices/{deviceId}

                    Gets a single device resource within a tenant.
                    

GET api/devices

                    Gets devices within a tenant.
                    

POST api/devices

                    Creates a device resource within a tenant.
             This is used primarily by the Client Engines for registering new devices within the Cyan infrastructure.
                    

POST api/devices/register

                    Creates a device resource within a tenant.
             This is used primarily by the Client Engines for registering new devices within the Cyan infrastructure.
                    


Resource: Files

HTTP TemplateDescription
GET api/files/{fileId:guid}

                    Gets a file resource by FileId.  Note that this is not the contents of the file, this is the file metadata, such as name, size, etc.
            Some properties such as BlobStorageUrl, Size, ContentType and IsShared are not populated.
            Use "api/files/{fileId:guid}/contents" to get the contents of a file.
                    

GET api/files?{name}

                    Gets a file resource by file Name.  Note that this is not the contents of the file, this is the file metadata, such as the FileId, Name and Description.
            Some properties such as BlobStorageUrl, Size, ContentType and IsShared are not populated.
            Use "api/files/{fileName}/blobContents" to get the contents of a file.
                    

GET api/files/{fileId:guid}/contents

                    Gets the contents of a File.
                    

GET api/files/{fileName}/blobContents

                    Gets the contents of a File.
                    

POST api/files

                    Creates a file.  This API method expects a multi-part form-data POST.
             
             The request should include the following headers:
            
             - Content-Type - "multipart/form-data;" with a boundary string to separate the request content parts.
             - Content-Length - set to the total number of bytes in the request.
            
             In the request body, each part (file) should be separated by the boundary string, and should include the
             following headers:
             
             - Content-Disposition: set to 'form-data; name="myfilename.ext"; filename="myfilename.ext"'
             - Content-Type: usually set to "application/octet-stream"
             
             Example:
             
             POST http://localhost:57677/api/files HTTP/1.1
             X-Api-Version: 1
             X-Cyan-TenantAccessKey: blue-dot-solutions
             Authorization: Basic {BASIC AUTH CREDENTIALS HERE}
             Accept: application/json, application/xml, text/json, text/x-json, text/javascript, text/xml
             User-Agent: RestSharp 104.1.0.0
             Host: localhost:57677
             Content-Type: multipart/form-data; boundary=-----------------------------28947758029299
             Content-Length: 15422
             Accept-Encoding: gzip, deflate
             Connection: Keep-Alive
             
             -------------------------------28947758029299
             Content-Disposition: form-data; name="test.txt"; filename="test.txt"
             Content-Type: application/octet-stream
             
             Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus libero ante, laoreet ut rutrum tempus, convallis et enim. Ut justo erat, blandit sit amet ultricies at, vulputate ut lectus. Quisque et dui eu nisi dapibus dictum sit amet vel quam. Aenean tincidunt auctor ligula ac rutrum. Donec nulla urna, porta at luctus vitae, rhoncus ultricies magna. Nunc ultricies massa nulla, fringilla bibendum nulla. Duis viverra laoreet nisl in porttitor. Aenean et adipiscing tellus. Mauris et fringilla sem. Suspendisse ut justo ipsum. In nibh mi, semper non imperdiet ut, posuere in erat. Sed hendrerit, ligula ut convallis iaculis, ante justo tempus quam, at vulputate ligula ligula sit amet enim. Mauris vestibulum malesuada molestie. Pellentesque non lorem porttitor augue ullamcorper adipiscing sit amet id augue. Donec viverra, ipsum at interdum lobortis, velit ligula ornare purus, ac ultrices ante quam ac nibh. Vestibulum pharetra, purus id adipiscing volutpat, orci dui dignissim magna, et fermentum elit tellus at ipsum.
             
             Suspendisse in turpis risus. Nunc ut sagittis metus. Maecenas auctor nibh eu dui hendrerit eget blandit sapien sollicitudin. Mauris eu libero dolor, ut facilisis est. Integer id tortor non dolor malesuada vestibulum. Quisque quis dolor id mi posuere pulvinar. Sed mollis, dui ac laoreet facilisis, lorem mi facilisis sem, quis vulputate purus lectus ut ante. Maecenas in orci eu tellus viverra feugiat sed et justo. Curabitur nunc purus, rutrum sit amet ultrices facilisis, scelerisque eu neque. Duis non ipsum vel urna scelerisque faucibus sit amet non nunc. In ut consequat urna.
             
             Nam bibendum ligula ac tellus sagittis eget tristique tortor laoreet. Nam quis nisl orci, non fringilla nunc. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque varius convallis diam congue egestas. Nullam ut turpis id ante congue iaculis vel eget nisi. Sed faucibus semper nisl, at dapibus sapien tempor vitae. Curabitur odio nunc, dapibus id aliquam ac, vulputate eu magna. Aenean consequat egestas massa, sit amet laoreet nisi ornare eu. Vivamus vulputate sollicitudin tortor, eget convallis elit commodo nec. Sed hendrerit scelerisque interdum. Mauris mollis dolor ut dolor blandit interdum tempus velit facilisis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras vitae nulla dui. Aliquam malesuada leo at sem congue elementum. Mauris semper vestibulum vestibulum.
             
             Suspendisse mauris purus, imperdiet vel porttitor sit amet, commodo et lectus. Proin vel odio in tellus accumsan vehicula. Fusce dapibus urna ante, eget dapibus quam. Integer a elementum diam. Aenean eget est nisi. Vestibulum accumsan, neque in malesuada mattis, quam purus ullamcorper eros, ac gravida nisl eros quis nisl. Maecenas ut pellentesque orci. Praesent et augue sit amet metus fermentum semper vel vel lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris at neque orci. Nullam quis ante massa, sed lacinia justo.
             
             Suspendisse potenti. Nullam rutrum semper tempus. Etiam hendrerit elementum orci ut consectetur. Aenean erat nunc, pulvinar eget porttitor at, facilisis pretium sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris id lacus sed quam vehicula molestie. Quisque nibh arcu, pretium et tincidunt eu, congue nec dolor. Praesent sit amet dolor urna, nec tincidunt nisi. Aliquam erat diam, fringilla in mattis a, fringilla ut massa. Vestibulum semper dolor vitae ante venenatis ullamcorper pellentesque nunc sodales. Quisque viverra felis id dui commodo viverra. Ut sit amet odio non ante dictum ullamcorper. Vivamus venenatis pretium est, et mattis augue pretium venenatis. Aliquam hendrerit dictum velit, id interdum velit eleifend vel.
             
             Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus libero ante, laoreet ut rutrum tempus, convallis et enim. Ut justo erat, blandit sit amet ultricies at, vulputate ut lectus. Quisque et dui eu nisi dapibus dictum sit amet vel quam. Aenean tincidunt auctor ligula ac rutrum. Donec nulla urna, porta at luctus vitae, rhoncus ultricies magna. Nunc ultricies massa nulla, fringilla bibendum nulla. Duis viverra laoreet nisl in porttitor. Aenean et adipiscing tellus. Mauris et fringilla sem. Suspendisse ut justo ipsum. In nibh mi, semper non imperdiet ut, posuere in erat. Sed hendrerit, ligula ut convallis iaculis, ante justo tempus quam, at vulputate ligula ligula sit amet enim. Mauris vestibulum malesuada molestie. Pellentesque non lorem porttitor augue ullamcorper adipiscing sit amet id augue. Donec viverra, ipsum at interdum lobortis, velit ligula ornare purus, ac ultrices ante quam ac nibh. Vestibulum pharetra, purus id adipiscing volutpat, orci dui dignissim magna, et fermentum elit tellus at ipsum.
             
             Suspendisse in turpis risus. Nunc ut sagittis metus. Maecenas auctor nibh eu dui hendrerit eget blandit sapien sollicitudin. Mauris eu libero dolor, ut facilisis est. Integer id tortor non dolor malesuada vestibulum. Quisque quis dolor id mi posuere pulvinar. Sed mollis, dui ac laoreet facilisis, lorem mi facilisis sem, quis vulputate purus lectus ut ante. Maecenas in orci eu tellus viverra feugiat sed et justo. Curabitur nunc purus, rutrum sit amet ultrices facilisis, scelerisque eu neque. Duis non ipsum vel urna scelerisque faucibus sit amet non nunc. In ut consequat urna.
             
             Nam bibendum ligula ac tellus sagittis eget tristique tortor laoreet. Nam quis nisl orci, non fringilla nunc. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque varius convallis diam congue egestas. Nullam ut turpis id ante congue iaculis vel eget nisi. Sed faucibus semper nisl, at dapibus sapien tempor vitae. Curabitur odio nunc, dapibus id aliquam ac, vulputate eu magna. Aenean consequat egestas massa, sit amet laoreet nisi ornare eu. Vivamus vulputate sollicitudin tortor, eget convallis elit commodo nec. Sed hendrerit scelerisque interdum. Mauris mollis dolor ut dolor blandit interdum tempus velit facilisis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras vitae nulla dui. Aliquam malesuada leo at sem congue elementum. Mauris semper vestibulum vestibulum.
             
             Suspendisse mauris purus, imperdiet vel porttitor sit amet, commodo et lectus. Proin vel odio in tellus accumsan vehicula. Fusce dapibus urna ante, eget dapibus quam. Integer a elementum diam. Aenean eget est nisi. Vestibulum accumsan, neque in malesuada mattis, quam purus ullamcorper eros, ac gravida nisl eros quis nisl. Maecenas ut pellentesque orci. Praesent et augue sit amet metus fermentum semper vel vel lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris at neque orci. Nullam quis ante massa, sed lacinia justo.
             
             Suspendisse potenti. Nullam rutrum semper tempus. Etiam hendrerit elementum orci ut consectetur. Aenean erat nunc, pulvinar eget porttitor at, facilisis pretium sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris id lacus sed quam vehicula molestie. Quisque nibh arcu, pretium et tincidunt eu, congue nec dolor. Praesent sit amet dolor urna, nec tincidunt nisi. Aliquam erat diam, fringilla in mattis a, fringilla ut massa. Vestibulum semper dolor vitae ante venenatis ullamcorper pellentesque nunc sodales. Quisque viverra felis id dui commodo viverra. Ut sit amet odio non ante dictum ullamcorper. Vivamus venenatis pretium est, et mattis augue pretium venenatis. Aliquam hendrerit dictum velit, id interdum velit eleifend vel.
             
             Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus libero ante, laoreet ut rutrum tempus, convallis et enim. Ut justo erat, blandit sit amet ultricies at, vulputate ut lectus. Quisque et dui eu nisi dapibus dictum sit amet vel quam. Aenean tincidunt auctor ligula ac rutrum. Donec nulla urna, porta at luctus vitae, rhoncus ultricies magna. Nunc ultricies massa nulla, fringilla bibendum nulla. Duis viverra laoreet nisl in porttitor. Aenean et adipiscing tellus. Mauris et fringilla sem. Suspendisse ut justo ipsum. In nibh mi, semper non imperdiet ut, posuere in erat. Sed hendrerit, ligula ut convallis iaculis, ante justo tempus quam, at vulputate ligula ligula sit amet enim. Mauris vestibulum malesuada molestie. Pellentesque non lorem porttitor augue ullamcorper adipiscing sit amet id augue. Donec viverra, ipsum at interdum lobortis, velit ligula ornare purus, ac ultrices ante quam ac nibh. Vestibulum pharetra, purus id adipiscing volutpat, orci dui dignissim magna, et fermentum elit tellus at ipsum.
             
             Suspendisse in turpis risus. Nunc ut sagittis metus. Maecenas auctor nibh eu dui hendrerit eget blandit sapien sollicitudin. Mauris eu libero dolor, ut facilisis est. Integer id tortor non dolor malesuada vestibulum. Quisque quis dolor id mi posuere pulvinar. Sed mollis, dui ac laoreet facilisis, lorem mi facilisis sem, quis vulputate purus lectus ut ante. Maecenas in orci eu tellus viverra feugiat sed et justo. Curabitur nunc purus, rutrum sit amet ultrices facilisis, scelerisque eu neque. Duis non ipsum vel urna scelerisque faucibus sit amet non nunc. In ut consequat urna.
             
             Nam bibendum ligula ac tellus sagittis eget tristique tortor laoreet. Nam quis nisl orci, non fringilla nunc. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque varius convallis diam congue egestas. Nullam ut turpis id ante congue iaculis vel eget nisi. Sed faucibus semper nisl, at dapibus sapien tempor vitae. Curabitur odio nunc, dapibus id aliquam ac, vulputate eu magna. Aenean consequat egestas massa, sit amet laoreet nisi ornare eu. Vivamus vulputate sollicitudin tortor, eget convallis elit commodo nec. Sed hendrerit scelerisque interdum. Mauris mollis dolor ut dolor blandit interdum tempus velit facilisis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras vitae nulla dui. Aliquam malesuada leo at sem congue elementum. Mauris semper vestibulum vestibulum.
             
             Suspendisse mauris purus, imperdiet vel porttitor sit amet, commodo et lectus. Proin vel odio in tellus accumsan vehicula. Fusce dapibus urna ante, eget dapibus quam. Integer a elementum diam. Aenean eget est nisi. Vestibulum accumsan, neque in malesuada mattis, quam purus ullamcorper eros, ac gravida nisl eros quis nisl. Maecenas ut pellentesque orci. Praesent et augue sit amet metus fermentum semper vel vel lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris at neque orci. Nullam quis ante massa, sed lacinia justo.
             
             Suspendisse potenti. Nullam rutrum semper tempus. Etiam hendrerit elementum orci ut consectetur. Aenean erat nunc, pulvinar eget porttitor at, facilisis pretium sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris id lacus sed quam vehicula molestie. Quisque nibh arcu, pretium et tincidunt eu, congue nec dolor. Praesent sit amet dolor urna, nec tincidunt nisi. Aliquam erat diam, fringilla in mattis a, fringilla ut massa. Vestibulum semper dolor vitae ante venenatis ullamcorper pellentesque nunc sodales. Quisque viverra felis id dui commodo viverra. Ut sit amet odio non ante dictum ullamcorper. Vivamus venenatis pretium est, et mattis augue pretium venenatis. Aliquam hendrerit dictum velit, id interdum velit eleifend vel.
             
             Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus libero ante, laoreet ut rutrum tempus, convallis et enim. Ut justo erat, blandit sit amet ultricies at, vulputate ut lectus. Quisque et dui eu nisi dapibus dictum sit amet vel quam. Aenean tincidunt auctor ligula ac rutrum. Donec nulla urna, porta at luctus vitae, rhoncus ultricies magna. Nunc ultricies massa nulla, fringilla bibendum nulla. Duis viverra laoreet nisl in porttitor. Aenean et adipiscing tellus. Mauris et fringilla sem. Suspendisse ut justo ipsum. In nibh mi, semper non imperdiet ut, posuere in erat. Sed hendrerit, ligula ut convallis iaculis, ante justo tempus quam, at vulputate ligula ligula sit amet enim. Mauris vestibulum malesuada molestie. Pellentesque non lorem porttitor augue ullamcorper adipiscing sit amet id augue. Donec viverra, ipsum at interdum lobortis, velit ligula ornare purus, ac ultrices ante quam ac nibh. Vestibulum pharetra, purus id adipiscing volutpat, orci dui dignissim magna, et fermentum elit tellus at ipsum.
             
             Suspendisse in turpis risus. Nunc ut sagittis metus. Maecenas auctor nibh eu dui hendrerit eget blandit sapien sollicitudin. Mauris eu libero dolor, ut facilisis est. Integer id tortor non dolor malesuada vestibulum. Quisque quis dolor id mi posuere pulvinar. Sed mollis, dui ac laoreet facilisis, lorem mi facilisis sem, quis vulputate purus lectus ut ante. Maecenas in orci eu tellus viverra feugiat sed et justo. Curabitur nunc purus, rutrum sit amet ultrices facilisis, scelerisque eu neque. Duis non ipsum vel urna scelerisque faucibus sit amet non nunc. In ut consequat urna.
             
             Nam bibendum ligula ac tellus sagittis eget tristique tortor laoreet. Nam quis nisl orci, non fringilla nunc. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque varius convallis diam congue egestas. Nullam ut turpis id ante congue iaculis vel eget nisi. Sed faucibus semper nisl, at dapibus sapien tempor vitae. Curabitur odio nunc, dapibus id aliquam ac, vulputate eu magna. Aenean consequat egestas massa, sit amet laoreet nisi ornare eu. Vivamus vulputate sollicitudin tortor, eget convallis elit commodo nec. Sed hendrerit scelerisque interdum. Mauris mollis dolor ut dolor blandit interdum tempus velit facilisis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras vitae nulla dui. Aliquam malesuada leo at sem congue elementum. Mauris semper vestibulum vestibulum.
             
             Suspendisse mauris purus, imperdiet vel porttitor sit amet, commodo et lectus. Proin vel odio in tellus accumsan vehicula. Fusce dapibus urna ante, eget dapibus quam. Integer a elementum diam. Aenean eget est nisi. Vestibulum accumsan, neque in malesuada mattis, quam purus ullamcorper eros, ac gravida nisl eros quis nisl. Maecenas ut pellentesque orci. Praesent et augue sit amet metus fermentum semper vel vel lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris at neque orci. Nullam quis ante massa, sed lacinia justo.
             
             Suspendisse potenti. Nullam rutrum semper tempus. Etiam hendrerit elementum orci ut consectetur. Aenean erat nunc, pulvinar eget porttitor at, facilisis pretium sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris id lacus sed quam vehicula molestie. Quisque nibh arcu, pretium et tincidunt eu, congue nec dolor. Praesent sit amet dolor urna, nec tincidunt nisi. Aliquam erat diam, fringilla in mattis a, fringilla ut massa. Vestibulum semper dolor vitae ante venenatis ullamcorper pellentesque nunc sodales. Quisque viverra felis id dui commodo viverra. Ut sit amet odio non ante dictum ullamcorper. Vivamus venenatis pretium est, et mattis augue pretium venenatis. Aliquam hendrerit dictum velit, id interdum velit eleifend vel.
             
             
             -------------------------------28947758029299--
                    

POST api/files?{correlationId}

                    Same as "POST api/files", but accepts a "correlationId" parameter on the query string, to allow the caller
            to provide its own ID for the file, for the purpose of later retrieval.
                    

POST api/filemetadata

                    Creates a metadata record that is used to track files uploaded to blob storage
                    

GET api/files/{blobName}/aquireLease

                    Acquires a blob lease.
                    

GET api/files/{blobName}/releaseLease?{leaseId}

                    Releases a Blob lease.
            Use "api/files/{blobName}/releaseLease?{leaseId}" to release a lease.
                    

GET api/files/{blobName}/renewLease?{leaseId}

                    Renews a Blob lease.
            Use "api/files/{blobName}/renewLease?{leaseId}" to renew a lease.
                    

PUT api/files?{leaseId}

                    Updates the contents of a blob.
                    

DELETE api/files/{fileId:guid}

                    Delete a file.
                    

DELETE api/files/{fileName}

                    Delete a file.
                    


Resource: Integrations

HTTP TemplateDescription
GET api/integrations

                    Gets integrations within a tenant.
                    

GET api/integrations/{integrationId}

                    Gets a single Integration.
                    

POST api/integrations

                    Creates an Integration resource within a tenant.
                    


Resource: IntegrationSettings

HTTP TemplateDescription
GET api/integrationSettings?{integrationId}

                    Gets IntegrationSettings for a specific Integration.
                    

GET api/integrationSettings/{integrationSettingId}

                    Gets an IntegrationSetting.
                    

POST api/integrationSettings

                    Creates an IntegrationSetting.
                    


Resource: IntegrationTypes

HTTP TemplateDescription
GET api/integrationTypes?{lookupKey}

                    Gets an IntegrationType by LookupKey
                    


Resource: Locations

HTTP TemplateDescription
POST api/locations

                    Insert a list of locations into the datastore.
                    


Resource: MessageAudits

HTTP TemplateDescription
GET api/messageAudits/{messageAuditId}

                    Gets a single MessageAudit.
                    

GET api/messageAudits?{messageId}

                    Gets all of the MessageAudit resources for a given MessageId
                    

POST api/messageAudits

                    Creates a MessageAudit
                    


Resource: MessageAuditTypes

HTTP TemplateDescription
GET api/messageAuditTypes?{lookupKey}

                    Gets a MessageAuditType by lookupKey
                    

GET api/messageAuditTypes

                    Gets all MessageAuditTypes
                    


Resource: MessageRoutes

HTTP TemplateDescription
GET api/messageRoute?{messageRouteId:guid}

                    Gets message route
                    

POST api/messageRoute

                    Creates a message route with a destination. A new destination will be created if a messageDestinationId is not passed in
                    

DELETE api/messageRoute?{messageRouteId:guid}

                    Deletes a message route
                    


Resource: Messages

HTTP TemplateDescription
GET api/messages?{senderSessionId}&{senderSessionSequence}

                    Gets a Message.
                    

GET api/messages/{messageId}

                    Gets a Message.
                    

GET api/messages?{senderSessionId}

                    Gets the messages for the given senderSessionId
                    

GET api/messages

                    Gets messages.
            
             If no query string parameters are specified, this will return all messages for the request tenant (not recommended).
             
             If query string parameters are passed, they will be used to filter the messages in the result.  The result will always
             be an array, even if there is no results or a single result.
             
             Query string parameters can be any of the following, and can be combined to create more complex filters:
             MessageMessageId (GUID): search by MessageId x
             MessageCreatedAfterUtc (ISO8601 datetime string): search for messages that were created at or after the given datetime
             MessageCreatedBeforeUtc (ISO8601 datetime string): search for messages that were created before the given datetime
             MessageUpdatedAfterUtc (ISO8601 datetime string): search for messages that were last updated at or after the given datetime
             MessageUpdatedBeforeUtc (ISO8601 datetime string): search for messages that were last updated before the given datetime
             MessageApplicationId (GUID): search for messages for the given ApplicationId x
             MessageApplicationVersionId (GUID): search for messages for the given ApplicationVersionId x
             MessageDeviceId (GUID): search for messages for the given DeviceId x
             MessageDeviceGroupId (GUID): search for messages for the given DeviceGroupId x
             MessageUserId (GUID): search for messages for the given UserId x
             MessageUserGroupId (GUID): search for messages for the given UserGroupId x
             MessageUserName (string): search for messages for the given username (exact match) x
             MessageAuditTypeLookupKey (string): search for messages which have a latest audit with the given lookup key (partial match) x
             MessageSkip (integer): number of records to skip (for paging) x
             MessageTake (integer): number of records to take (for paging) x
             IncludeFullDocument (bool): true return audits and body with the messages - defaults to false x
             MessageTypeLookupKey (string): search for messages by the given MessageTypeLookupKey
                    

POST api/messages

                    Creates (and submits) a Message for processing.
                    

PUT api/messages/{messageId:guid}/body

                    Updates the body of a message, but does not (re)submit the message.
                    

POST api/messages/{messageId:guid}/resubmit

                    Resubmit a message to the appropriate message processor.
            Does not modify the existing message
                    

GET api/messageBodies/putData

                    Gets an example of the message body format for a "PutData" message.
                    

GET api/messageBodies/transaction

                    Gets an example of the message body format for a "Transaction" message.
                    

GET api/messageBodies/runIntegration

                    Gets an example of the message body format for a "RunIntegration" message.
                    

GET api/messageBodies/login

                    Gets an example of the message body format for a "Login" message.
                    

GET api/messageBodies/pushNotification

                    Gets and example of the message body format for a "PushNotification" message.
                    

GET api/messageBodies/putDataDelete

                    Gets and example of the message body format for a "PutDataDelete" message.
                    

GET api/messageBodies/routeData

                    Gets and example of the message body format for a Route Data message.
            NodeRoutingRequest Properties
            type: Activate/Deactivate
            targetNode: The node to apply the routes to (only key fields are required: nodeId or type/id)
            Routes: array of key/value pairs.
                Well known route keys:
                usr = UserId (Guid identifier for a Cyan User)
                usrg = UserGroupId (Guid identifier for a Cyan Application)
                app = ApplicationId (Guid identifier for a Cyan Application)
                appv = ApplicationVersionId (Guid identifier for a Cyan ApplicationVersion)
                dev = DeviceId (Guid identifier for a Cyan Device)
                devg = DeviceGroupId (Guid identifier for a Cyan DeviceGroup)
                Custom route keys:
                Any custom key/value known by an application can be used.
            applyParentRoutes:  (Activate) If true and routes is empty, system will find the parent of the targetNode 
                                and apply any active routes on the parent to the targetNode.
            applyToDescendants:  (Activate/Deactivate) If true, any routes specified will be applied to all descendants of the targetNode.
            applyToTree:  (Activate) If true, any routes specified will be applied to the targetNode as well as all nodes 
                          in the target nodes tree.  (Find root and apply to descendants)
                    


Resource: MessageTypes

HTTP TemplateDescription
GET api/messageTypes?{lookupKey}

                    Gets a MessageType by LookupKey
                    

GET api/messageTypes

                    Gets all MessageTypes
                    


Resource: NewId

HTTP TemplateDescription
GET api/newId?{dbSequenceName?}

                    Gets a new id value.
                    


Resource: NodeIndices

HTTP TemplateDescription
GET api/nodeIndices?{nodeId}

                    Gets the NodeIndices for a Node.
                    

GET api/nodeIndices/{nodeIndexId}

                    Gets a NodeIndex
                    

POST api/nodeIndices

                    Creates a NodeIndex
                    


Resource: NodeRoutes

HTTP TemplateDescription
GET api/nodeRoutes?{nodeId}

                    Gets all of the NodeRoutes for a Node
                    

GET api/nodeRoutes

                    Gets all NodeRoutes for a tenant.
                    

GET api/nodeRoutes/{nodeRouteId}

                    Gets a NodeRoute by NodeRouteId
                    

POST api/nodeRoutes

                    Creates a NodeRoute.
                    

DELETE api/nodeRoutes?{nodeId}&{userId?}&{userGroupId?}&{deviceId?}&{deviceGroupId?}&{applicationId?}&{applicationVersionId?}&{customKey?}&{customValue?}&{deleteChildRoutes?}

                    Deletes node routes for the given node.  Allows the caller to pass optional route filter parameters to control
            exactly which routes will be deleted from the node (and child nodes, if deleteChildNodes is true).
                    

DELETE api/nodeRoutes/{nodeRouteId}

                    Deletes a NodeRoute.
                    


Resource: Nodes

HTTP TemplateDescription
GET api/nodes/{nodeId}

                    Gets a Node resource.
                    

GET api/nodes?{type}&{id}&{parentType}&{parentId}

                    Gets a Node by the domain-specific type+id+parenttype+parentid identifier.  This assumes that the Tenant only
            contains a single Node with this type+id+parenttype+parentid.  If more than one Node is found, the first is returned.
                    

GET api/nodes?{type}&{id}

                    Gets a Node by the domain-specific type+id identifier.  This assumes that the Tenant only
            contains a single Node with this Type+ID.  If more than one Node is found, the first is returned.
                    

GET api/nodes/{nodeId}/tree

                    Gets a Node resource.
                    

GET api/nodes?{type}

                    Gets all Nodes for the given domain-specific type.
                    

GET api/nodes

                    Gets node resources.
             Calling this method with no query string parameters will return all nodes for a Tenant (not recommended).
             If you call this method with query string parameters, these will be used to query for Nodes using the NodeIndex table,
             or other special query mechanisms.
            
             For example, if you have created a Node with a property like "assignedTo" = "DGOOD" in the props bag, and also inserted
             a NodeIndex record with PropertyKey="assignedTo", and PropertyValue="DGOOD", you can issue a GET request to
             
             api/nodes?assignedTo=DGOOD
             
             This will run a query against the NodeIndex table to locate nodes that are indexed by the specified query parameters.
            
             In addition to searching the NodeIndex table to locate nodes, you can also pass special search keys to search based
             on other node-related properties:
             
             Special search keys:
             
             nodeNodeId - serach by the Node's "NodeId" (exact match).  Note: this is the NodeId GUID column, not the Node "Id" string.
             nodeType - search by the Node's "Type" (exact match)
             nodeId - search by the Node's "Id" (exact match)
             nodeParentType - search by the Node's "ParentType" (exact match)
             nodeParentId - search by the Node's "ParentId" (exact match)
             nodeTitle - search by the Node's "Title" (partial match or exact match with = modifier)
             nodeBody - search by the Node's raw "Body" JSON string (partial match) (this is not recommended, as the Node Body may not be in a predictable or easily-queryable format)
             nodeCreatedBeforeUtc - find all nodes that were created, or have NodeIndices that were created before the given UTC date time (non-inclusive)
             nodeCreatedAfterUtc - find all nodes that were created, or have NodeIndices that were created at or after the given UTC date time (inclusive)
             nodeUpdatedBeforeUtc - find all nodes that were last updated, or have NodeIndices that were last updated before the given UTC date time (non-inclusive)
             nodeUpdatedAfterUtc - find all nodes that were last updated, or have NodeIndices that were last updated at or after the given UTC date time (inclusive)
             nodeHasRoutes - "true": find nodes that have one or more routes, "false": find nodes that have no routes
             nodeRouteApplicationId - find nodes that have a route which matches this ApplicationId, or the route has null for ApplicationId
             nodeRouteApplicationVersionId - find nodes that have a route which matches this ApplicationVersionId, or the route has null for ApplicationVersionId
             nodeRouteUserId - find nodes that have a route which matches this UserId, or the route has null for UserId
             nodeRouteUserGroupId - find nodes that have a route which matches this UserGroupId, or the route has null for UserGroupId
             nodeRouteDeviceId - find nodes that have a route which matches this DeviceId, or the route has null for DeviceId
             nodeRouteDeviceGroupId - find nodes that have a route which matches this DeviceGroupId, or the route has null for DeviceGroupId
             nodeSkip - an integer that defines the number of records to skip (for paging)
             nodeTake - in integer that defines the number of records to take (for paging)
                    

GET api/nodes?{parentType}&{parentId}

                    Gets the child nodes for the specified parent Node Type+Id
                    

GET api/nodesXmlApiTransactions?{gtTransactionId}&{limit?}

                    This is a specific custom method used by the XML.Api "dequeue2" service
            for getting Mongo ONLY nodes where the transId property value
            is greater than the last successful transaction sent/received.
            ALERT: the n_props.transId filed should be indexed for any tenant using this Web Api endpoint.
                    

POST api/nodes

                    Creates a node resource.
                    

POST api/nodes/packages

                    Create a list of node resources with routes if specified.
                    

PUT api/nodes/{nodeId}

                    Updates a node resource.
                    

DELETE api/nodes?{nodeId}&{deleteChildNodes}

                    Deletes a node resource.
                    

DELETE api/nodes?{type}&{id}&{deleteChildNodes}

                    Deletes a node resource.
                    


Resource: RolesTest

HTTP TemplateDescription
GET api/rolesTest/anonymous

                    Tests a route that has no Authorize attribute.  This has no requirement for authentication or authorization of the current user.
                    

GET api/rolesTest/authenticated

                    Tests a route that has a plain "Authorize" attribute.  This requires that the current user be authenticated.
                    

GET api/rolesTest/admin

                    Tests a route that requires the RootAdmin or TenantAdmin role.
                    

GET api/rolesTest/rootadmin

                    Tests a route that requires the RootAdmin role.
                    

GET api/rolesTest/tenantadmin

                    Tests a route that requires the TenantAdmin role.
                    

GET api/rolesTest/tenantregistrar

                    Tests a route that requires the TenantRegistrar role.
                    

GET api/rolesTest/tenantdispatcher

                    Tests a route that requires the TenantDispatcher role.
                    

GET api/rolesTest/tenantuser

                    Tests a route that requires the TenantUser role.
                    


Resource: SharedAccess

HTTP TemplateDescription
GET api/sas/storage

                    Gets a shared access signature for st
                    


Resource: Sync

HTTP TemplateDescription
GET api/syncTokens?{userId}&{applicationId}

                    Returns the last SyncToken for the specified user and application.
                    

POST api/syncTokens

                    Creates a token that can be used to retrieve sync data.
                    

GET api/sync?{syncTokenId}&{pageSize}&{pageNumber}

                    Gets the data associated with a SyncToken
                    

GET api/sync/deletes?{syncTokenId}&{pageSize}&{pageNumber}

                    Gets the data associated with a SyncToken that should be deleted by the client.
            This will return the set of Nodes whose NodeRoutes have been deleted on the server-side.
                    

GET api/sync/snapshot

                    Get a database snapshot based on the provided SyncToken.
                    


Resource: TenantApplications

HTTP TemplateDescription
GET api/tenantApplications?{tenantId}&{applicationId}

                    Gets a TenantApplication.
                    

GET api/tenantApplications

                    Gets TenantApplications.
                    

POST api/tenantApplications

                    Creates a TenantApplication.
                    


Resource: TenantCustomPages

HTTP TemplateDescription
GET api/tenantCustomPage?{customPageId}

                    Gets an Custom Page by CustomPageId
                    

GET api/tenantCustomPage?{tenantId}&{customPageId}

                    Gets an Custom Page by TenantId and CustomPageId
                    

POST api/tenantCustomPage

                    Creates a tenant custom page.
                    

DELETE api/tenantCustomPage?{tenantId}&{customPageId}

                    Deletes a Custom Page by TenantId and CustomPageId
                    


Resource: Tenants

HTTP TemplateDescription
GET api/tenants?{accessKey}

                    Gets a Tenant by AccessKey.
                    

GET api/tenants/{tenantId}

                    Gets a Tenant.
                    

GET api/tenants

                    Gets all Tenants
                    

POST api/tenants

                    Creates a Tenant.
                    


Resource: UserGroups

HTTP TemplateDescription
GET api/userGroups

                    Gets all UserGroups.
                    

GET api/userGroups/{userGroupId}

                    Gets a UserGroup.
                    

POST api/userGroups

                    Creates a UserGroup.
                    


Resource: Users

HTTP TemplateDescription
GET api/users/{userId}

                    Gets a User by Tenant and UserId.
                    

GET api/users?{userName}

                    Gets a User by Tenant and UserName.
                    

GET api/users?{emailAddress}

                    Gets a User by Tenant and EmailAddress.
                    

GET api/users

                    Gets all of the users within a tenant.
                    

POST api/users

                    Creates a new User.
                    

PUT api/users/{userId}

                    Updates a user resource.
             
             The following User properties are updatable:
               Custom01
               Custom02
               Custom03
               Custom04
               Custom05
               Description
               Disabled
               EmailAddress
               PrimaryPhone
               UserName
               
               All of the above properties will be updated IF they are set in UserRepresentation. If not set, the
               property values will come through as null and will therefore not be set. To "blank" out the value 
               set the property value to an empty string.
            
             Note: Updating User Role and Memebership data is not currently supported through the Web API.
                    


Resource: Values

HTTP TemplateDescription
GET api/values

                    Gets all of the values (v1)
                    

GET api/values/{id}

                    Gets the value specified by id (v1)
                    

POST api/values

                    Creates a new value (v1)
                    

PUT api/values/{id}

                    Updates the value with the specified id (v1)
                    

DELETE api/values/{id}

                    Deletes the value with the specified id (v1)