Welcome

The Connecting-Expertise Vendor Management System, further referred to as CE-VMS, exposes services via REST. With our REST API, called Connecting-Expertise OpenApi, further referred to as CE-OpenApi, you develop applications that are able to exchange (read and write) data with the CE-VMS.

Our Connecting-Expertise OpenApi Event Message Inbox, further referred to as CE-OpenApi EMI, is a queue system. When you subscribe to this queue system, each CE-VMS application event is published to your message inbox as a unique message. You’ll be notified when a new message has been published, and will be able to respond accordingly.

The documentation is divided in three major sections:

Getting started

This section tells you everything you need to know about the creation of a request for our CE-OpenApi via a REST-client, and how to use the CE-OpenApi EMI.
It gives an overview of how requests are structured and what you can expect as a response. If you’ve used a REST-API before then you’ll know most of this already.

Essentials

This section contains generic information, how to?,…​ . Background information that’s useful when you’re working with our CE-OpenApi.

CE-OpenApi Method details

Subscribing to our public plan will allow you to make a limited number of requests to the CE-OpenApi. This should be sufficient for exploration purposes.

For more information on the commercial conditions that apply to using our APIs, please contact our sales team at sales@connecting-expertise.com.

Note
You are an early adopter of our new CE-OpenApi. If you run into a mistake, or can’t find what you’re looking for, please let us know via openapi@connecting-expertise.com.

Getting started

Before you can use our CE-OpenApi let’s explain how you get started.

Get connected

It’s easy to connect with the CE-OpenApi. Follow these 3 steps:

STEP 1

Register your company/user

If you already have a Connecting-Expertise login, you can skip this step. Otherwise, register as a new company/user.

Note
You may use these CE-VMS environments:
* Development: https://int.connecting-expertise.com
* Production: https://customer.connecting-expertise.com
STEP 2

Apply for access

Once you are able to logon to the CE-VMS, we will need to activate the CE-OpenApi. We can also activate the CE-OpenApi EMI on your request. Please contact us via openapi@connecting-expertise.com.
Subscribing to our public plan will allow you to make a limited number of requests to the CE-OpenApi. This should be sufficient for exploration purposes.
Once you develop a production application that relies on our api services, contact our sales team via sales@connecting-expertise.com.

In return, you’ll receive:

  1. For the CE-OpenApi

    • a client_id (e.g. SupplierApplication_Yik3jkDD7fJJIOKLPSDMaf_)

    • a client_secret (e.g. Q9dd8FDyFg4oeTMAFhDolJKlalaUD2pplosDSU_)

  2. For the CE-OpenApi EMI:

    • a client_id (e.g. Xvz1evFS4wEEPTGEFPHBog_)

    • a client_secret (e.g. L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ66DRdyFHH_)

Caution
Your client_secret key should not be shared or embedded in client-side code.
STEP 3

Try the CE-OpenApi services and CE-OpenApi EMI

Once your user has access to our CE-OpenApi or CE-OpenApi EMI, you can try out our services.

Building a request

The CE-OpenApi is a collection of 'REST(ful)' webservices. You interact with our resources by sending a message with the HTTPS protocol to a URL. The URL determines the resource and the HTTPS method defines the type of action. Data is passed as JSON in a POST request or as GET query parameters.

URLs

All URLs conform to this pattern:

https://{hostname} /{version} /{area} /[?{option_key}={option_value}]
Table 1. URL composition components
Component Explanation

hostname

The hostname determines whether you access the development- or production environment:
Development environment: https://openapi-mars.connecting-expertise.com/connectingExpertise/swagger/ce3OpenApi#/
Production environment: https://openapi.connecting-expertise.com/connectingExpertise/swagger/ce3OpenApi#/

version

New versions of services can be introduced with additional features. The version number allows you to select a particular service version.

area

The CE-OpenApi is separated into different 'areas':

Master data (e.g. city, company, department, language, location,…​)
Document
Received request
Human resource
Proposal

HTTP method

The HTTP method (GET, PUT, PATCH, POST, DELETE) defines what you want to do with the resource.

Authentication

The CE-OpenApi supports basic authentication and token based authentication. For more information, please check out Authentication for a detailed explanation.

Service request outcome: HAL

The output format of a CE-OpenApi request is HAL, short for "Hypertext Application Language" (See also "Hypertext Application Language").

HAL is an open specification describing a generic structure for RESTful resources. The structure it proposes readily achieves the Richardson Maturity Model’s Level 3, by ensuring that each resource contains relational links, and that a standard, identifiable structure exists for embedding other resources.

Note
Essentially, good RESTful APIs should:
- expose resources
- via HTTP, using HTTP verbs to manipulate them
- and provide canonical links to themselves, as well as link to other, related resources

HAL was created to be simple to use and easily applicable across different domains by avoiding the need to impose any requirements on structure of the project.
Maintaining this minimal impact approach, HAL has enabled developers to create general-purpose libraries which can be easily incorporated on any API that uses HAL.

APIs that adopt HAL simplify the use of open source libraries and make it possible to interact with the API using JSON or XML.

Connecting-Expertise OpenApi Console

We’ve teamed up with SwaggerHub to provide you with an interactive manual through a REST console. This console allows you to experiment with the CE-OpenApi without writing a single line of code.

Steps to explore our CE-OpenApi

If you like to experiment with our services on the CE-OpenApi, you need to follow these steps:

STEP 1

Visit our CE-OpenApi swagger page

Go to the desired swagger page (choose between development or production).

STEP 2

Select the "HTTPS" scheme (picklist on the left)

OpenApiConsole

STEP 3

“Authorize” (green button on the right)

OpenApiConsole Authorize

STEP 4

Enter credentials

Choose the desired authentication method (For more information, please check out Authentication).
With basic authentication, enter the credentials that you used to register yourself:

  • Username: your Connecting-Expertise login name

  • Password: your Connecting-Expertise password

    OpenApiConsole BasicAuthorization

STEP 5

Explore the CE-OpenApi

Click "Authorize" and you’re all set to explore our CE-OpenApi. It serves as an access point to your own CE-VMS environment.

Essentials

Authentication

The CE-OpenApi supports basic authentication and token based authentication. The CE-OpenApi EMI supports only token based authentication.

Note
An access token is a string representing the granted permissions.

Basic authentication

We allow basic authentication on our develop environment, but as soon as you want to integrate with our production environment, you’ll have to use the token based approach.

