Expense - Associating External Attendees to Expense Entries

This guide prescribes how to associate external attendees to expense entries in Concur Expense. It assumes you are familiar with Concur Expense and the system of record for the external attendees. It also assumes that you have registered your application, and that you know how to make API calls to the SAP Concur Platform.

APIs Used in This Guide

Base URL: https://www.concursolutions.com/api/v3.0

  • /expense/attendees
  • /expense/entryattendeeassociations
  • /expense/attendeetypes

Context

For certain types of expenses such as entertainment, business meals, and events, the person filing the expense report must identify all the people who participated in the event. In Concur Expense, the participants are called attendees. Often, attendees are tracked and managed in a business system outside of SAP Concur such as a customer-relationship management (CRM) application. Concur Expense refers to these attendees as external attendees.

Solution Summary

To successfully associate attendees to an expense entry, the attendees and the expense entry must already exist in SAP Concur. Associating external attendees to an expense entry consists of these steps:

  1. Identifying the expense entry where the attendees should be associated.
  2. Determining if Concur Expense has a record of the external attendees.
  3. Adding any necessary external attendees.
  4. Getting the unique identifier SAP Concur has for each attendee.
  5. Associating the SAP Concur attendees to the expense entry.

Solution Details

This section provides details of the SAP Concur API calls you need to make to associate external attendees to expense entries.

The following is the sequence of API calls a fictitious partner application makes to the SAP Concur Platform. This app has a collection of external attendees it wants to associate to a specified expense entry. Each external attendee has a unique identifier assigned by the system of record for the attendees called the External ID.

The app has a collection of external attendees it wants to associate to a specified expense entry. Each external attendee has a unique identifier assigned by the system of record for the attendees called the External ID.

The sequence of events is as follows:

  1. The app sets up a loop that processes each attendee.
  2. The app searches SAP Concur using the External ID to determine whether it has a record for the external attendee.
  3. The search result returns information that indicates whether or not SAP Concur has a record for the attendee.
  4. If SAP Concur has it, the app gets the ID SAP Concur assigned to the attendee from the search results. Skip to Step 7.
  5. If SAP Concur doesn’t have it, the app needs to make an API call to the GET /expense/attendeetypes endpoint to obtain the ID for the attendee types.
  6. Make an API call to the POST /expense/attendees endpoint to create an attendee in the SAP Concur system. Use the ID value obtained in Step 5 for the AttendeeTypeID.
  7. SAP Concur responds with the just created attendee’s ID.
  8. The app associates the attendee with the expense entry.
  9. The loop repeats Steps 2 through 7 for each attendee.

The following sections provide the details for each API call.

1. Identify the Expense Entry

The method for identifying an expense entry depends on whether the expense entry needs to be created or it already exists. Regardless of whether you create a new expense entry or you search for an existing one, you can use the GET Reports API followed by the GET Report Details API to obtain the unique identifier for the expense entry.

  • Expense Reports v3
  • https://developer.concur.com/api-reference/expense/expense-report/expense-report-get.html

New Expense Entries

When creating a new expense entry, the SAP Concur Platform returns to the developer the unique identifier for the expense entry. In some cases a developer needs to create an expense entry. For example, in a CRM application there is an object called Sales Call that allows sales professionals to record expenses and contacts involved in a sales call they make for a prospective opportunity. In this case the developer creates an expense entry in Concur Expense to record the expense in the sales call. For details on how to create a new expense entry in Concur Expense, see these APIs:

  1. User to identify the Group value
  2. Group Configuration to identify Policy IDs, Payment Type IDs, Expense Type code
  3. Expense Form to identify the Form Name and Form Code
  4. Obtain Form Data for each form to which you need to post
  5. Obtain Form Field Details to identify the fields and their corresponding attributes
  6. List Items for fields defined as a list:
  7. Now you should have enough information to Post a new report and an entry within the report:

Existing Expense Entries

