Fluent Commerce Logo
Docs

commercetools Prerequisites & Project Configuration

Essential knowledge

Changed on:

30 July 2025

Overview

This page covers how to configure the appropriate settings in the commercetools the commercetools system i.e.: custom fields, channels, etc. so that syncing can be enabled between it and the Fluent Commerce system.

Key points

  • Custom fields are required for Orders, Order Line Items, Delivery, Channels, and Parcels, with specific field names provided.
  • Project configuration files include application-connector.yml, application.yml, bootstrap.yml, and logback-spring.xml for different settings and environments.
  • Route mappings are used to map incoming messages to handlers, with examples provided for configuration.
  • Listeners manage different types of queues, including batch jobs, internal messages, notifications, and commercetools events.
  • Detailed configuration examples and instructions are available for customizing routes, handlers, and Fluent account mappings.

Prerequisites

Custom fields will be required for the following areas:
  • Order
  • Order Line Item
  • Delivery
  • Channels
Order
  • Group key name: Fluent Custom Field
  • Field name: Pickup Location Ref
No alt provided
Order Line Item
  • Group key name : Fluent Fulfilment Metadata
  • Field name : Fulfilment Metadata
Delivery
  • Group key name : Fluent Consignment
  • Field name : Fluent Consignment Ref
  • Fluent Consignment Status
Order Parcel
  • Group key name : Fluent Article
  • Field name : Fluent Tracking Url
Channels
  • Group key name: Fluent Store Details
  • Fields name:
  • Type
  • Status
  • Email
  • Phone No.
  • Latitude
  • Longitude
  • Timezone
  • Opening Schedule
  • Attributes