Note
Basic authentication is a simple authentication scheme built into the HTTPS protocol. Your client sends HTTPS requests with the Authorization header that contains the word Basic word followed by a space and a base64-encoded string username:password.

Example: to authorize as 'demo' / 'p@55w0rd', your client should send:

Authorization: Basic ZGVtbzpwQDU1dzByZA

Token based authentication

Even though you are able to use basic authentication to explore services for the CE-OpenApi on our development environment, you’ll have to use a token based approach as soon as you want to connect to our production environment, or use the CE-OpenApi EMI.
Token based authentication, which uses a bearer token, is also known as application-only authentication.

Note
Token based authentication consists of 2 steps:
- obtain a valid bearer token
- use a valid bearer token in your api requests
Obtain a valid bearer token

First of all we’ll need to set up access for your application account to the CE-OpenApi or CE-OpenApi EMI (Refer to Get connected).

With your own client_id your application is able to get an authorization code (not an authentication token!).
After receiving an authorisation code, your application exchanges this for an access token and a refresh token.

Note
An authorization code can only be exchanged once for an access token and expires 10 minutes after issuance.

These access tokens are also known as bearer tokens. You can use this token to call API endpoints on behalf of a user, by adding it to the API request as an Authorization header.

This 2-step authentication flow is necessary for security reasons.

Access tokens expire shortly after they are issued for security reasons. If your integration needs to communicate with our API beyond the access token’s lifespan, you will need to request a new access token using the refresh token which was issued with the access token. Note that refresh tokens can only be used once to get a new access token and refresh token.

Example: request a CE-OpenApi bearer token

Here’s an example of how your OIDC settings for the issuing of a CE-OpenApi bearer token might look like:

{
"authority": "https://auth-nonprod.connecting-expertise.com/realms/openapi-mars/protocol/openid-connect/token",
"redirectUri": "http://localhost:8082/oidc-callback", // (1)
"responseType": "token",
"scope": "openid profile",
"client_id": "SupplierApplication_Yik3jkDD7fJJIOKLPSDMaf_", // (2)
"client_secret": "Q9dd8FDyFg4oeTMAFhDolJKlalaUD2pplosDSU_" // (3)
}
  1. Replace with your own url

  2. Replace with your own client_id

  3. Replace with your own client_secret

Result:

{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJqb19wZC1HeHMxQUZscUhvNGUxMXo5Zm9sN083aFAzMVhjMS1fYmhabENRIn0eyJleHAiOjE2NDAxMTQ2MDksImlhdCI6MTY0MDExNDMwOSwianRpIjoiNTJhZGE5ZTQtNTQyZS00MTc2LWJiMWUtZGVlZDFmNzI2Y2Y3IiwiaXNzIjoiaHR0cHM6Ly9hdXRoLW5vbnByb2QuY29ubmVjdGluZy1leHBlcnRpc2UuY29tL2F1dGgvcmVhbG1zL2RldmVsb3AiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiYzRmMTNjNTYtNzhmYi00Y2RhLTg3NDQtYmVmM2Y5OGUxNDZlIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoic3VwcGxpZXJUZXN0Iiwic2Vzc2lvbl9zdGF0ZSI6IjgzYjc3ZGM0LWEyMjItNGY5MS1hYzIwLWQyYTE3YjdiNTU0ZCIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1kZXZlbG9wIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiJJKIOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhcGlAY29udGluZ2VudC5jb20iLCJlbWFpbCI6FDFwaUBjb250aW5nZW50LmNvbSJ9eQacAr_tvEgHrIQpE5vzhp1yDXpv_QDviFWr6Rf2zWJD_mBFA12S25cu3qq8fZq9NtHpvg6nhQ2hbilHHLez3g3YiuZKu1ZG6pf9dwQ1w0TMOEDxIgWduMHt_g0r9YCCHmy3y1Af5rIeq3g8_uySQ1iSJy9IKWMeGaHfRBmrhaalu0UU5jzKy4vEXc81TDtDVMP2vdwJUwxoQTsHEcdw3Ul024qonxOcUHRCs1pIOiu2d_ViRgdf9P0DPiWfPdYuoheUJQHoTPTChuXYCXtjTRwLZAcuySUUeORVb7ty7WXD0wkKJjQTMgg5yGrw9wn5iOl4ByCLHdUw",
    "expires_in": 600,
    "refresh_expires_in": 1800,
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxMjQyZjA4Ni04YTgyLTQ1NjAtYWI3My0wYWVhMTUzNDk0ZDYifQeyJleHAiOjE2NDAxMTYxMDksImlhdCI6MTY0MDExNDMwOSwianRpIjoiZDg1MGU2ZjAtOWY4My00M2ZjLThjZDktZTFjYWM3MzJkZWE1IddjkiiaXNzIjoiaHR0cHM6Ly9hdXRoLW5vbnByb2QuY29ubmVjdGluZy1leHBlcnRpc2UuY29tL2F1dGgvcmVhbG1zL2RldmVsb3AiLCJhdWQiOiJodHRwczovL2F1dGgtbm9ucHJvZC5jb25uZWN0aW5nLWV4cGVydGlzJKKIoZS5jb20vYXV0aC9yZWFsbXMvZGV2ZWxvcCIsInN1YiI6ImM0ZjEzYzU2LTc4ZmItNGNkYS04NzQ0LWJlZjNmOThlMTQ2ZSIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJzdXBwbGllclRlc3QiLCJzZXNzaW9uX3N0YXRlIjoiODNiNzdkYzQtYTIyMi00ZjkxLWFjMjAtZDJhMTdiN2I1NTRkIiwic2NvcGUiOiJwcm9maWxlIGVtYWlsIn0.pQtvnimnCeUXKvZcClMCZe9SWdkYRuRgcES2sQ10yzY",
    "token_type": "Bearer",
    "not-before-policy": 1638266634,
    "session_state": "83b77dc4-a222-4f91-ac20-d2a17b7b554d",
    "scope": "profile email"
}
Authentication environments

These are the urls you can use to obtain valid bearer tokens for your requests or {openApiEventMessageInbox}.

Purpose Environment Url

CE-OpenApi

development

https://auth-nonprod.connecting-expertise.com/realms/openapi-mars/protocol/openid-connect/token

production

https://auth.connecting-expertise.com/realms/openapi/protocol/openid-connect/token

CE-OpenApi EMI

