User Events

Overview

When changes are made to a user's status on the AppDirect marketplace, a user event notification will be triggered and sent to the ISV. Such events include assigning a user to an application, removing a user from an application, or updating the user's information.

Developers must register two URL endpoints to handle notifications for access management related events: User Assignment Notification URL and User Unassignment Notification URL. (The developer can implement a URL for each event type or use a single URL to handle all of them.) When an event occurs, AppDirect will notify you by calling this URL, which is hosted by you, and passing an eventUrl parameter you will then use to fetch information about this event. The eventUrl parameter uniquely identifies the location of an event, which then can be used to fetch information about that event. Upon notification, you can perform an HTTP GET to the eventUrl to read an XML or JSON representation of the event.

These access URL endpoints are configured under the "Edit Integration Settings" section when you edit your product in the Developer Portal. We highly recommend that developers use HTTPS endpoints secured with SSL certificates. Such certificates have to be valid and verifiable by the AppDirect server for the integration to work. If a certificate does not pass this validation, it should either be fixed by the developer integrating his or her app, or manually added to the AppDirect server list of trusted certificates (using the Java keytool utility).

AppDirect's APIs support "two-legged" OAuth 1.0, also known as "signed fetch." You need to sign calls to this API using "2-legged OAuth". The OAuth consumer key and secret can be found under the "Edit Integration Settings" section. Additional information about using OAuth can be found here.

 

User Event Notification Flow

All user event notifications follow the same general flow:

  1. An event is triggered by a user action (e.g., assigning a user to an application, unassigning a user from an application, or updating customer information).
  2. AppDirect sends a user event notification to the application vendor (ISV). This event is uniquely identified by an event URL.  More detail about the notification URL is provided below.
  3. The ISV must validate the OAuth-signature on the request, then can read the event URL from the parameters to send an HTTP GET request for more information about the particular subscription event.
  4. The ISV then POSTs a request back to AppDirect, passing account and/or status information.
  5. This status information is used by AppDirect to provide feedback to the customer via the AppDirect UI.

 

Synchronous and Asynchronous Events

Typically when AppDirect sends a notification to an ISV, a response is expected. Subscription events are assumed to be synchronous (the response is received immediately) unless otherwise stated. However, when a business process requires a delayed response, AppDirect can support it with an asynchronous event. AppDirect listens for the delayed response to arrive.

The SUBSCRIPTION_NOTICE event is the only subscription event that does not involve a response so it is only supported as a synchronous event.

Notification URLs and Responses

When a user triggers an event on an AppDirect-powered marketplace, the marketplace performs an HTTP GET, signed with your OAuth credentials, to your notification URL and passes the event URL as a parameter. You must verify the OAuth signature for the call made to your notification URL is valid and refuse the call by returning an HTTP status 401 or 403 if it is not valid. Once the call has been validated, you can perform an HTTP GET, signed with your OAuth credentials, to the event URL you received to retrieve the information about this event in JSON or XML form. You can then process the event on your side (account creation, account updates, account cancellations, etc.). After processing the event you must respond to the call you received in JSON or XML form indicating the result of the operation. If an error occurred while processing the event, do not return a 500 or 404 status. Always return a 200 status with properly formatted JSON or XML as described below.

Success Response to a Notification


{
    "success": "true",
    "accountIdentifier": "new-account-identifier"
}

  
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<result>
	<success>true</success>
	<accountidentifier>new-account-identifier</accountidentifier>
</result>

AppDirect only requires an accountIdentifier in the response to a Subscription Order Event so we can know how to reference the new customer account in future Event Notifications.

Error Response to a Notification


{
	"success": "false",
	"errorCode": "ACCOUNT_NOT_FOUND",
	"message": "The account TEST123 could not be found."
}

  
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<result>
	<success>false</success>
	<errorcode>ACCOUNT_NOT_FOUND</errorcode>
	<message>The account TEST123 could not be found.</message>
<result>

Event Flags

Event notifications may contain an event flag field of the form value. AppDirect supports two possible flag values:

  • DEVELOPMENT: This event was generated for an application that is still in development. This is intended to allow application developers to identify events generated by applications in development that are not publicly visible. For example, it may be used to distinguish debugging and developer accounts from live accounts. These events need to be honored, but will not generate invoices or payments.
  • STATELESS: This event is for testing purposes only. No persistent state change is needed by the application. Applications will be expected to return some well-formed response, such as an error code. This flag will be used for API uptime monitoring.

Example User Event Notification Flow