commercetools Custom field collection
1    {
2    "info": {
3    "_postman_id": "a194556c-159f-4810-80a0-84776857dbae",
4    "name": "CT Custom Fields",
5    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
6    "_exporter_id": "21544403"
7    },
8    "item": [
9    {
10    "name": "Create  Order custom field",
11    "event": [
12    {
13    "listen": "test",
14    "script": {
15    "exec": [
16    "tests[\"Status code \" + responseCode.code] = responseCode.code === 200 || responseCode.code === 201;",
17    "var data = JSON.parse(responseBody);",
18    "if(data.results && data.results[0] && data.results[0].id && data.results[0].version){",
19    "    pm.environment.set(\"type-id\", data.results[0].id); ",
20    "    pm.environment.set(\"type-version\", data.results[0].version);",
21    "}",
22    "if(data.results && data.results[0] && data.results[0].key){",
23    "    pm.environment.set(\"type-key\", data.results[0].key); ",
24    "}",
25    "if(data.version){",
26    "    pm.environment.set(\"type-version\", data.version);",
27    "}",
28    "if(data.id){",
29    "    pm.environment.set(\"type-id\", data.id); ",
30    "}",
31    "if(data.key){",
32    "    pm.environment.set(\"type-key\", data.key);",
33    "}",
34    ""
35    ],
36    "type": "text/javascript"
37    }
38    }
39    ],
40    "request": {
41    "auth": {
42    "type": "oauth2",
43    "oauth2": [
44    {
45    "key": "accessToken",
46    "value": "{{ctp_access_token}}",
47    "type": "string"
48    },
49    {
50    "key": "addTokenTo",
51    "value": "header",
52    "type": "string"
53    },
54    {
55    "key": "tokenType",
56    "value": "Bearer",
57    "type": "string"
58    }
59    ]
60    },
61    "method": "POST",
62    "header": [
63    {
64    "key": "Content-Type",
65    "value": "application/json"
66    }
67    ],
68    "body": {
69    "mode": "raw",
70    "raw": "{\n  \"key\" : \"flOrderCustomField\",\n  \"name\" : {\n    \"en\" : \"Fluent Custom Field\"\n  },\n  \"description\" : {\n    \"en\" : \"Fluent Custom Field\"\n  },\n  \"resourceTypeIds\" : [ \"order\" ],\n  \"fieldDefinitions\" : [ {\n    \"name\" : \"flPickupLocationRef\",\n    \"label\" : {\n      \"en\" : \"Pickup Location Ref\"\n    },\n    \"required\" : false,\n    \"type\" : {\n      \"name\" : \"String\"\n    },\n    \"inputHint\" : \"SingleLine\"\n  } ]\n}"
71    },
72    "url": {
73    "raw": "{{host}}/{{project-key}}/types",
74    "host": [
75    "{{host}}"
76    ],
77    "path": [
78    "{{project-key}}",
79    "types"
80    ],
81    "query": [
82    {
83    "key": "expand",
84    "value": "",
85    "disabled": true
86    }
87    ]
88    }
89    },
90    "response": []
91    },
92    {
93    "name": "Create Lineitems custom fields",
94    "event": [
95    {
96    "listen": "test",
97    "script": {
98    "exec": [
99    "tests[\"Status code \" + responseCode.code] = responseCode.code === 200 || responseCode.code === 201;",
100    "var data = JSON.parse(responseBody);",
101    "if(data.results && data.results[0] && data.results[0].id && data.results[0].version){",
102    "    pm.environment.set(\"type-id\", data.results[0].id); ",
103    "    pm.environment.set(\"type-version\", data.results[0].version);",
104    "}",
105    "if(data.results && data.results[0] && data.results[0].key){",
106    "    pm.environment.set(\"type-key\", data.results[0].key); ",
107    "}",
108    "if(data.version){",
109    "    pm.environment.set(\"type-version\", data.version);",
110    "}",
111    "if(data.id){",
112    "    pm.environment.set(\"type-id\", data.id); ",
113    "}",
114    "if(data.key){",
115    "    pm.environment.set(\"type-key\", data.key);",
116    "}",
117    ""
118    ],
119    "type": "text/javascript"
120    }
121    }
122    ],
123    "request": {
124    "auth": {
125    "type": "oauth2",
126    "oauth2": [
127    {
128    "key": "accessToken",
129    "value": "{{ctp_access_token}}",
130    "type": "string"
131    },
132    {
133    "key": "addTokenTo",
134    "value": "header",
135    "type": "string"
136    },
137    {
138    "key": "tokenType",
139    "value": "Bearer",
140    "type": "string"
141    }
142    ]
143    },
144    "method": "POST",
145    "header": [
146    {
147    "key": "Content-Type",
148    "value": "application/json"
149    }
150    ],
151    "body": {
152    "mode": "raw",
153    "raw": "{\n  \"key\" : \"flFulfilment\",\n  \"name\" : {\n    \"en\" : \"Fluent Fulfilment Metadata\"\n  },\n  \"description\" : {\n    \"en\" : \"Fluent Fulfilment Metadata\"\n  },\n  \"resourceTypeIds\" : [ \"line-item\" ],\n  \"fieldDefinitions\" : [ {\n    \"name\" : \"flFulfilmentMetadata\",\n    \"label\" : {\n      \"en\" : \"Fulfilment Metadata\"\n    },\n    \"required\" : false,\n    \"type\" : {\n      \"name\" : \"String\"\n    },\n    \"inputHint\" : \"SingleLine\"\n  } ]\n}"
154    },
155    "url": {
156    "raw": "{{host}}/{{project-key}}/types",
157    "host": [
158    "{{host}}"
159    ],
160    "path": [
161    "{{project-key}}",
162    "types"
163    ],
164    "query": [
165    {
166    "key": "expand",
167    "value": "",
168    "disabled": true
169    }
170    ]
171    }
172    },
173    "response": []
174    },
175    {
176    "name": "Create Delivery custom fields",
177    "event": [
178    {
179    "listen": "test",
180    "script": {
181    "exec": [
182    "tests[\"Status code \" + responseCode.code] = responseCode.code === 200 || responseCode.code === 201;",
183    "var data = JSON.parse(responseBody);",
184    "if(data.results && data.results[0] && data.results[0].id && data.results[0].version){",
185    "    pm.environment.set(\"type-id\", data.results[0].id); ",
186    "    pm.environment.set(\"type-version\", data.results[0].version);",
187    "}",
188    "if(data.results && data.results[0] && data.results[0].key){",
189    "    pm.environment.set(\"type-key\", data.results[0].key); ",
190    "}",
191    "if(data.version){",
192    "    pm.environment.set(\"type-version\", data.version);",
193    "}",
194    "if(data.id){",
195    "    pm.environment.set(\"type-id\", data.id); ",
196    "}",
197    "if(data.key){",
198    "    pm.environment.set(\"type-key\", data.key);",
199    "}",
200    ""
201    ],
202    "type": "text/javascript"
203    }
204    }
205    ],
206    "request": {
207    "auth": {
208    "type": "oauth2",
209    "oauth2": [
210    {
211    "key": "accessToken",
212    "value": "{{ctp_access_token}}",
213    "type": "string"
214    },
215    {
216    "key": "addTokenTo",
217    "value": "header",
218    "type": "string"
219    },
220    {
221    "key": "tokenType",
222    "value": "Bearer",
223    "type": "string"
224    }
225    ]
226    },
227    "method": "POST",
228    "header": [
229    {
230    "key": "Content-Type",
231    "value": "application/json"
232    }
233    ],
234    "body": {
235    "mode": "raw",
236    "raw": "{\n    \"key\": \"flConsignment\",\n            \"name\": {\n                \"en\": \"Fluent Consignment\"\n            },\n            \"description\": {\n                \"en\": \"Fluent Consignment\"\n            },\n            \"resourceTypeIds\": [\n                \"order-delivery\"\n            ],\n            \"fieldDefinitions\": [\n                {\n                    \"name\": \"flConsignmentRef\",\n                    \"label\": {\n                        \"en\": \"Fluent Consignment Ref\"\n                    },\n                    \"required\": false,\n                    \"type\": {\n                        \"name\": \"String\"\n                    },\n                    \"inputHint\": \"SingleLine\"\n                },\n                {\n                    \"name\": \"flConsignmentStatus\",\n                    \"label\": {\n                        \"en\": \"Fluent Consignment Status\"\n                    },\n                    \"required\": false,\n                    \"type\": {\n                        \"name\": \"String\"\n                    },\n                    \"inputHint\": \"SingleLine\"\n                }\n            ]\n        }"
237    },
238    "url": {
239    "raw": "{{host}}/{{project-key}}/types",
240    "host": [
241    "{{host}}"
242    ],
243    "path": [
244    "{{project-key}}",
245    "types"
246    ],
247    "query": [
248    {
249    "key": "expand",
250    "value": "",
251    "disabled": true
252    }
253    ]
254    }
255    },
256    "response": []
257    },
258    {
259    "name": "Create Parcel custom fields",
260    "event": [
261    {
262    "listen": "test",
263    "script": {
264    "exec": [
265    "tests[\"Status code \" + responseCode.code] = responseCode.code === 200 || responseCode.code === 201;",
266    "var data = JSON.parse(responseBody);",
267    "if(data.results && data.results[0] && data.results[0].id && data.results[0].version){",
268    "    pm.environment.set(\"type-id\", data.results[0].id); ",
269    "    pm.environment.set(\"type-version\", data.results[0].version);",
270    "}",
271    "if(data.results && data.results[0] && data.results[0].key){",
272    "    pm.environment.set(\"type-key\", data.results[0].key); ",
273    "}",
274    "if(data.version){",
275    "    pm.environment.set(\"type-version\", data.version);",
276    "}",
277    "if(data.id){",
278    "    pm.environment.set(\"type-id\", data.id); ",
279    "}",
280    "if(data.key){",
281    "    pm.environment.set(\"type-key\", data.key);",
282    "}",
283    ""
284    ],
285    "type": "text/javascript"
286    }
287    }
288    ],
289    "request": {
290    "auth": {
291    "type": "oauth2",
292    "oauth2": [
293    {
294    "key": "accessToken",
295    "value": "{{ctp_access_token}}",
296    "type": "string"
297    },
298    {
299    "key": "addTokenTo",
300    "value": "header",
301    "type": "string"
302    },
303    {
304    "key": "tokenType",
305    "value": "Bearer",
306    "type": "string"
307    }
308    ]
309    },
310    "method": "POST",
311    "header": [
312    {
313    "key": "Content-Type",
314    "value": "application/json"
315    }
316    ],
317    "body": {
318    "mode": "raw",
319    "raw": "{\n    \"key\": \"fluentarticle\",\n    \"name\": {\n        \"en\": \"Fluent Article\"\n    },\n    \"description\": {\n        \"en\": \"Fluent Article\"\n    },\n    \"resourceTypeIds\": [\n        \"order-parcel\"\n    ],\n    \"fieldDefinitions\": [\n        {\n            \"name\": \"trackingUrl\",\n            \"label\": {\n                \"en\": \"Fluent Tracking Url\"\n            },\n            \"required\": false,\n            \"type\": {\n                \"name\": \"String\"\n            },\n            \"inputHint\": \"SingleLine\"\n        }\n    ]\n}"
320    },
321    "url": {
322    "raw": "{{host}}/{{project-key}}/types",
323    "host": [
324    "{{host}}"
325    ],
326    "path": [
327    "{{project-key}}",
328    "types"
329    ],
330    "query": [
331    {
332    "key": "expand",
333    "value": "",
334    "disabled": true
335    }
336    ]
337    }
338    },
339    "response": []
340    },
341    {
342    "name": "Create  Channel custom fields",
343    "event": [
344    {
345    "listen": "test",
346    "script": {
347    "exec": [
348    "tests[\"Status code \" + responseCode.code] = responseCode.code === 200 || responseCode.code === 201;",
349    "var data = JSON.parse(responseBody);",
350    "if(data.results && data.results[0] && data.results[0].id && data.results[0].version){",
351    "    pm.environment.set(\"type-id\", data.results[0].id); ",
352    "    pm.environment.set(\"type-version\", data.results[0].version);",
353    "    pm.environment.set(\"fluent-channel-id\", data.results[0].id);",
354    "}",
355    "if(data.results && data.results[0] && data.results[0].key){",
356    "    pm.environment.set(\"type-key\", data.results[0].key); ",
357    "}",
358    "if(data.version){",
359    "    pm.environment.set(\"type-version\", data.version);",
360    "}",
361    "if(data.id){",
362    "    pm.environment.set(\"type-id\", data.id); ",
363    "}",
364    "if(data.key){",
365    "    pm.environment.set(\"type-key\", data.key);",
366    "}",
367    ""
368    ],
369    "type": "text/javascript"
370    }
371    }
372    ],
373    "request": {
374    "auth": {
375    "type": "oauth2",
376    "oauth2": [
377    {
378    "key": "accessToken",
379    "value": "{{ctp_access_token}}",
380    "type": "string"
381    },
382    {
383    "key": "addTokenTo",
384    "value": "header",
385    "type": "string"
386    },
387    {
388    "key": "tokenType",
389    "value": "Bearer",
390    "type": "string"
391    }
392    ]
393    },
394    "method": "POST",
395    "header": [
396    {
397    "key": "Content-Type",
398    "value": "application/json"
399    }
400    ],
401    "body": {
402    "mode": "raw",
403    "raw": "{\n  \"key\" : \"flStoredetails\",\n  \"name\" : {\n    \"en\" : \"Fluent Store Details\"\n  },\n  \"description\" : {\n    \"en\" : \"Fluent Store Details\"\n  },\n  \"resourceTypeIds\" : [ \"channel\" ],\n  \"fieldDefinitions\" : [  {\n            \"name\": \"flStoreType\",\n            \"label\": {\n                \"en\": \"Type\"\n            },\n            \"required\": false,\n            \"type\": {\n                \"name\": \"String\"\n            },\n            \"inputHint\": \"SingleLine\"\n        },\n        {\n            \"name\": \"flStoreStatus\",\n            \"label\": {\n                \"en\": \"Status\"\n            },\n            \"required\": false,\n            \"type\": {\n                \"name\": \"String\"\n            },\n            \"inputHint\": \"SingleLine\"\n        },\n        {\n            \"name\": \"flStoreEmail\",\n            \"label\": {\n                \"en\": \"Email\"\n            },\n            \"required\": false,\n            \"type\": {\n                \"name\": \"String\"\n            },\n            \"inputHint\": \"SingleLine\"\n        },\n        {\n            \"name\": \"flStorePhoneNo\",\n            \"label\": {\n                \"en\": \"Phone No.\"\n            },\n            \"required\": false,\n            \"type\": {\n                \"name\": \"String\"\n            },\n            \"inputHint\": \"SingleLine\"\n        },\n        {\n            \"name\": \"flStoreLatitude\",\n            \"label\": {\n                \"en\": \"Latitude\"\n            },\n            \"required\": false,\n            \"type\": {\n                \"name\": \"String\"\n            },\n            \"inputHint\": \"SingleLine\"\n        },\n        {\n            \"name\": \"flStoreLongitude\",\n            \"label\": {\n                \"en\": \"Longitude\"\n            },\n            \"required\": false,\n            \"type\": {\n                \"name\": \"String\"\n            },\n            \"inputHint\": \"SingleLine\"\n        },\n        {\n            \"name\": \"flStoreTimezone\",\n            \"label\": {\n                \"en\": \"Timezone\"\n            },\n            \"required\": false,\n            \"type\": {\n                \"name\": \"String\"\n            },\n            \"inputHint\": \"SingleLine\"\n        },\n        {\n            \"name\": \"flOpeningSchedule\",\n            \"label\": {\n                \"en\": \"Opening Schedule \"\n            },\n            \"required\": false,\n            \"type\": {\n                \"name\": \"String\"\n            },\n            \"inputHint\": \"MultiLine\"\n        },\n        {\n            \"name\": \"flStoreAttributes\",\n            \"label\": {\n                \"en\": \"Attributes \"\n            },\n            \"required\": false,\n            \"type\": {\n                \"name\": \"String\"\n            },\n            \"inputHint\": \"MultiLine\"\n        } ]\n}"
404    },
405    "url": {
406    "raw": "{{host}}/{{project-key}}/types",
407    "host": [
408    "{{host}}"
409    ],
410    "path": [
411    "{{project-key}}",
412    "types"
413    ],
414    "query": [
415    {
416    "key": "expand",
417    "value": "",
418    "disabled": true
419    }
420    ]
421    }
422    },
423    "response": []
424    }
425    ]
426    }    