development

https://auth-nonprod.connecting-expertise.com/realms/emi-mars/protocol/openid-connect/token

production

https://auth.connecting-expertise.com/realms/emi/protocol/openid-connect/token

Accessing a CE-OpenApi endpoint with a valid token

Every REST API request needs a valid bearer token (other option(s) are available, but we don’t promote them).
Without a valid token a request sent to the REST API will result in an authorization error.

When you use the token based authentication flow, your client sends HTTPS requests with the Authorization header that contains the word Bearer followed by a space and valid token.

Example: to authorize your application, your client should send:

Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJqb19wZC1HeHMxQUZscUhvNGUxMXo5Zm9sN083aFAzMVhjMS1fYmhabENRIn0eyJleHAiOjE2NDAxMTQ2MDksImlhdCI6MTY0MDExNDMwOSwianRpIjoiNTJhZGE5ZTQtNTQyZS00MTc2LWJiMWUtZGVlZDFmNzI2Y2Y3IiwiaXNzIjoiaHR0cHM6Ly9hdXRoLW5vbnByb2QuY29ubmVjdGluZy1leHBlcnRpc2UuY29tL2F1dGgvcmVhbG1zL2RldmVsb3AiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiYzRmMTNjNTYtNzhmYi00Y2RhLTg3NDQtYmVmM2Y5OGUxNDZlIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoic3VwcGxpZXJUZXN0Iiwic2Vzc2lvbl9zdGF0ZSI6IjgzYjc3ZGM0LWEyMjItNGY5MS1hYzIwLWQyYTE3YjdiNTU0ZCIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1kZXZlbG9wIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhcGlAY29udGluZ2VudC5jb20iLCJlbWFpbCI6FDFwaUBjb250aW5nZW50LmNvbSJ9eQacAr_tvEgHrIQpE5vzhp1yDXpv_QDviFWr6Rf2zWJD_mBFA12S25cu3qq8fZq9NtHpvg6nhQ2hbilHHLez3g3YiuZKu1ZG6pf9dwQ1w0TMOEDxIgWduMHt_g0r9YCCHmy3y1Af5rIeq3g8_uySQ1iSJy9IKWMeGaHfRBmrhaalu0UU5jzKy4vEXc81TDtDVMP2vdwJUwxoQTsHEcdw3Ul024qonxOcUHRCs1pIOiu2d_ViRgdf9P0DPiWfPdYuoheUJQHoTPTChuXYCXtjTRwLZAcuySUUeORVb7ty7WXD0wkKJjQTMgg5yGrw9wn5iOl4ByCLHdUw
...

Schematic representation:

Authentication OpenApi

Using refresh tokens

If an access token is expired, a new access token and refresh token pair can be obtained.

Acting "on behalf of"

Acting on behalf of allows a (middleware) application to authenticate on the CE-OpenApi with an "authentication user", and to perform the actual business actions "on behalf of a business user".

By using this pattern, the (middleware) application doesn’t need to know/use the actual business user credentials to authenticate in the CE-VMS. The (middleware) application authenticates by using it’s own credentials and adds the acting on behalf of information to the CE-OpenApi-call to communicate the actual business user to the CE-VMS.

Example

ActingOnBehalfOf

STEP 1

Create an ATS candidate

'Jean Dockx', an employee of supplier company 'Suppliers inc.', creates a Candidate in his own ATS system, called 'Suppliers inc. ATS'.

'Jean Dockx' is also registered as a CE-VMS user with:

  • Uuid: '47c3dd2c-a9b2-11ec-8857-525400c4a10a'

  • Username: 'jean.dockx@suppliers-inc.com'

  • Reference:

    • Source system = 'Suppliers inc. ATS'

    • external reference = 'JEAN_34J3K4JM_FH'

STEP 2

The middleware creates a C-E HumanResource

The middleware application uses our CE-OpenApi to create a CE-VMS HumanResource for the new 'Suppliers inc. ATS' Candidate.

Therefore, the middleware:

  • Authenticates with a CE-VMS authentication user ('api@suppliers-inc.com')

  • Creates a CE-VMS Human Resource on behalf of business user 'Jean Dockx' with:

    • Acting-On-Behalf-Of-External-User = 'JEAN_34J3K4JM_FH:Suppliers inc. ATS' Or

    • Acting-On-Behalf-Of-User = '47c3dd2c-a9b2-11ec-8857-525400c4a10a'

STEP 3

The outcome

A new CE-VMS HumanResource, created by user 'jean.dockx@suppliers-inc.com'.

How to use the "acting on behalf of" feature?

There are two options to communicate the acting on behalf of-business user to the CE-OpenApi:

  • Acting-On-Behalf-Of-User: refers to the uuid of the business user

  • Acting-On-Behalf-Of-External-User: refers to the external reference of the business user.

    • Layout:

externalReference:sourceSystem
Important
An authentication user can only act on behalf of a business user if it has been set up in the CE-VMS. If you would like to use this feature and/or adjust the setup, please contact us via {openapi@connecting-expertise.com}.

Connecting-Expertise OpenApi Event Message Inbox

In the CE-VMS events may occur. An event could be the publication of a request, the selection of a candidate, a timesheet that requires approval, …​

Let’s say that you’re interested in the Proposal selection process, and that you would like to be informed each time a selection step (=application event on a Proposal) has occurred.

One approach could be to use the Proposal history-endpoint in a recurring fashion. Check for example each hour if new events have occurred, and process them.
But our preferred solution is to subscribe to our CE-OpenApi EMI. Each CE-VMS application event is published to a message inbox. And you’ll be notified when a new message has been published.

Start using the CE-OpenApi EMI

To use the CE-OpenApi EMI, you’ll need to follow these steps:

STEP 1

Register your application
If you have an active user account on the CE-VMS, we can activate the CE-OpenApi EMI for you. Please contact us via openapi@connecting-expertise.com, and we’ll get back to you with your application’s client id and client secret.

STEP 2

Setup a consumer
From the moment we activate your CE-OpenApi EMI, every CE-VMS application event is stored as 1 unique message in your CE-OpenApi EMI-inbox. It’s up to you which messages you’re interested in: the entire CE-OpenApi EMI, or only a subset(s) of it.

STEP 3