There are cases when the expense entry already exists. For example, in a CRM application there is an object called an Event that includes contacts, but not expenses. In this case, the expenses related to events come into Concur Expense as imported credit card charges. In this situation, you can use the search capabilities in the Expense Report web service to find the relevant expense entry associated to the event. When searching for an existing expense entry the SAP Concur Platform returns to the developer the unique identifier for the expense entry.

2. Determine If SAP Concur Has a Record of the External Attendees

To determine if SAP Concur has a record of external attendees, make a GET HTTPS request to the Attendees resource using the External ID search term for external attendees stored in SAP Concur:

GET https://www.concursolutions.com/api/v3.0/expense/attendees?externalid={unique_identifier_for_external_attendee} HTTP/1.1
Authorization: OAuth {valid OAuth Access Token goes here}
Content-Type: {application/json or application/xml goes here}

Where:

externalID is the unique identifier record for the external attendee assigned by the system of record. If the attendee with this external ID exists, the response includes the details about the attendee including its ID.

Example

Here’s an example for how to look for the SAP Concur record for an external attendee with an ID of 5575592349 in a business system outside of SAP Concur.

Make a GET HTTP request to the attendees endpoint:

GET https://www.concursolutions.com/api/v3.0/expense/attendees?externalid=5575592349 HTTP/1.1
Authorization: OAuth pBA8nW1qGJcd4AZp9sGxti374Cc=
Content-Type: application/json

If SAP Concur has a record of the external attendee, its unique identifier in SAP Concur is returned in the ID element and you can skip to Step 4. If SAP Concur does not have a record, the Items element will be empty and you need to add the external attendee in SAP Concur as prescribed in Step 3.

A successful response when SAP Concur has a record of the external attendee looks like this:

{
  "Items": [
    {
      "AttendeeTypeCode": "HCP",
      "AttendeeTypeID": "niJ6GaAD60bAetp3vtK6$sGRgCi1s",
      "FirstName": "Emilie",
      "LastName": "Cass",
      "MiddleInitial": null,
      "Suffix": null,
      "Company": "Life Care Center of Action",
      "Title": "Gynecology and Obstetrics",
      "ExternalID": "5575592349",
      "HasExceptionsPrevYear": false,
      "HasExceptionsYTD": false,
      "TotalAmountPrevYear": 0.00000000,
      "TotalAmountYTD": 0.00000000,
      "VersionNumber": 1,
      "OwnerName": "System, Concur",
      "OwnerLoginID": "ConcurSystem",
      "CurrencyCode": "USD",
      "Cust om1": null,
      "Custom2": null,
      "Custom3": null,
      "Custom4": null,
      "Custom5": null,
      "Custom6": null,
      "Custom7": null,
      "Custom8": null,
      "Custom9": null,
      "Custom10": null,
      "Custom11": null,
      "Custom12": null,
      "Custom13": null,
      "Custom14": null,
      "Custom15": null,
      "Custom16": null,
      "Custom17": null,
      "Custom18": null,
      "Custom19": null,
      "Custom20": null,
      "Custom21": null,
      "Custom22": null,
      "Custom23": null,
      "Custom24": null,
      "Custom25": null,
      "ID": "nmBwIaoDagUkD8kXZGIl7B170uK9tE6pk",
      "URI": "https://rqa3-cb.concurtech.net/api/v3.0/expense/attendees/nmBwIaoDagUkD8kXZGIl7B170uK9tE6pk"
    }
  ],
  "NextPage": null
}

3. Add External Attendees That Are Missing

If the attendee doesn’t exist in SAP Concur, make a POST request to the Attendees resource to create a new attendee in SAP Concur:

POST https://www.concursolutions.com/api/v3.0/expense/attendees HTTP/1.1
Authorization: OAuth {valid OAuth Access Token goes here}
Content-Type: {application/json or application/xml goes here}

The request content body includes the details about the attendee. For example:

{
  "AttendeeTypeID": "ID for the attendee type",
  "FirstName": "Taylor",
  "LastName": "Hernandez",
  "MiddleInitial": "E",
  "Company": "Life Care Center of Action",
  "Title": "Anaesthetics",
  "ExternalID": "6164704601"
}