Project Configuration

The resource folder of the project contains all build time configurations for the commercetools connector.
  • application-connector.yml - Project and Connector specific configuration.
  • application.yml - Core Connect SDK configuration. These are mostly default configurations and core settings.
  • bootstrap.yml - Server/Container configuration. This file includes settings for all different environments and follows the spring profile standards.
  • logback-spring.xml - Log configuration also supports different configurations based on spring profiles.
It is possible to have dedicated configuration files for each environment. This is often used to override a common setting for a particular environment. To create such a file, follow SpringBoot's format having the additional desired spring profile name at the end of the application.yml file, for example, application-dev.yml. More on [Fluent Account Listener Configuration][1].
PropertyDescription
connector-nameThis is the name of the connector and this property is used to both name the connector as well as build the path of other configuration keys. Keep characters limited to 'a-z' and '-'.
route-mappingRoutes mappings are used to determine a route for an incoming message.
routesAllows new routes to be defined or override existing route configuration.
listenersAll active listeners for the connector
credential.credential-managerSets the credential manager. When using AWS, keep the value as "aws-secrets-manager"
job-scheduler.job-scheduler-typeSets the scheduler manager. Currently, the only possible value is "message-queue"
Route Mappings
When different kinds of messages (e.g. orders, categories, products, etc…) are received by the connector, it needs to be told how to map each kind to a handler. A handler has a single purpose for example to process orders. The snippet below illustrates a configuration that tells the connector to react to commercetools inbound messages that have the resource type `“order”` and message type `“ResourceCreated“`, and forward these to the appropriate handler. Messages that fail to map to any entry in this route mapping will be discarded.
1   - route: "commercetools.connect.order.create"
2     props:
3        name: "order"
4        inclusion-filter:
5          - "ResourceCreated"
The next step in processing a message is to determine which Fluent retailer this message is for. This is done by taking the project-key from the commercetools message and doing a lookup at the connector Fluent account mapping setting. For more information on how to configure this setting, follow this guide.
Routes
Handlers by default have a predefined route and properties set but it is possible to override them through the configuration files. The example below will show how to override an existing route. To view all available handlers and routes, check Connector Features
1{
2  "route": "batch-inventory-sync",
3  "handler": "InventorySyncJob",
4  "priority": 0,
5  "rops": {
6    "page-size": "500"
7  },
8  "className": "com.fluentcommerce.connect.client.commercetools.handler.job.InventorySyncJobHandler",
9  "description": "Sync inventory details from Fluent to commerceTools"
10}
It is possible to modify its behaviour by specifying a different property value. Note that if the route name is different from the original one, a new route is created and the original is still valid.
1  routes: 
2    job: 
3      route: "batch-inventory-sync"
4      handlerName: "InventorySyncJob"
5      props:
6        page-size: "1000"
The format of this configuration block is as follows:
1  routes: 
2    #possible values: job, message or notification
3    job: 
4      route: "<route-name>"
5      handlerName: "<handler-name>"
6      props:
7        #this flexible. Consider this is a map of String: String/int/double/long
8        page-size: "1000"  
Listeners
There are 4 listeners in this connector
  • batch - used to process queued jobs.
  • messages - used to queue internal connector messages.
  • notification - for internal connector events that require an external notification.
  • commercetools_events - queue to receive all commercetools application events. This queue behaves differently from the other queues and it requires a property fluent-account with the Fluent account to be used by the connector. Without this property, this queue will fail to start.