An example of a user event notification flow is shown below using user assignment.

  1. Admin Alice assigns a seat to user Bob. This creates an event identified by URL https://www.acme-marketplace.com/api/integration/v1/events/12345.
  2. AppDirect calls http://example.com/assign?url=https%3A%2F%2Fwww.acme-marketplace.com%2Fapi%2Fintegration%2Fv1%2Fevents%2F12345
  3. Example.com issues a signed fetch to: https://www.acme-marketplace.com/api/integration/v1/events/12345
  4. AppDirect returns a user assignment event.

    
    {
        "type": "USER_ASSIGNMENT",
        "marketplace": {
          "baseUrl": "https://www.acme.com",
          "partner": "APPDIRECT"
        },
        "creator": {
          "email": "387a2e29-1dec-4ed0-b945-c9b4cf52381c",
          "firstName": "Another",
          "language": "en",
          "lastName": "User",
          "locale": "en-US",
          "openId": "https://www.acme.com/openid/id/b358dac2-da0c-40f2-a187-f7a34f183163",
          "uuid": "b358dac2-da0c-40f2-a187-f7a34f183163"
        },
        "payload": {
          "account": {
            "accountIdentifier": "202827",
            "status": "ACTIVE"
          },
          "user": {
            "email": "387a2e29-1dec-4ed0-b945-c9b4cf52381c",
            "firstName": "Another",
            "language": "en",
            "lastName": "User",
            "locale": "en-US",
            "openId": "https://www.acme.com/openid/id/b358dac2-da0c-40f2-a187-f7a34f183163",
            "uuid": "b358dac2-da0c-40f2-a187-f7a34f183163"
          }
        }
    }
    
    
      
    <?xml version="1.0" encoding="UTF-8" ?>
    <event>
            <type>USER_ASSIGNMENT</type>
            <marketplace>
                    <baseUrl>https://www.acme.com</baseUrl>
                    <partner>APPDIRECT</partner>
            </marketplace>
            <creator>
                    <email>387a2e29-1dec-4ed0-b945-c9b4cf52381c</email>
                    <firstName>Another</firstName>
                    <language>en</language>
                    <lastName>User</lastName>
                    <locale>en-US</locale>
                    <openId>https://www.acme.com/openid/id/b358dac2-da0c-40f2-a187-f7a34f183163</openId>
                    <uuid>b358dac2-da0c-40f2-a187-f7a34f183163</uuid>
            </creator>
            <payload>
                    <account>
                            <accountIdentifier>202827</accountIdentifier>
                            <status>ACTIVE</status>
                    </account>
                    <user>
                            <email>387a2e29-1dec-4ed0-b945-c9b4cf52381c</email>
                            <firstName>Another</firstName>
                            <language>en</language>
                            <lastName>User</lastName>
                            <locale>en-US</locale>
                            <openId>https://www.acme.com/openid/id/b358dac2-da0c-40f2-a187-f7a34f183163</openId>
                            <uuid>b358dac2-da0c-40f2-a187-f7a34f183163</uuid>
                    </user>
            </payload>
    </event>
    
    
  5. Example.com creates a new user for Bob in its account system.
  6. Example.com returns an XML response to the original HTTP request.

    
    Status Code: 200 OK
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Content-Length: 18
    Content-Type: application/json;charset=UTF-8
    Date: Tue, 25 Aug 2015 20:40:25 GMT
    Expires: 0
    Pragma: no-cache
    Server: Apache-Coyote/1.1
    Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    x-content-type-options: nosniff
    
    {
     	"success": "true"
    }
    
    
      
    Status Code: 200 OK
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Content-Length: 27
    Content-Type: application/xml;charset=UTF-8
    Date: Tue, 25 Aug 2015 20:40:25 GMT
    Expires: 0
    Pragma: no-cache
    Server: Apache-Coyote/1.1
    Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    x-content-type-options: nosniff
    
    <result>
        <success>true</success>
    </result>
    
    

    Or in the event of an error, Example.com can return an error code.

    
    Status Code: 400 Bad Request
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Content-Length: 46
    Content-Type: application/json;charset=UTF-8
    Date: Tue, 25 Aug 2015 20:40:25 GMT
    Expires: 0
    Pragma: no-cache
    Server: Apache-Coyote/1.1
    Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    x-content-type-options: nosniff
    
    {
     	"success": "false"
    	"errorCode": "MAX_USERS_REACHED"
    	"message": "Optional message about the max users being reached"
    }
    
    
      
    Status Code: 400 Bad Request
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Content-Length: 62
    Content-Type: application/xml;charset=UTF-8
    Date: Tue, 25 Aug 2015 20:40:25 GMT
    Expires: 0
    Pragma: no-cache
    Server: Apache-Coyote/1.1
    Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    x-content-type-options: nosniff
    
    <result>
        <success>false</success>
        <errorCode>MAX_USERS_REACHED</errorCode>
        <message>Optional message about the max users being reached</message>
    </result>
    
    

