Event Subscription Management

1. Access Control (JWT)

The Event Subscription Service (ESS) APIs uses the standard Concur OAuth2 Framework for Authentication and Authorization via JSON Web Token (JWT).

The authentication is done by using a JWT which represents the event subscriber. This can be obtained by calling the Client Credentials grant type using your OAuth2 credentials. The JWT generated by this grant will have a JWT Type of App where your Application ID is the Subject of the Token.

For authorization, the Application needs to contain the scope events.topic.read in order to access the ESS APIs. This scope will be inherited by the JWT during the Client Credentials Grant which is then checked by the ESS API.

Pass the JWT in the Post Header when making calls to the ESS API:

Authorization: Bearer <JWT>

The Client Credentials JWT has a lifetime of 60 minutes and can only be obtained again via the Client Credentials Grant.

2. Browse available topics

Before you create any subscription you need to verify that you have sufficient access to the topic. If that request returns empty you need to get in touch with your assigned contact from SAP Concur to set proper scopes to your Concur Oauth2 Application.

Request

GET /events/v4/topics

Response

["public.test"]

3. Create a subscription

To create a subscription you need to

  1. know and have sufficient access to the topic
  2. get your receiving endpoint running, endpoint requirements
  3. come up with unique name (id) of your subscription. Subscription names are globally unique, and you will get an error if name is already occupied.
  4. set filter to .* (regexp syntax), you can use it later to filter out unwanted types of events

Request

PUT /events/v4/subscriptions/webhook
{
  "id": "my-unique-subscription-id",
  "filter": ".*",
  "topic": "public.test",
  "webHookConfig": {
    "endpoint": "https://www.concuress.com/sub/my-valid-endpoint"
  }
}

Response

{"message":"Subscription 'my-unique-subscription-id' saved successfully"}

4. Verify your subscription

You can always request a configuration of your subscription. You might notice that your subscription contains some more parameters that you can not modify for security reasons, but can use them for troubleshooting purposes.

  • applicationId - identifies your Concur Application as an owner of that subscription
  • companyIds - a list of UUIDs of companies that allowed your Applicaion to access their data, the process of connecting Concur company to your application is described here (link)
  • groups and scope - are used for complex access control scenarios

Request

GET /events/v4/subscriptions/my-unique-subscription-id

Response

[
    {
        "id": "my-unique-subscription-id",
        "topic": "public.test",
        "filter": ".*",
        "webHookConfig": {
            "endpoint": "https://www.concuress.com/sub/my-valid-endpoint"
        },
        "applicationId": "dabd27f0-23e7-415d-b5e5-19a7dbe4fb4d",
        "scope": "",
        "groups": [],
        "companyIds": []
    }
]

5. Browse existing subscriptions

If you happen to forget your subscription name/id, you can always retrieve all of your subscriptions by calling next endpoint:
Request

GET /events/v4/subscriptions

Response

[
    {
        "id": "my-second-unique-subscription-id",
        "topic": "public.test",
        "filter": ".*",
        "webHookConfig": {
            "endpoint": "https://www.concuress.com/sub/my-second-valid-endpoint"
        },
        "applicationId": "dabd27f0-23e7-415d-b5e5-19a7dbe4fb4d",
        "scope": "",
        "groups": [],
        "companyIds": []
    },
    {
        "id": "my-unique-subscription-id",
        "topic": "public.test",
        "filter": ".*",
        "webHookConfig": {
            "endpoint": "https://www.concuress.com/sub/my-valid-endpoint"
        },
        "applicationId": "dabd27f0-23e7-415d-b5e5-19a7dbe4fb4d",
        "scope": "",
        "groups": [],
        "companyIds": []
    }
]

6. Delete your subscription

Request

DELETE /events/v4/subscriptions/my-unique-subscription-id

Response

{
    "message": "Subscription 'my-unique-subscription-id' marked for deletion"
}

6. Request Example

HEADERS

PUT /events/v4/subscriptions/webhook HTTP/1.1
Content-Type: application/json
Concur-Correlationid: something-unique-and-trackable
Authorization: Bearer eyJ0e*****MY-SECRET-JWT-HERE********
Accept: */*
Cache-Control: no-cache
Host: www-us.api.concursolutions.com
Accept-Encoding: gzip, deflate
Connection: keep-alive

BODY

{
  "id": "my-unique-subscription-example",
  "filter": ".*",
  "topic": "public.test",
  "webHookConfig": {"endpoint": "https://www.concuress.com/sub/my-unique-endpoint" }
}

CURL Code

curl -X PUT \
  https://www-us.api.concursolutions.com/events/v4/subscriptions/webhook \
  -H 'Accept: */*' \
  -H 'Accept-Encoding: gzip, deflate' \
  -H 'Authorization: Bearer eyJ0e*****MY-SECRET-JWT-HERE********' \
  -H 'Cache-Control: no-cache' \
  -H 'Concur-Correlationid: something-unique-and-trackable' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -H 'Host: www-us.api.concursolutions.com' \
  -H 'cache-control: no-cache' \
  -d '{
  "id": "my-unique-subscription-example-2",
  "filter": ".*",
  "topic": "public.test",
  "webHookConfig": {
    "endpoint": "https://www.concuress.com/sub/my-unique-endpoint"
  }
}'

On this page