Subscribe to your CE-OpenApi EMI
The CE-OpenApi EMI requires subscription with your dedicated CE-OpenApi EMI client id and client secret, and the usage of a filter to access your event messages.
Each subscription will result in 1 CE-OpenApi EMI subset (= a queue), and you decide how finely meshed your CE-OpenApi EMI subset(s) are.

Note
There are 3 possible filtering options:
- all messages
- all messages from 1 specific Application Context (e.g. PROPOSAL)
- all messages from 1 specific Application Event (e.g. CREATE)
STEP 4

Start processing event messages
Once we’ve activated your CE-OpenApi EMI account and you subscribed to (parts) of your CE-OpenApi EMI, we’ll start saving every application event occurrence as 1 unique event message.
Remark: we’ve adopted QoS 1 (at least once) semantics. While your client is permitted to request QoS 2 subscription, the adapter will only grant subscription up to QoS 1.

Important
We make a distinction between these environments for the CE-OpenApi EMI:
- CE-OpenApi EMI Development: emi-mars.connecting-expertise.com
- CE-OpenApi EMI Production: emi.connecting-expertise.com
Schematic representation: CE-OpenApi EMI usage

This schema shows you how to use the CE-OpenApi EMI:

Authentication OpenApiEventMessageInbox

Schematic representation of 2 subscriptions by 1 subscribing company

In this example, 1 company/application subscribed to 2 subsets (=2 queues) of the CE-OpenApi EMI. As a result each queue will contain certain messages, depending on the filter used during subscription.

EventMessageInbox

CE-OpenApi EMI filtering examples

Multiple filtering options are available, depending on your needs:

Scope Definition

All event messages

5b50e671-63dd-11ec-87e9-525400118a56 /#

All PROPOSAL event messages

5b50e671-63dd-11ec-87e9-525400118a56 /PROPOSAL/#

CREATE PROPOSAL event messages

5b50e671-63dd-11ec-87e9-525400118a56 /PROPOSAL/CREATE

TIP

For a list of all existing Application Context and Application Events, refer to Addendum "Event".

CE-OpenApi EMI settings

Durability

There are two options when you connect to the CE-OpenApi EMI:

  • Your client is transient and therefore receives transient (non-persistent) messages. This is default behaviour. Transient (QoS0) subscription use non-durable, auto-delete queues that will be deleted when your client disconnects.

  • You could however adopt a stateful client that uses durable subscriptions (non-clean sessions, QoS1). Durable (QoS1) subscriptions use durable queues.

Whether the queues are auto-deleted is controlled by the client’s clean session flag. Clients with clean sessions use auto-deleted queues, others use non-auto-deleted ones.

Limitation settings

We implemented following properties for your CE-OpenApi EMI:

  • If you don’t connect at least once every 96 hours, all messages will be deleted.

  • We store up to one million messages. If more messages are received they will be rejected.

  • You are able to use manual acknowledges to control the speed of reads from the queue (See documentation of your client).

  • If you are not acknowledging received messages, the connection will be closed after one minute.

Message example

When you receive a message, it will look like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
	"uuid": "b32890ac-7a04-4ed4-8784-001c6dab0517",  // (1)
	"context": "PROPOSAL",  // (2)
	"event": "EXECUTE_CUSTOM_ACTION",  // (3)
	"history": "ca5dca5c-90c1-44ac-8eaa-52540011eb54",  // (4)
	"additionalInfo": {  // (5)
		"customAction": {
			"uuid": "dd6dca7c-90c1-11ec-8eaa-525400118f99",
			"code": "SCREENING"
		}
	}
}
  1. identification of the message

  2. context of the message, see Application Context

  3. event related to the message, see Application Event

  4. combined with the context, you are able to use the related history endpoint to get additional information about the event. In this example, use the /proposals/{proposalId}/history endpoint. Additional information could contain for example remarks that a used added to the event.

  5. additional information will show extra info regarding the event. In this example the event is the execution of a custom action (EXECUTE_CUSTOM_ACTION), and the additionalInfo explains which custom action has been executed (SCREENING)

Setup examples

Python

This example is a subscription to all your CE-OpenApi EMI messages with direct grant access.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import paho.mqtt.client as mqtt
import time
import requests

connection_result_codes = {
	0: "Connection successful",
	1: "Connection refused - incorrect protocol version",
	2: "Connection refused - invalid client identifier",
	3: "Connection refused - server unavailable",
	4: "Connection refused - bad username or password",
	5: 'Connection refused - not authorised'
}

authorisation_request = requests.post(
	'https://auth-nonprod.connecting-expertise.com/realms/emi-mars/protocol/openid-connect/token',
	data = dict(
        grant_type = "password",
	    username = "eventmessageinbox@contingent.com", // (1)
	    password = "_ContingentIsTheWayToGo_", // (2)
	    client_id = "Xvz1evFS4wEEPTGEFPHBog_", // (3)
	    client_secret = "L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ66DRdyFHH_" // (4)
    )
)

open_id_token = authorisation_request.json()['access_token']


# Callback procedure when the client app receives a MQTT CONNACK response from the server

print(f"new token {open_id_token}")

def on_connection(client, userdata, flags, rc):
    print(f"{connection_result_codes[rc]} with code {rc} flags {flags} ")

    # Subscribing in on_connection() means that a connection interrupt and reconnection result in renewed subscriptions
    main_topic = "5b50e671-63dd-11ec-87e9-525400118a56/#" // (5)
    client.subscribe(main_topic)
    print(f"Subscribing to topic {main_topic}")


# Callback procedure when a PUBLISH message is received from the server

def on_message(client, userdata, msg):
    print("Incoming message: " + msg.topic + " " + str(msg.payload))

def on_disconnect(client, userdata, rc):
    if rc != 0:
        print(f"Unexpected disconnection. Result code {rc}")

def on_log(client, userdata, level, buf):
    print("Log: ", buf)

client = mqtt.Client(client_id="MQTTSupplierApplication1", protocol=mqtt.MQTTv31) // (6)

client.tls_set()
client.username_pw_set(
    username = "emi:eventmessageinbox@contingent.com", // (7)
	password = open_id_token
) # access_token response eyJhbGciOiJSUzI1NiIsInR5cC...
client.on_connection = on_connection
client.on_message = on_message
client.on_log=on_log
client.on_disconnect = on_disconnect

client.connect("emi-mars.connecting-expertise.com", {url_OpenApiEMI_Port}, 5)