User Assignment

Admin users can add (assign) additional users to existing application subscriptions.  User assignments can be done either through the AppDirect UI (shown below) or by calling the AppDirect account API.

The user assignment event notification allows you to receive notice (USER_ASSIGNMENT) when a user is assigned to an existing subscription. In order to allow users to be assigned to existing subscriptions, you must define a user assignment notification URL, such as http://example.com/assign?url={eventUrl}, on the product's "Edit Integration" page. AppDirect will call this URL when users are assigned to existing subscriptions. This URL must contain the {eventUrl} placeholder which will be replaced by the URL of the order event at runtime.  

The general flow for a user assignment event notification is as follows:

  • An admin assigns a user to an application from AppDirect.

  • AppDirect creates a uniquely identified USER_ASSIGNMENT event, which is persisted in the AppDirect-powered marketplace. This event is uniquely identified by an event URL, such as https://www.acme-marketplace.com/api/integration/v1/events/d15bb36e-5fb5-11e0-8c3c-00262d2cda03.

  • AppDirect calls the configured User Assignment notification URL, passing the event URL as a parameter.
  • The application vendor must first validate the OAuth-signature in the authorization header.
  • The application vendor can then get the event URL from the URL parameters and issue an OAuth-signed fetch to read information regarding the USER_ASSIGNMENT event that was triggered. Briefly, this event contains the following elements:
    • type: The type of the event (USER_ASSIGNMENT in this case).
    • marketplace: Information about the AppDirect-powered marketplace on which the event took place.
    • creator: The identity of the admin user who triggered the event.
    • payload: The event payload, containing the following elements:
      • user: The user who is being assigned.
      • attributes: An optional list of key/value pairs representing user attributes.
      • accountIdentifier: The account identifier provided by the application in the initial Subscription Order.
  • The application vendor will add the retrieved user to their account system.
  • The application vendor responds to the original call from AppDirect with the following attributes:
    • success: Which should be "true" or "false."
    • errorCode: If "success" is false, this should contain one of the supported error codes.
    • message: An optional message containing information about the result of the operation.

Example USER_ASSIGNMENT event notification.


{
    "type": "USER_ASSIGNMENT",
    "marketplace": {
      "baseUrl": "https://www.acme.com",
      "partner": "APPDIRECT"
    },
    "creator": {
      "email": "c734676b-40f6-4783-b4ee-e20d59bbf943",
      "firstName": "Another",
      "language": "en",
      "lastName": "User",
      "locale": "en-US",
      "openId": "https://www.acme.com/openid/id/7ac30510-c54c-45ca-9c2f-f4d6b3aa2c15",
      "uuid": "7ac30510-c54c-45ca-9c2f-f4d6b3aa2c15"
    },
    "payload": {
      "account": {
        "accountIdentifier": "199722",
        "status": "ACTIVE"
      },
      "user": {
        "email": "c734676b-40f6-4783-b4ee-e20d59bbf943",
        "firstName": "Another",
        "language": "en",
        "lastName": "User",
        "locale": "en-US",
        "openId": "https://www.acme.com/openid/id/7ac30510-c54c-45ca-9c2f-f4d6b3aa2c15",
        "uuid": "7ac30510-c54c-45ca-9c2f-f4d6b3aa2c15"
      }
    }
}

  
<?xml version="1.0" encoding="UTF-8" ?>
<event>
        <type>USER_ASSIGNMENT</type>
        <marketplace>
                <baseUrl>https://www.acme.com</baseUrl>
                <partner>APPDIRECT</partner>
        </marketplace>
        <creator>
                <email>c734676b-40f6-4783-b4ee-e20d59bbf943</email>
                <firstName>Another</firstName>
                <language>en</language>
                <lastName>User</lastName>
                <locale>en-US</locale>
                <openId>https://www.acme.com/openid/id/7ac30510-c54c-45ca-9c2f-f4d6b3aa2c15</openId>
                <uuid>7ac30510-c54c-45ca-9c2f-f4d6b3aa2c15</uuid>
        </creator>
        <payload>
                <account>
                        <accountIdentifier>199722</accountIdentifier>
                        <status>ACTIVE</status>
                </account>
                <user>
                        <email>c734676b-40f6-4783-b4ee-e20d59bbf943</email>
                        <firstName>Another</firstName>
                        <language>en</language>
                        <lastName>User</lastName>
                        <locale>en-US</locale>
                        <openId>https://www.acme.com/openid/id/7ac30510-c54c-45ca-9c2f-f4d6b3aa2c15</openId>
                        <uuid>7ac30510-c54c-45ca-9c2f-f4d6b3aa2c15</uuid>
                </user>
        </payload>