To determine the value you need to enter for the AttendeeTypeID element in the content body of the POST request, make a GET request to the AttendeeTypes resource. For example:

GET https://www.concursolutions.com/api/v3.0/expense/attendeetypes HTTP/1.1
Authorization: OAuth pBA8nW1qGJcd4AZp9sGxti374Cc=
Content-Type: application/json

In this example, we’re looking for the attendee type ID for Business Guest attendee types. A successful response looks like this:

{
  "Items": [
    {
      "Name": "Business Guest",
      "Code": "BUSGUEST",
      "AttendeeFormID": "gWgSQwsOy6EcM7sy3esMk25cqEZM9yf9gPg",
      "DuplicateSearchFields": [
        "Title",
        "Company",
        "OwnerEmpName",
        "FirstName",
        "LastName"
      ],
      "ConnectorID": "",
      "AllowManuallyEnteredAttendees": true,
      "AllowAttendeeCountEditing": false,
      "ID": "gWjUHBxUY4iQLA9KTkbtUD6pc",
      "URI": "https://www.concursolutions.com /api/v3.0/expense/attendeetypes/gWjUHBxUY4iQLA9KTkbtUD6pc"
    },
    {
      "Name": "Employee",
      "Code": "EMPLOYEE",
      "AttendeeFormID": "gWgSQwsOy6EcM7sy3esMk25cqEZM9yf9gPg",
      "DuplicateSearchFields": [
        "Title",
        "Company",
        "OwnerEmpName",
        "FirstName",
        "LastName"
      ],
      "ConnectorID": "",
      "AllowManuallyEnteredAttendees": true,
      "AllowAttendeeCountEditing": false,
      "ID": "gWjYs6nUm$ptrgvkjvwYt2B3SN",
      "URI": " https://www.concursolutions.com/api/v3.0/expense/attendeetypes/gWjYs6nUm$ptrgvkjvwYt2B3SN"
    }
  ],
  "NextPage": null
}

Now we can make our POST request to the /api/v3.0/expense/attendees endpoint:

POST https://www.concursolutions.com/api/v3.0/expense/attendees HTTP/1.1
Authorization: OAuth pBA8nW1qGJcd4AZp9sGxti374Cc=
Content-Type: application/json

With this request body:

{
  "AttendeeTypeID": "gWjUHBxUY4iQLA9KTkbtUD6pc",
  "FirstName": "Taylor",
  "LastName": "Hernandez",
  "MiddleInitial": "E",
  "Company": "Life Care Center of Action",
  "Title": "Anaesthetics",
  "ExternalID": "6164704601"
}

A successful response looks like this:

{
  "ID":"nmBwIaoDagUvXYaxgYZp$pWlPZOvpzUfsM",
  "URI": "https://www.concursolutions.com/api/v3.0/expense/attendees/nmBwIaoDagUvXYaxgYZp$pWlPZOvpzUfsM"
}

4. Associate Attendee to the Expense Entry

Once you obtain the ID for the attendee, make a POST request to the Entry Attendee Associations resource. To make this call, the user account associated with the OAuth 2.0 access token must have an SAP Concur account with one of these roles: Web Services Administrator for Professional or Can Administer for Standard.

Here’s what the call looks like:

POST https://www.concursolutions.com/api/v3.0/expense/entryattendeeassociations?user={URL_Encoded_Login_ID_for_the_Login_ID_for_the_owner_of_the_expense_entry} HTTP/1.1
Authorization: OAuth {valid OAuth Access Token goes here}
Content-Type: application/json
Accept: application/json
...

{
  "EntryID": "n4MrUpcqIH3ot4bFvFCNXCpk7TJOphLTH",
  "AttendeeID": "nmBwIaoDagUkD8kXZGIl7B170uK9tE6pk"
}

In this example, the content body for POST request has an expense entry with the unique identifier n4MrUpcqIH3ot4bFvFCNXCpk7TJOphLTH and the attendee with the unique identifier nmBwIaoDagUkD8kXZGI l7B170uK9tE6pk.

On this page