# Blocking call that processes network traffic, dispatches callbacks and handles reconnecting.
# Other loop*() functions are available that give a threaded interface and a manual interface.
client.loop_start()
time.sleep(5)
client.loop_stop()
  1. Replace with your CE-OpenApi EMI username

  2. Replace with your CE-OpenApi EMI password

  3. Replace with your CE-OpenApi EMI client_id

  4. Replace with your CE-OpenApi EMI client_secret

  5. Replace with your CE-OpenApi company identification (uuid) and desired topic granularity

  6. Replace with your MQTT client_id, followed by a sequence counter (1-9). Example: MQTTSupplierApplication1

  7. Replace with [EnvironmentName]:[your CE-OpenApi EMI username]

Java

This example is a subscription to all your CE-OpenApi EMI messages with direct grant access.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import com.fasterxml.jackson.databind.ObjectMapper;
import kong.unirest.HttpResponse;
import kong.unirest.Unirest;
import org.eclipse.paho.client.mqttv3.IMqttClient;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class SubscriberMqtt {

    public static void main(String[] args) {

        class MqttMessageCallback implements MqttCallback {

            @Override
            public void connectionLost(Throwable throwable) {
                System.out.println("connection lost");
            }

            @Override
            public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
                System.out.println("message arrived callback");
                System.out.println("reply topic  : " + s);
                System.out.println("reply payload: " + mqttMessage.toString());
            }
        }

        try {

            // Request identity server (Keycloak) token
            // ----------------------------------------
            HttpResponse<String> httpResponse = Unirest.post("https://auth-nonprod.connecting-expertise.com/realms/emi-mars/protocol/openid-connect/token")
                .header("Content-Type", "application/x-www-form-urlencoded")
                .field("grant_type", "password")
                .field("username", "eventmessageinbox@contingent.com") // (1)
                .field("password", "_ContingentIsTheWayToGo_") // (2)
                .field("client_id", "Xvz1evFS4wEEPTGEFPHBog_") // (3)
                .field("client_secret", "L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ66DRdyFHH_") // (4)
                .asString();

            ObjectMapper objectMapper = new ObjectMapper();
            KeyCloak keyCloak = objectMapper.readValue(httpResponse.getBody(), KeyCloak.class);

            // Connect
            // -------
            MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
            mqttConnectOptions.setAutomaticReconnect(true);
            mqttConnectOptions.setCleanSession(false); // (5)
            mqttConnectOptions.setConnectionTimeout(10);
            mqttConnectOptions.setUserName("emi:eventmessageinbox@contingent.com"); // (6)
            mqttConnectOptions.setPassword(keyCloak.getAccess_token().toCharArray()); // password = bearerToken

            String mqttServerUri = "ssl://emi-mars.connecting-expertise.com";
            String mqttClientId = "Supplier_All_Messages"; // your event message subscription/queue name
            IMqttClient mqttClient = new MqttClient(mqttServerUri, mqttClientId);
            mqttClient.connect(mqttConnectOptions);

            // Subscribe to all messages in your event message inbox
            // -----------------------------------------------------
            String mqttTopic = "5b50e671-63dd-11ec-87e9-525400118a56/#"; // (7)

            subscriber.setCallback(new MqttMessageCallback());
            subscriber.subscribe(mqttTopic);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  1. Replace with your CE-OpenApi EMI username

  2. Replace with your CE-OpenApi EMI password

  3. Replace with your CE-OpenApi EMI client_id

  4. Replace with your CE-OpenApi EMI client_secret

  5. With the clean session flag set to false, you choose a Durable (QoS1) subscription, and thus use durable queues.

  6. Replace with [EnvironmentName]:[your CE-OpenApi EMI username]

  7. Replace with your CE-OpenApi company identification (uuid) and desired topic granularity

Response outcome

If everything goes according to plan, the CE-OpenApi will return a '200' feedback code.

Whenever something goes wrong, the error will look like this (example for Not found error):

{
  "type": "/doc/v1/errors#NF001",
  "title": "Resource not found",
  "status": 404,
  "identifier": "e21ce68e-9e0b-45ba-9425-beb061b24e33",
  "code": "NF001",
  "extraInfo": {
    "cityId": [
      {
        "code": "VE010",
        "message": "Given ID does not exist",
        "parameters": {}
      }
    ]
  }
}
Note
Check out addendum Addendum "Response outcome feedback codes" for more information regarding possible feedback codes.
Check out addendum Addendum "Response outcome error codes" for more information regarding possible error codes.

Time format

There is no date format in JSON, there’s only strings to map to date values. We chose https://en.wikipedia.org/wiki/ISO_8601, to be the de facto standard.

We will accept 3 different date/time formats:

  1. A date and a time with a timezone. This is the most preferred method, because it excludes discussion and assumption.

  2. A date without a time. This will never include a time zone.

  3. A date and time without a timezone. We accept that some external parties will use this format. It is important to realize that we will never make an assumption about the time zone. Therefore, this is the least preferred method.

Caution
Although valid, something like "20210714T100320Z" should not be used. Always use dashes and colons as separators: 2021-07-14T10:03:20Z
Note
A decimal fraction may be added after the seconds. Use a dot as a separator and a maximum of 9 digits in the fractional second portion: 2021-07-14T10:03:20.4875Z

Examples

A date and a time with a timezone

2020-10-13T07:28:20+02:00

Time with fraction:

2020-10-13T07:28:20.123456789+02:00

UTC (Coordinated Universal Time, see also https://en.wikipedia.org/wiki/Coordinated_Universal_Time) can be expressed as:

2020-10-14T10:03:20Z
2020-10-14T10:03:20+00:00

A date without a time

E.g. date of birth, license valid from,…​

2020-10-14 Only one format for this case can be used.

A date and time without a timezone

E.g. Christmas at noon:

2020-12-25T12:00:00

Should be handled by the backend as a timestamp without timezone. No assumption about timezone will be made.

Caution
A date and time without a timezone should be used with care!

Document handling

Some objects have a document-feature. You can attach for example a CV to a Proposal, or a certificate to a Human Resource.

If you would like to attach a document to an object:

STEP 1

Upload your document

If you want to attach a document to an object, you need to upload it first. After a successful upload, we’ll return a unique identification of the document.

Use service /documents/base64 or /documents/binary to upload a new document. This will upload your document to a temporary folder. You still need to link it to a desired object (for example a Request or Proposal) with a separate service.

HTTPS Example

POST /connectingExpertise/OpenApi/v1/documents HTTP/1.1

Host:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

Authorization: Basic "your authorisation credentials come here"==

Content-Length: 182
----WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name="file"; filename="test.png"

Content-Type: image/png
(data)
STEP 2

Link your document

Step 2 is creating a link between your document (using the unique identification of the document) and the object (Proposal, Human Resource,…​).

Important
Uploaded documents remain available for 24 hours to create a link with an object. If you don’t create a link with an object within the first 24 hours after the upload, your document will be automatically deleted.

Proposal definition

What about the building blocks?

A Proposal consists of several building blocks:

  1. Proposal core

  2. Customer specific fields (optional)

  3. Documents

  4. Skills (optional)

We’ll discuss these building blocks in the next paragraphs.

Proposal core

The foundation and thus the most important building block is the proposal core. This building block contains essential information about a proposal, like a link to a Human Resource., a base rate,…​

Important
When you create a Proposal you’ll have to add an Assignment type.
Follow these steps to determine a valid Assignment type :
- First of all you must use this endpoint to get all applicable Assignment types for a given Received request:
/receivedrequests/{receivedRequestId}/assignmenttypesforproposal
- Then you choose one of the allowed Assignment types for a Proposal for your Proposal creation.
Customer specific fields

Each Proposal is related to a Request. Each Request is published by a Customer. And each Customer can decide to use one or more customer specific fields.
If a Customer adds customer specific fields to the Proposal-setup, you will need to take them into account, especially the mandatory fields. To determine which Custom fields to use for a given Proposal, see Proposal business rules.

Applicable proposal custom fields
/proposals/{proposalId}/applicablecustomfields

The Proposal-building block Custom field has a specific format, depending on the Customer setup. When you create a new Proposal, the first step before adding custom fields, is determining which custom fields are allowed and which format you have to respect.
You can use the /proposals/{ proposalId }/applicablecustomfields-endpoint to gain insight for the Proposal custom field -definition.

The Proposal-building block 'Custom field' contains 1 or multiple Custom field group(s), and each Proposal custom field group consists of 1 or more Custom fields. The customer setup determines for each group the maximum number of recurrences (1-M).

Documents

You can attach one or more documents (like a cv) to a Proposal.

Important
It depends on the customer setup, but most of the time at least one document will be mandatory.
Skills

If a Customer defines skills on a Request, you need to respond to each one of them, because each Request skill is mandatory.

Proposal definition example

ProposalPublication ProposalComposition

In this example:

  1. the Proposal-building block Custom field consists of 2 Custom field groups (the default group and 'Profile').

  2. The default group has always only 1 recurrence. This recurrence consists of 2 Custom fields ('Number of days' and 'Worker type').

  3. The 'Profile' group has up to 5 recurrences. Each recurrence consists of 2 Custom fields ('Profile' and 'Positions').

Proposal creation

If you decide to respond to a Customer Request (=Received Request) you will have to:

  1. create a Proposal,

  2. accept the contractual conditions (if required by the Requests Customer setup)

  3. and finally publish your Proposal

Putting all building blocks together

When you create a new Proposal, you need to start with the Proposal core. After a successful creation of the core, you can add other building blocks, with respect the Customer setup.

Each building block has business rules that your Proposal must comply with. Failing one or more business rules will prevent the creation of the building block.

Example JSON payload for 'Proposal core' creation

{
  "request": "0a0d6f9e-057d-11ec-87e9-525400118a56",
  "firstName": "Anne",    (1)
  "lastName": "Boleyn",   (2)
  "startDate": "2021-10-18T12:29:54.424Z",
  "assignmentType": "2856ae8a-2ad1-11e9-8542-5254006fc9a6",
  "baseRate": 750,
  "currency": "4c34b815-fc03-11eb-87e9-525400118a56",
  "coefficient": 1,   (3)
  "remark": "Very good candidate with loads of experience!",
  "humanResource": "36406ca9-fcd5-493f-8ddc-afea057074f9",
  "isSupplierAllowedToRepresentHumanResource": true
}
  1. Optional, because already defined by the linked Human Resource.

  2. Optional, because already defined by the linked Human Resource.

  3. The "baseRate" will be multiplied by this "coefficient" to determine the final "rate" of the Proposal.

Example JSON payload for 'Proposal customer specific fields' creation

{
  "groups": [{
      "group": "6318ce18-1136-4c10-b5b7-a19bd790cf2c",
      "recurrences": [{
          "customFields": [{
              "customField": "3bd25446-dcc9-47cd-9207-8288e44b28d1",
              "value": "true"
          },
          {
              "customField": "018fc0fd-e947-4e3f-8fd3-d85b24c61caa",
              "value": "5"
          }]
      },
      {
          "customFields": [{
              "customField": "3bd25446-dcc9-47cd-9207-8288e44b28d1",
              "value": "false"
              },
              {
              "customField": "018fc0fd-e947-4e3f-8fd3-d85b24c61caa",
              "value": "4"
              }
          ]
      }]
  },
  {
      "group": "bb159c60-9a41-4143-9466-bb60ae772db0",
      "recurrences": [{
        "customFields": [{
          "customField": "416e26a1-9fa9-42aa-a2eb-d46805d0907b",
          "value": "9e541c8c-495c-4af6-ae5d-98d0d47b744d"
        }]
      }]
  }]
}

Example JSON payload for 'Proposal document' creation

{
  "document": "60205f16-c64f-4813-a31f-c1cb34c4d910"    (1)
}
  1. Id of an already uploaded document.

Example JSON payload for 1 'Proposal skill' creation

{
  "requestSkill": "0a0d6f9e-057d-11ec-87e9-525400118a34",  (1)
  "experienceLevel": "9d34b815-fc03-11eb-87e9-525400118c77",
  "value": "5"
}
  1. Refers to a Request skill.

Accept general terms and conditions

The customer setup can require the acceptance of contractual conditions (='general terms and conditions') for Marketplace requests. These conditions are included in a Request as contractualCondition and an array of contractualDocuments.
A necessary step before you can publish a Proposal when acceptance of those conditions is required, is a formal acceptance. Not accepting them will prevent the publication of a Proposal.

We refer to endpoint: /proposal/{propoaslId}/accepttermsandconditions

Publish a proposal

Finally, when you are confident about your Proposal, you publish it to the Customer. As long as you didn’t publish your Proposal, it won’t be visible/accessible for the Customer.

Proposal business rules

A consequence of the fact that each Customer setup is unique, is that the business logic that applies to a Proposal may vary per Customer.
The Customer setup determines which standard fields are used, if they are mandatory or not, if customer specific fields are used and so on…​
Like each building block, the publication process has a number of business rules that you must comply with. Failing one or more business rules will cause failure of the publication process.

Connecting-Expertise OpenApi Method Details

We’ve teamed up with SwaggerHub to provide you with an interactive manual through a REST console:

We support multiple environments for the CE-OpenApi:

The CE-OpenApi includes the following top-level areas:

Generic

The CE-OpenApi contains a number of generic services. The relate to master data (companies, cities, countries, currencies, departments, users, …​), document handling, picklists, …​

Received request

A Request is a very important object in our CE-VMS. A company can capture the need for contingent workforce in a Request. Such a Request will be published to (preferred) suppliers and/or the marketplace. This section describes the services to manage Requests. Keep in mind that the resulting data set may differ from one Request to another as each customer has the possibility to decide which fields will to be included, and which fields are shared with the supplier community.

Human Resource

As a result of the selection process, requests will be assigned to individuals or teams. Individuals are called Human Resource.
If you want to know what you can do with this Human Resource-object, this section is the place to look for it.

Proposal

When a company (a supplier) wants to respond to a Request, they can create a Proposal. Proposals will be subjected to a selection process performed by the customer.

Addendum

Addendum "Response outcome feedback codes"

These are the possible CE-OpenApi feedback codes.

Status Error code Description

[200] Successfully operation

[400] Bad request

BR001

Validation error

BR002

JSON

BR003

JSON mapping

BR004

JSON processing

BR005

Invalid format

BR006

JSON parse

BR007

Query param

BR008

Timestamp format

BR009

Header param

BR010

Path param

BR011

Cookie param

BR012

Form param

BR013

Matrix param

BR014

Malformed header

[401] Unauthorized

UA001

Not authorized

[403] Forbidden errors

FB001

Forbidden

FB002

Cors

[404] Not found errors

NF001

Resource

NF002

Endpoint

[406] Not acceptable

AC001

Not acceptable

[415] Unsupported media type

UM001

Not supported

[500]Internal server error

SE001

Illegal state

SE002

Search failed

SE003

Create failed

SE004

Modification failed

SE005

Delete failed

SE006

Illegal db state

SE007

Null pointer

SE008

Method not found

SE009

Transaction rolled back

SE010

Illegal argument

SE011

Generic

SE012

Header value

SE013

Unknown response error

SE014

Unknown

Addendum "Response outcome error codes"

If an error is raised as a result of a service call, the extraInfo tag will contain additional information about the occurred error.

Error code Description

VE000

empty

VE001

missing_required_value

VE002

no_string

VE003

no_double

VE004

no_long

VE005

invalid_date

VE006

missing_default_data

VE007

no_boolean

VE008

invalid_format

VE009

no_number

VE010

wrong_id

VE011

invalid_option

VE012

size_issue

VE013

incorrect_type

VE014

max_length_issue

VE015

invalid_json

VE016

empty_string

VE017

no_list

VE018

missing_values_in_list

VE019

invalid_database_option

VE020

not_unique

VE021

invalid_state_transition

VE022

invalid_email

VE023

is_connected

VE024

invalid_swagger

VE025

invalid_swagger_url

VE026

swagger_unreachable

VE027

no_integer

VE028

no_short

Addendum "Event"

ApplicationContext ApplicationEvent ApplicationEventContext

PROPOSAL

CREATE

PROPOSAL

UPDATE

PROPOSAL

PUBLISH

PROPOSAL

UNDO_PUBLISH

PROPOSAL

CANCEL

PROPOSAL

RETURN

PROPOSAL

LONGLIST

PROPOSAL

UNDO_LONGLIST

PROPOSAL

SHORTLIST

PROPOSAL

UNDO_SHORTLIST

PROPOSAL

SELECT

PROPOSAL

UNDO_SELECT

PROPOSAL

CONFIRM

PROPOSAL

UNDO_CONFIRM

PROPOSAL

REJECT

PROPOSAL

UNDO_REJECT

PROPOSAL

SEND_EMAIL

PROPOSAL

NOSHOW

PROPOSAL

REPLACE

PROPOSAL

DELETE_CUSTOM_ACTION

PROPOSAL

EXECUTE_CUSTOM_ACTION

PROPOSAL

ANONYMIZE

SUPPLIER_REQUEST

CREATE

SUPPLIER_REQUEST

UPDATE

CANCEL

SUPPLIER_REQUEST

UPDATE

ONHOLD

SUPPLIER_REQUEST

UPDATE

POSITIONS

SUPPLIER_REQUEST

UPDATE

PROLONG

SUPPLIER_REQUEST

UPDATE

RESPONSE_DATE

SUPPLIER_REQUEST

UPDATE

SPLIT

SUPPLIER_REQUEST

UPDATE

UNDO_CANCEL

SUPPLIER_REQUEST

UPDATE

UNDO_ONHOLD

SUPPLIER_REQUEST

CLOSE

SUPPLIER_REQUEST

CLOSE

PROLONG

Revisions

Version Date Changed by Description

1.0.0

March 20, 2022

SB

Release 1.0.0

1.1.0

March 31, 2022

SB

Release 1.1.0

1.2.0

May 03, 2022

SB

Release 1.2.0

1.3.0

May 20, 2022

SB

Release 1.3.0

1.4.0

June 10, 2022

SB

Release 1.4.0

1.5.0

July 28, 2022

SB

Release 1.5.0

1.6.0

October 14, 2022

SB

Release 1.6.0

1.7.0

November 2, 2022

SB

Release 1.7.0

1.8.0

December 1, 2022

SB

Release 1.8.0

1.9.0

February 15, 2023

SB

Release 1.9.0

1.10.0

March 10, 2023

SB

Release 1.10.0

1.11.0

March 24, 2023

SB

Release 1.11.0

Release 1.0.0

Initial release

Release 1.1.0

Adjustment of urls.

Release 1.2.0

Endpoint /receivedrequests/{receivedRequestId}/history

An additional attribute has been added: applicationEventContext. This attributes stands for additional information about an applicationEvent.

Example: if the applicationEvent is 'UPDATE', applicationEventContext could be 'CANCEL', 'ONHOLD', 'POSITIONS', 'PROLONG', 'RESPONSE_DATE', …​

Note
Check out the applicationEvent list in addendum Event
Additional events for the CE-OpenApi EMI

When a Request event is triggered by a customer action and therefore registered as a Request History-entry, it will also be registered for each supplier who received the Request (= ReceivedRequest). A supplier who subscribed to the CE-OpenApi EMI will receive event messages. For a complete list of application events, see addendum "Event".

Endpoint "/proposals/"

In some cases the Proposal-list contained duplicates. This has been fixed.

Acting "on behalf of"

Acting on behalf of allows a (middleware) application to authenticate on the CE-OpenApi with an authentication user, and to perform the actual business actions on behalf of a business user.

Invoicing companies: /companies/{companyId}/allowedinvoicingcompanies

When creating a new department or updating an existing one in the CE-VMS, you can define an Invoicing company. Invoices that are created for timesheets linked to a certain department, will be addressed to the invoicing company instead of the company of the department itself.

You can use this new endpoint to retrieve allowed invoicing companies for a given company

Release 1.3.0

Events in the CE-OpenApi EMI

CE-OpenApi EMI messages are triggered for every relevant event on a Request.

A durable CE-OpenApi EMI

In this release we added the possibility to use durable MQTT queues. See CE-OpenApi EMI settings - section Durability.

Master data management: department

Added functionality to add/update/delete:

  • Department

  • DepartmentAssignmentType

  • DepartmentExternalReference

  • DepartmentAssignmentCategory

  • DepartmentCostCenter

  • DepartmentMotive

  • DepartmentLocation

  • DepartmentRequestTemplate

Remark: when a new department is created, linked data elements will be copied from the parent department. It’s highly recommended respecting this approach. However, you can avoid this behaviour by adding the hasCopyFromParent = 'false' parameter to the payload.

1.4.0

Belgian Human Resource

When creating a Belgian Human Resource, we’ve implemented business logic to validate the social security number. The logic takes into account regular numbers as well as bis numbers. For additional information about a Belgian social security number, see belgianIDpro.

Proposal history

The 'Proposal History'-endpoint has been expanded with Custom Action information.

ProposalHistoryEndpoint

To retrieve a specific CustomAction object from a Proposal, use this endpoint:

/proposals/{proposalId}/customactions/{proposalCustomActionId}

Attention: the resourceUri can change. If a ProposalCustomAction has been deleted, the resourceUri will refer to a CustomAction. Otherwise, it will refer to a ProposalCustomAction-object.

Master data management: department property inheritance

When a new department is created, all linked data elements will be copied from the parent department. We’ve added the last few linked objects (AssignmentSettings, PriceAgreementSettings and ServiceProviderPriceAgreementSettings).

CE-OpenApi EMI contains source information

When you receive a new CE-OpenApi EMI message, it will contain information about the source of the message. See CE-OpenApi EMI Settings - Message example.

Proposal decision

When a Proposal is processed by a customer, a decision will be made: a candidate can be selected or rejected. Information about this decision process is stored in a ProposalDecision-object, and can be retrieved via this endpoint:

/proposals/{proposalId}/decisions

1.5.0

Filter proposals

The endpoint to retrieve Proposals has been altered: you can now filter on active/nonactive Proposals

/proposals
User management

We have added a number of endpoints for user management - Users - User roles - External references for users

1.6.0

Notifications

We’ve added a notification application to our CE-OpenApi stack. This means that in case of events, a notification will be sent to users. It’s the same approach as the CE-VMS.

We’ve also integrated Mailchimp. This platform is used for marketing communication as well as for CE-VMS related messages (release notes, planned downtime,…​).

Authentication server

We’ve update our authentication server (keycloack) to the latest version for security reasons.

User management

We have extended the user management endpoints:

  • We’ve implemented a user deactivation flow (periodically for GDPR as well as manually by a system administrator)

  • We’ve implemented a user password change flow in our authentication server

1.7.0

Acceptance of general terms and conditions

The customer setup can require the acceptance of contractual conditions (='general terms and conditions') for Marketplace requests. These conditions are included in a Request as contractualCondition and an array of contractualDocuments.
A necessary step before you can publish a Proposal when acceptance of those conditions is required, is a formal acceptance. Not accepting them will prevent the publication of a Proposal.

Before this release the acceptance of those conditions were done once per Request. Due to a change in legislation those conditions for marketplace requests have to be formally accepted for each Proposal.

Therefor endpoint /receivedrequests/{receivedRequestId}/accepttermsandconditions has been replaced by a new endpoint: /proposal/{proposalId}/accepttermsandconditions

1.8.0

Only technical improvements

1.9.0

Functional changes
  • The determination of company type has been altered

  • Major refactoring of code/softwareCode/(display)name + HAL standard reference links fixed for all dataElements.

Features

We made it possible to link multiple CostCenters to Assignments.

We’ve added an additional filter on receivedRequestId for /proposals endpoints.

Because the number of price agreements can be pretty high, we’ve created separate endpoints for PriceAgreements on ReceivedRequest and Assignment, including pagination.

We’ve added Assignment endpoints.

Bug fixes
  • Fixed /proposals/{proposalId}/properties/documentsallowed endpoint.

  • Fixed /proposals/properties/applicablegenericfields endpoint.

  • Request/Proposal/AssignmentExternalStatus name value changes.

  • SubscriptionType name value changes.

  • PriceAgreement 'impactOnProposal' value changes.

  • Field 'additionalRequestInformation' for endpoint /proposals/{proposalId} changed to 'additionalInformationByCustomer'.

  • User create fix.

  • Added uniqueness check for AssignmentAccessScope and AssignmentAccessSupplierDepartment.

  • Added department link to AssignmentAccessSettingScope endpoints.

  • Acceptation of conditions changed from SupplierRequest to Proposal.

1.10.0

Functional changes

We’ve removed deprecated permissions. This doesn’t affect the current endpoints, but is preparation for next phases.

Features

We’ve added additional business rules to proposal endpoints

The endpoint with customActions to view applicable actions for a proposal has been added.

1.11.0

Functional changes

We’re adding UI related endpoints (not available in our Connecting-Expertise OpenApi) (thus for internal use only).

We’ve added additional attributes to proposal endpoints (e.g. ReceivedRequest, isVatApplicable,…​).

Features

You can now execute and delete (if allowed) a Proposal custom action.

You can now use Timesheet related endpoints