</event>

User Unassignment

Admin users can remove (unassign) users from existing application subscriptions. User unassignments can be done either through the AppDirect UI (shown below) or by calling the AppDirect account API.

The user unassignment event notification allows you to receive notice (USER_UNASSIGNMENT) when a user is unassigned (removed) from an existing subscription. In order to allow users to be unassigned from existing subscriptions, you must define a user unassignment notification URL, such as http://example.com/unassign?url={eventUrl}, on the product's "Edit Integration" page. AppDirect will call this URL when users are unassigned from existing subscriptions. This URL must contain the {eventUrl} placeholder which will be replaced by the URL of the order event at runtime.

The general flow for a user unassignment event notification is as follows:

  • An admin user unassigns a user to an application from AppDirect.

  • AppDirect creates a uniquely identified USER_UNASSIGNMENT event, which is persisted in the AppDirect-powered marketplace. This event is uniquely identified by an event URL, such as https://www.acme-marketplace.com/api/integration/v1/events/d15bb36e-5fb5-11e0-8c3c-00262d2cda03.

  • AppDirect calls the configured User Unassignment notification URL, passing the event URL as a parameter.
  • The application vendor must first validate the OAuth-signature in the authorization header.
  • The application vendor can then get the event URL from the URL parameters and issue an OAuth-signed fetch to read information regarding the USER_UNASSIGNMENT event that was triggered. Briefly, this event contains the following elements:
    • type: The type of the event (USER_UNASSIGNMENT in this case).
    • marketplace: Information about the AppDirect-powered marketplace on which the event took place.
    • creator: The identity of the user who triggered the event.
    • payload: The event payload, containing the following elements:
      • user: The user who is being assigned.
      • attributes: An optional list of key/value pairs representing user attributes.
      • accountIdentifier: The account identifier provided by the application in the initial Subscription Order.
  • The application vendor removes the retrieved user from their account system.
  • The application vendor responds to the original call from AppDirect with the following attributes:
    • success: Which should be "true" or "false."
    • errorCode: If "success" is false, this should contain one of the supported error codes.
    • message: An optional message containing information about the result of the operation.

Example USER_UNASSIGNMENT event notification.


{
    "type": "USER_UNASSIGNMENT",
    "marketplace": {
      "baseUrl": "https://www.acme.com",
      "partner": "APPDIRECT"
    },
    "creator": {
      "email": "738a5bd7-7472-3ebb-9754-14520f89eac7",
      "firstName": "Another",
      "language": "en",
      "lastName": "User",
      "locale": "en-US",
      "openId": "https://www.acme.com/openid/id/a9501ec3-d028-4ad0-a939-607d10c24fe3",
      "uuid": "a9501ec3-d028-4ad0-a939-607d10c24fe3"
    },
    "payload": {
      "account": {
        "accountIdentifier": "199722",
        "status": "ACTIVE"
      },
      "user": {
        "address": {
          "city": "San Jose",
          "country": "US",
          "firstName": "Another",
          "fullName": "Another User",
          "lastName": "User",
          "state": "CA",
          "street1": "1 Main St",
          "zip": "95131"
        },
        "email": "738a5bd7-7472-3ebb-9754-14520f89eac7",
        "firstName": "Another",
        "language": "en",
        "lastName": "User",
        "locale": "en-US",
        "openId": "https://test.appdirect.com/openid/id/a9501ec3-d028-4ad0-a939-607d10c24fe3",
        "uuid": "a9501ec3-d028-4ad0-a939-607d10c24fe3"
      }
    }
}

  
<?xml version="1.0" encoding="UTF-8" ?>
<event>
        <type>USER_UNASSIGNMENT</type>
        <marketplace>
                <baseUrl>https://www.acme.com</baseUrl>
                <partner>APPDIRECT</partner>
        </marketplace>
        <creator>
                <email>738a5bd7-7472-3ebb-9754-14520f89eac7</email>
                <firstName>Another</firstName>
                <language>en</language>
                <lastName>User</lastName>
                <locale>en-US</locale>
                <openId>https://www.acme.com/openid/id/a9501ec3-d028-4ad0-a939-607d10c24fe3</openId>
                <uuid>a9501ec3-d028-4ad0-a939-607d10c24fe3</uuid>
        </creator>
        <payload>
                <account>
                        <accountIdentifier>199722</accountIdentifier>
                        <status>ACTIVE</status>
                </account>
                <user>
                        <address>
                                <city>San Jose</city>
                                <country>US</country>
                                <firstName>Another</firstName>
                                <fullName>Another User</fullName>
                                <lastName>User</lastName>
                                <state>CA</state>
                                <street1>1 Main St</street1>
                                <zip>95131</zip>
                        </address>
                        <email>738a5bd7-7472-3ebb-9754-14520f89eac7</email>
                        <firstName>Another</firstName>
                        <language>en</language>
                        <lastName>User</lastName>
                        <locale>en-US</locale>
                        <openId>https://test.appdirect.com/openid/id/a9501ec3-d028-4ad0-a939-607d10c24fe3</openId>
                        <uuid>a9501ec3-d028-4ad0-a939-607d10c24fe3</uuid>
                </user>
        </payload>
</event>

Asynchronous Events

All subscription events that involve a response can also be supported as asynchronous (delayed response) events. (SUBSCRIPTION_NOTICE is the only subscription event that does not involve a response and therefore is only supported as a synchronous event.)

When AppDirect calls an ISV with a notification URL, they return a JSON or XML response, as well as an HTTP response code. Usually, this code is 200 (OK) or 201 (Created). Additionally, however, AppDirect will recognize an code of 202 (Accepted) as a mechanism for the ISV to tell AppDirect that the event has been received and is being processed, and the ISV will notify AppDirect upon completion. The ISV can make an HTTP POST to the /api/integration/v1/events/{eventUrl}/result endpoint to notify AppDirect of the result. The POST body is the same as it would be for a synchronous event response.  The subscription or assignment will remain in a "pending" state (e.g., PENDING_USER_ACTIVATION, PENDING_REMOTE_CREATION, or PENDING_REMOTE_CANCELLATION) in the AppDirect marketplace until AppDirect is notified of the result. When a subscription or assignment is in the pending state, the user cannot act upon it.

Asynchronous Event Notification Flow

All asynchronous event notifications follow the same general flow:

  1. An event is triggered by a customer action (e.g., purchasing an application, upgrading an existing subscription, cancelling a subscription, or failing to pay an invoice).
  2. AppDirect sends an asynchronous event notification to the application vendor (ISV). This event is uniquely identified by an event URL.  More details about the notification URL are provided below.
  3. The ISV must validate the OAuth-signature on the request, then can read the event URL from the parameters to send an HTTP GET request for more information about the particular subscription event.
  4. AppDirect sends a JSON or XML response to the ISV.
  5. The ISV then does a POST request back to AppDirect, passing account and/or status information. This status information is used by AppDirect to provide feedback to the customer via the AppDirect UI.
  6. The key difference with an asynchronous event is that the header returns a 202 (Accepted) HTTP code. AppDirect will recognize this code as a pending event.
  7. Once the event is manually resolved (such as an account is provisioned), the ISV can POST a result to the eventUrl.

 

Example Asynchronous Event Notification Flow

An example of a asynchronous event notification flow is shown below using a user assignment.

  1. Admin Alice assigns a seat to user Bob. This creates an event identified by URL https://www.acme-marketplace.com/api/integration/v1/events/12345.
  2. AppDirect calls http://example.com/assign?url=https%3A%2F%2Fwww.acme-marketplace.com%2Fapi%2Fintegration%2Fv1%2Fevents%2F12345
  3. Example.com issues a signed fetch to: https://www.acme-marketplace.com/api/integration/v1/events/12345
  4. AppDirect sends a JSON or XML response to the ISV.

    
    {
        "type": "USER_ASSIGNMENT",
        "marketplace": {
          "baseUrl": "https://www.acme.com",
          "partner": "APPDIRECT"
        },
        "creator": {
          "email": "387a2e29-1dec-4ed0-b945-c9b4cf52381c",
          "firstName": "Another",
          "language": "en",
          "lastName": "User",
          "locale": "en-US",
          "openId": "https://www.acme.com/openid/id/b358dac2-da0c-40f2-a187-f7a34f183163",
          "uuid": "b358dac2-da0c-40f2-a187-f7a34f183163"
        },
        "payload": {
          "account": {
            "accountIdentifier": "202827",
            "status": "ACTIVE"
          },
          "user": {
            "email": "387a2e29-1dec-4ed0-b945-c9b4cf52381c",
            "firstName": "Another",
            "language": "en",
            "lastName": "User",
            "locale": "en-US",
            "openId": "https://www.acme.com/openid/id/b358dac2-da0c-40f2-a187-f7a34f183163",
            "uuid": "b358dac2-da0c-40f2-a187-f7a34f183163"
          }
        }
    }
    
    
      
    <?xml version="1.0" encoding="UTF-8" ?>
    <event>
            <type>USER_ASSIGNMENT</type>
            <marketplace>
                    <baseUrl>https://www.acme.com</baseUrl>
                    <partner>APPDIRECT</partner>
            </marketplace>
            <creator>
                    <email>387a2e29-1dec-4ed0-b945-c9b4cf52381c</email>
                    <firstName>Another</firstName>
                    <language>en</language>
                    <lastName>User</lastName>
                    <locale>en-US</locale>
                    <openId>https://www.acme.com/openid/id/b358dac2-da0c-40f2-a187-f7a34f183163</openId>
                    <uuid>b358dac2-da0c-40f2-a187-f7a34f183163</uuid>
            </creator>
            <payload>
                    <account>
                            <accountIdentifier>202827</accountIdentifier>
                            <status>ACTIVE</status>
                    </account>
                    <user>
                            <email>387a2e29-1dec-4ed0-b945-c9b4cf52381c</email>
                            <firstName>Another</firstName>
                            <language>en</language>
                            <lastName>User</lastName>
                            <locale>en-US</locale>
                            <openId>https://www.acme.com/openid/id/b358dac2-da0c-40f2-a187-f7a34f183163</openId>
                            <uuid>b358dac2-da0c-40f2-a187-f7a34f183163</uuid>
                    </user>
            </payload>
    </event>
    
    
    
  5. Example.com starts the creation of a new user for Bob in its account system.
  6. Example.com returns an XML response to the original HTTP request.

    
    Status Code: 202 Accepted
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Content-Length: 17
    Content-Type: application/json;charset=UTF-8
    Date: Tue, 25 Aug 2015 20:40:25 GMT
    Expires: 0
    Pragma: no-cache
    Server: Apache-Coyote/1.1
    Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    x-content-type-options: nosniff
    
    {
     	"success":true
    }
    
    
      
    Status Code: 202 Accepted
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Content-Length: 35
    Content-Type: application/xml;charset=UTF-8
    Date: Tue, 25 Aug 2015 20:40:25 GMT
    Expires: 0
    Pragma: no-cache
    Server: Apache-Coyote/1.1
    Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    x-content-type-options: nosniff
    
    <result>
        <success>true</success>
    </result>
    
    
  7. AppDirect puts the user assignment into a pending state (PENDING_USER_ACTIVATION). The user cannot do anything with the subscription at this time.
  8. The ISV sends an HTTP POST to https://www.acme-marketplace.com/api/integration/v1/events/12345/result to indicate the account creation is complete. Note that the POST body is the same object as a synchronous event response. 
    
    Status Code: 200 OK
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Content-Length: 18
    Content-Type: application/json;charset=UTF-8
    Date: Tue, 25 Aug 2015 20:40:25 GMT
    Expires: 0
    Pragma: no-cache
    Server: Apache-Coyote/1.1
    Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    x-content-type-options: nosniff
    
    {
     	"success":true
    }
    
    
      
    Status Code: 200 OK
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Content-Length: 27
    Content-Type: application/xml;charset=UTF-8
    Date: Tue, 25 Aug 2015 20:40:25 GMT
    Expires: 0
    Pragma: no-cache
    Server: Apache-Coyote/1.1
    Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    x-content-type-options: nosniff
    
    <result>
        <success>true</success>
    </result>
    
    

    Or in the event of an error, Example.com can return an error code.

    
    Status Code: 400 Bad Request
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Content-Length: 46
    Content-Type: application/json;charset=UTF-8
    Date: Tue, 25 Aug 2015 20:40:25 GMT
    Expires: 0
    Pragma: no-cache
    Server: Apache-Coyote/1.1
    Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    x-content-type-options: nosniff
    
    {
     	"success": "false"
    	"errorCode": "MAX_USERS_REACHED"
    	"message": "Optional message about the max users being reached"
    }
    
    
      
    Status Code: 400 Bad Request
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Content-Length: 62
    Content-Type: application/xml;charset=UTF-8
    Date: Tue, 25 Aug 2015 20:40:25 GMT
    Expires: 0
    Pragma: no-cache
    Server: Apache-Coyote/1.1
    Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    x-content-type-options: nosniff
    
    <result>
        <success>false</success>
        <errorCode>MAX_USERS_REACHED</errorCode>
        <message>Optional message about the max users being reached</message>
    </result>
    
    

Attributes

AppDirect may pass several attributes as part of the request (JSON or XML) when it sends a event notification request to an ISV. Below is a table summarizing all of the possible attributes, as well as a table summarizing the attributes expected in the response (JSON or XML).

Supported Request Attributes

Request Field Format Required Description

type

String Enum

Yes

The type of event triggered in the AppDirect marketplace. Can be SUBSCRIPTION_ORDER, SUBSCRIPTION_CHANGE, SUBSCRIPTION_CANCEL, SUBSCRIPTION_NOTICE, USER_ASSIGNMENT, USER_UNASSIGNMENT, or USER_UPDATED.

marketplace

Object

Yes

Information about the partner channel.

marketplace.partner

String

Yes

The name of the channel, defaults to APPDIRECT.

marketplace.baseUrl

String

Yes

The root URL for the partner channel.

applicationUuid

String

No

The unique identifier for the application.

flag

String Enum

No

Flag indicating how the event is used, may be STATELESS or DEVELOPMENT.

returnUrl

String

No

An optional redirect URL.

creator

Object

No

The identity of the admin creating the event. Note that this will be the original purchaser of the application for SUBSCRIPTION_ORDER, but may be other users for the other event types.

creator.email

String

Yes

Email address for the creator.

creator.firstName

String

No

First name of the creator.

creator.language

String

No

Default language for the creator.

creator.lastName

Object

No

Last name of the creator.

creator.locale

String

No

Default locale for the creator.

creator.openId

String

No

The openId for the creator.

creator.uuid

String

No

Unique user identifier for the creator.

creator.address

Object

No

The creator's address

address.city

String

Yes, if address specified

Creator address city

address.country

String

Yes, if address specified

Creator address country

address.state

String

No

Creator address state

address.street1

String

Yes, if address specified

Creator street address line 1

address.street2

String

No

Creator street address line 2

address.zip

String

Yes, if address specified

Creator address zip code

creator.attributes

Array

No

Optional attributes about the creator.

payload

 

payload.user

Object

Yes, for USER_ASSIGNMENT, USER_UNASSIGNMENT, and USER_UDPATED events

The affected user; may or may not be the same as the creator.

user.email

String

Yes

Email address for the user.

user.firstName

String

No

First name of the user.

user.language

String

No

Default language for the user.

user.lastName

Object

No

Last name of the user.

user.locale

String

No

Default locale for the user.

user.openId

String

No

The openId for the user.

user.uuid

String

No

Unique user identifier for the user.

user.attributes

Array

No

Optional attributes about the user.

payload.user.address

Object

No

The user's address

address.city

String

Yes, if address specified

User address city

address.country

String

Yes, if address specified

User address country

address.state

String

No

User address state

address.street1

String

Yes, if address specified

User street address line 1

address.street2

String

No

User street address line 2

address.zip

String

Yes, if address specified

User address zip code

payload.account

Object

Yes, if account has been created.

The account associated with the event, except for SUBSCRIPTION_ORDER (when account is created).

accountIdentifier

String

Yes, if account has been created.

The unique account identifier.

status

String

Yes, if account has been created.

The current account status. Can be INITIALIZED, FAILED, FREE_TRIAL, FREE_TRIAL_EXPIRED, ACTIVE, SUSPENDED, or CANCELLED. The account will be in the INITIALIZED state until the ISV provides a result back to AppDirect indicating whether the account was successfully created or not.  When success is true, for instance, the account will be put into an ACTIVE or FREE_TRIAL state as appropriate.  When success is false, the account will be put into a FAILED state.

payload.company

Object

Yes, for SUBSCRIPTION_ORDER

Information about the company associated with the event.

company.uuid

String

Yes

The unique identifier for the company.

company.externalId

String

No

The external identifier for the company.

company.name

String

Yes

The name of the company.

company.email

String

Yes

The email associated with the company.

company.phoneNumber

String

Yes

The phone number associated with the company.

company.website

String

Yes

The company's website.

company.country

String

No

The company's country.

payload.order

Object

Yes, for SUBSCRIPTION_ORDER and SUBSCRIPTION_CHANGE

Part of payload, SUBSCRIPTION_ORDER and SUBSCRIPTION_CHANGE

order.editionCode

String

Yes

The code for the edition associated with the subscription event.

order.addonOfferingCode

String

No

The code for the addon offering associated with the subscription event, if there is an addon.

order.pricingDuration

String

Yes

The pricing duration for the edition associated with the subscription event.

payload.addonInstance

Object

Yes, for addon-related events

Information about the addon.

addonInstance.id

String

Yes

The identifier for the addon instance.

payload.addonBinding

Object

Yes, for addon-related events

Information about the addon binding.

addonInstance.id

String

Yes

The identifier for the addon binding.

payload.notice

Object

Yes, for SUBSCRIPTION_NOTICE only.

Information about the notice.

notice.type

String Enum

Yes

Type of notice; can be REACTIVATED, DEACTIVATED, or CLOSED

notice.message

String

No

A message containing additional information about the notice.

payload.configuration

Array

Yes, for SUBSCRIPTION_ORDER and SUBSCRIPTION_CHANGE

The configuration from the subscription's purchase order.

Response Attributes

Response Parameter Description

accountIdentifier

Unique account identifier for the customer on the ISV. Only required in the response to a Subscription Order Event.

errorCode

An error code as described below required when success is false.

message

An optional message string to use in conjunction with the errorCode.

success

A required boolean value -- true when success, false when error.

User Attributes

Vendors may also enable custom attribute fields that users will be prompted for during User Assignment operations. These attributes may be configured within an application's "Edit Integration Settings" page under "User Information to Sync".

User Attribute Description

companyDepartment

A company department provided by a user in a free-form text field, such as "HR" or "Sales".

companyTitle

A title provided by a user in a free-form text field, such as "Vice President"or "Engineer".

billingRate

A billing rate provided by a user in a free-form text field , such as "$100 an hour" or "500€ daily".

zipCode

A ZIP or postal code provided by a user in a free-form text field, such as "90210" or "M1 1AA".

timeZone

A user-provided time zone selected from valid tz zone values, such as "America/Pacific" or "Europe/Copenhagen".

appAdmin

A boolean value indicating whether the user should be an application administrator, such as "true" or "false".

accessRights

A boolean value indicating whether the user should have access rights, such as "true" or "false".

username

A user name provided by the user in a free-form text field, such as "exampleuser@testco.com" or "ExampleUser".

password

A password provided by the user in a free-form password text field, such as "secretPassword" or "abc123".

idNumber

An identification number provided by the user in a free-form text field, such as "9870123" or "12436769090".

These values will appear as part of the JSON or XML user payload as a list of key/value pairs, an example of which is shown below.


  "user": {
    ...
    "attributes": {
      "entry": [
        {
          "key": "timezone",
          "value": "America/Pacific"
        },
        {
          "key": "zipCode",
          "value": "90210"
        },
        {
          "key": "zipCode",
          "value": "90210"
        }
      ]
    }
    ...
  }

  
<?xml version="1.0" encoding="UTF-8" ?>
<user>
    ...
    <attributes>
        <entry>
            <key>timezone</key>
            <value>America/Pacific</value>
        </entry>
        <entry>
            <key>zipCode</key>
            <value>90210</value>
        </entry>
        <entry>
            <key>zipCode</key>
            <value>90210</value>
        </entry>
    </attributes>
    ...
</user>

Error Codes

Occasionally, it is necessary to return an error. If the application vendor must communicate a failure when processing information from AppDirect, one of the following error codes must be returned:

Error Code Description

USER_ALREADY_EXISTS

This error code is typically used when AppDirect admins try to buy subscriptions for apps they have already purchased directly from the application vendor. In this scenario, we will show the user an error message and prompt them to link their account.

USER_NOT_FOUND

This error code is typically used when AppDirect admins try to unassign users not found in the application vendor's account.

ACCOUNT_NOT_FOUND

This error code is typically used when AppDirect admins try to add or remove users from an account not found in the application vendor's records.

MAX_USERS_REACHED

This error code is typically used when AppDirect admins try to assign users beyond the limit of the number of seats available. AppDirect will typically prevent that from happening by monitoring application usage.

UNAUTHORIZED

This error code is returned when users try any action that is not authorized for that particular application, for example, if an application does not allow the original creator to be unassigned.

OPERATION_CANCELED

This error code is returned when a user manually interrupts the operation (clicking cancel on the account creation page, etc.).

CONFIGURATION_ERROR

This error code is returned when the vendor endpoint is not currently configured.

INVALID_RESPONSE

This error code is returned when the vendor was unable to process the event fetched from AppDirect.

PENDING

This error code is returned when the vendor was unable to process the event because the service is under provisioning.

FORBIDDEN

This error code is returned when the operation is not allowed.

BINDING_NOT_FOUND

This error code is returned when the specified binding cannot be found.

TRANSPORT_ERROR

This error code is returned when the there is a transport error, such as the server being unreachable.

UNKNOWN_ERROR

This error code may be used when none of the other error codes apply.