eBay Fulfilment OC Technical Scope Phase 1
The purpose of this document is to give good understanding how eBay fulfilment will be integrated with Hemi
Latest API spec and connection guidelines: https://mf-seller-static-hk.orangeconnex.com/static/website/document/UK//20211117/1637147111937/OCERP Connection Guidelines v1.0.pdf
Latest version of seller manual: https://www.orangeconnex.co.uk/sellermanual.html
Shipping services and weight/dimensions restrictions: at the bottom of page: https://www.orangeconnex.co.uk/fulfillment.html API Documentation:
3PP API Document_beta_v4.1.xlsx
Test Credentials:
Customer Name | not necessary if 3PP-ERP |
---|---|
Country/Region | UK |
OCID | |
not necessary if 3PP-ERP | |
ERP Type | 3PP-ERP |
ERP Name | Pentagon |
EF Service | UK |
Test Sell-Portal | https://fulfillment.orangeconnex.com/ |
Test SellerPortal account | Account: ukerptest@163.com |
Password: UKtest2021 | |
Test Key | Clientkey: d025137a-da0a-4c43-b351-4efa75e7fd1e |
SecretKey: 8a883f0e-0aec-460c-9178-ac8f267f05a8 | |
Authorization Code | xS04ADHSlHRBgDwMBcFOEks4aYbIK%252B%252BsFKjIjSo6z1XVS%252BAqNYkD0fHwWn6u76CZLGkBSRaYN%252BXs%252FC2shOlpiAuBNxasZMYVyD%252FQbV13qW5T%252FTEi4g1JixEfhxRTjnlTvfayIpGn%252FGBriVtGSF4m1BEHVFY7HWFa9Qvck%252FP7Cfkn1KDvlUjnnQEJ42mGO%252BjXEbrKeYuvu8v6wMcxDclV5YQ6cWobsDyREgOB3M8%252FPvk107%252F%252BjsXSw2fedw8QltMWnjSnVy44C%252B9LjrZ5NqntIo6D7D6kVxy8EsvEC1qwvMOBiQ5h4Kg7%252F%252BQK0s%252Bb%252FXKnAIVhabjBzjeCMfjaND9EPPxthUzGWV0enPKuz8932KVB5MTJs9HxmWhYsMb9f0hpSRWIAAw1%252BZTuVsRevV3AkzQLIwndA9bXePgf%252FKOzTn%252BBwvrigL3vM4Q919jfAwppnvSJh13L5WYxvUKK885tuaQAVhMfUXUgMjpOWy0dbjNhsrvay02a3PjvacJ2mwEIe3S1xdYQp%252BBd0rQpb3OrEa22JZCfCd54H3ehRKV6O9SlCYdPxa%252FnfWvjzKBSbeWUHUybZqpqPQwG62dCKZY5oIaCYspFqm4mY78BKt4%252FIV3f9WsH0BodqmtXu41x87jly25GHBFlZPiSQlhn41jzxvKD96jsGYjSBYMBDgNxM5U%253D |
Test API URL | https://openapi-uk.orangeconnex.com |
API document | Please see the official website or attachment |
1. Authorization

STEP 1
To begin the authorization flow, the 3PP constructs a URL like the following
Request:
POST: https://authorization-server.com/oauth/authorize?response_type=code&client_id=a74877d520200ae841a2cfc34c46e208&redirect_uri=https%3A%2F%2Fexample-app.com%2Fcallback&state=xcoiv98y2kd22vusuye3kch
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
eBay Field | Hemi Field | Description | Type | Max Length | Mandatory (Y/N/C) |
---|---|---|---|---|---|
response_type | N/A | Fixed value: "code" | VARCHAR | 100 | Y |
client_id | N/A | The ID of 3PP offered by OC offline. | VARCHAR | 100 | Y |
redirect_uri | N/A | To prevent attack, OC validates value of this field against the redirect URL that was used when requesting the authorization code. The two redirect URLs should be the same. | VARCHAR | 4000 | Y |
state | N/A | 3PP generates a string and includes it in the request. This string could be used to recognize 3PP's account. | VARCHAR | 2000 | Y |
When the user visits this URL, the authorization server will present them with a prompt asking if they would like to authorize this application’s request. If the user approves the request, OC will redirect the browser back to the redirect_uri specified by the application, adding a code and state to the query string.
Response:
https%3A%2F%2Fexample-app.com%2Fcallback?code=g0ZGZmNjVmOWIjNTk2NTk4ZTYyZGI3&state=xcoiv98y2kd22vusuye3kch
eBay Field | Hemi Field | Description | Type | Max Length | Mandatory (Y/N/C) |
---|---|---|---|---|---|
code | N/A | value of authorization code | VARCHAR | 1000 | Y |
state | N/A | This is the same state value from URL1 query string. | VARCHAR | 2000 | Y |
STEP 2 Once we get the authorization code, we need to exchange the authorization token for an access token and refresh token.
POST: /oauth/token?grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcallback&client_td=409uioe809eoiuo434
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Request:
eBay Field | Hemi Field | Description | Type | Max Length | Mandatory (Y/N/C) |
---|---|---|---|---|---|
client_id | N/A | The ID of 3PP offered by OC offline | VARCHAR | 100 | Y |
grant_type | N/A | Fixed value: "authorization_code" | VARCHAR | 50 | Y |
redirect_uri | N/A | To prevent attack, OC validates value of this field against the redirect URL that was used when requesting the authorization code. The two redirect URLs should be the same. | VARCHAR | 4000 | Y |
code | N/A | Value of authorization code | VARCHAR | 1000 | Y |
Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODc4OTg4OTQsInVzZXJfbmFtZSI6IjE1NzY0NzcwNDY4NzAwMjEiLCJjbGllbnRfaWQiOiJjYzE3YzMwY2QxMTFjNzIxNWZjOGY1MWY4NzkwZTBlMSIsInNjb3BlIjpbImFsbCJdfQ.L_u1FA-sIy5ure4z-j18_mqkfT4ZslwliHgC6UHFcF7zAUtrI5vrrK_weIyGGhE3r_9V8GFLhp-GPNtezLQdOGsD12DbnBYmBeHLHPbmHFZ3a4KX2gyz4FzocL-A6Kj633TlL5vIhCc2jBV9iXUiR0yCmLSsQbISnowVz8vdJT4ltd6KGwVpAZQZ6QtB6WwLOrDViyxEmFrIpGAd-Lc2p53vEJvCfUdJu_JyUUaGVow7k2amuaPu6LRfCvFTOy75kp51Pwy2Y_rTYJ5halY5Orh0qTEYSKEEiBElfR-oAytwYqJ8UuvjGBL0TnBrsiKp5TJGu9Cd72Z8fRhbF4oEq4P2Dr9zCS3pyoZMYjSwuEfNxaAvlzQMs_oWb9KxACi5SYlSfryEmltnY1yNSvPrKXu-lb37JtHIisAZqMXLb4vkRz86NgMNOXHmQewRCzKgeNpDVjVrqnUhlwfJy0hwNa71hFMTi9RvOooBfJIo2gqAMnliucTtpAfotq1gdullwFRkZZTXoQGzHovMkkibzQrglQlIqfghyGAnGC7X9oR2YWvF0enMuIpb3yB4hpIB48S8wfbntZDw_sLCibYA7IEqdyfyOrDiy8QBUn4ltIO2uizwgwJXz1Y-Ty5PzVA_2vGH00Bj7ElFReb0IEtt9wfNqtqSfIGZge9hGRrEFmU",
"token_type": "bearer",
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MTc1MjQyNTcsInVzZXJfbmFtZSI6IjE1NzY0NzcwNDY4NzAwMjEiLCJjbGllbnRfaWQiOiJjYzE3YzMwY2QxMTFjNzIxNWZjOGY1MWY4NzkwZTBlMSIsInNjb3BlIjpbImFsbCJdfQ.BjXrwlXlsNvi2-r8dXkEnAvUbtOXFSRdYSgC181uE1XZP6mbYLPHfAX2Xp_KstlUjC_W9Iw5XzZUz9PrGoZhtkEan96kdlZ0RpW_BBs_ikYnkRJ_8IgASvHTpQNu-jcYnaVRiyoSHyqs1TXdv97cru3tMXReanKkEtEt8RUMiLfoJ-T7OZ8fjIcVW1mfIRGcFmvmI3hTsDSOSPSCiFtFeyR1FKXghq2Qjlcms8paZCNr-qucdvxi9Iexs-Z6y8hDJ27HUTz1tYxL0icOx67-GPsUGqW6gThOwDV1Cwc7pQUKjROXJXcxAMi94m_TddgSHvcZb0euAw6Yy6A72lNh8whTQ9URQoD_9jL_OUNfxma6bYsqjeajR01efhpKSu9igSJLzTDmFmNGKEdGXDCoN4k5sqtoPA_YRSDqM0SdMk0xCRAbkFJg9ZesrpqPGvH1Ny566yQPfGWkrQ_T8xhz990K1BT_3TYqpwEU1X6Obkzzb6MNYHf-phMMfwPzFDQlqHZjTUuwjV8Q5yQG2h_jz4rd8q83L0DFFv0lQHwS5Xjx8t21m0aQFHHwphGWhOTxoHvqqpNjzRM3IRsfe_-dJlMmzoe9YsrIECeh8WZB5_hR5g2YhfQZl5QvXOZ21mPz4neRq-XlVcDnRGlm9c9CDf8OsihTTXv0vLzZTRarkIY"f,
"expires_in": 3600
}
eBay Field | Hemi Field | Description | Type | Max Length | Mandatory (Y/N/C) |
---|---|---|---|---|---|
access_token | N/A (Not stored anywhere on this step.) | Value of access token. When 3PP requests APIs (exclude "getServiceList" API), access token should be contained in a header named "Access-Token". | |||
Expires in 3600 seconds | VARCHAR | 2000 | Y | ||
token_type | “BEARER“ | Fixed value: "bearer" | VARCHAR | 50 | Y |
refresh_token | Account Orange Connex > Refresh Token (not visible in the UI) | Value of refresh token. If the access token is expired, 3PP uses the refresh token to get a new access token and its expiration date. | |||
Expires in one year | VARCHAR | 2000 | Y | ||
expires_in | Ac count Orange Connex > Refresh Token Expiration Date (calculate the expiration date) | Duration of validity of access token. | NUMBER | Y |
STEP3
Once we have generated the access and the refresh token every 3600 seconds we will need to regenerate the Access Token using the following Request:
POST /oauth/token?grant_type=refresh_token&refresh_token=SplxlOBeZQQYbYS6WxSbIA&client_id=409uioe809eoiuo434
Content-Type: application/x-www-form-urlencoded
Field | Description | Type | Max Length | Mandatory (Y/N/C) |
---|---|---|---|---|
client_id | The ID of 3PP offered by OC offline. | VARCHAR | 100 | Y |
grant_type | Fixed value "refresh_token" | VARCHAR | 50 | Y |
refresh_token | The refresh token is from the response of "get accessToken&refreshToken" API | VARCHAR | 2000 | Y |
Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODc4OTg4OTQsInVzZXJfbmFtZSI6IjE1NzY0NzcwNDY4NzAwMjEiLCJjbGllbnRfaWQiOiJjYzE3YzMwY2QxMTFjNzIxNWZjOGY1MWY4NzkwZTBlMSIsInNjb3BlIjpbImFsbCJdfQ.L_u1FA-sIy5ure4z-j18_mqkfT4ZslwliHgC6UHFcF7zAUtrI5vrrK_weIyGGhE3r_9V8GFLhp-GPNtezLQdOGsD12DbnBYmBeHLHPbmHFZ3a4KX2gyz4FzocL-A6Kj633TlL5vIhCc2jBV9iXUiR0yCmLSsQbISnowVz8vdJT4ltd6KGwVpAZQZ6QtB6WwLOrDViyxEmFrIpGAd-Lc2p53vEJvCfUdJu_JyUUaGVow7k2amuaPu6LRfCvFTOy75kp51Pwy2Y_rTYJ5halY5Orh0qTEYSKEEiBElfR-oAytwYqJ8UuvjGBL0TnBrsiKp5TJGu9Cd72Z8fRhbF4oEq4P2Dr9zCS3pyoZMYjSwuEfNxaAvlzQMs_oWb9KxACi5SYlSfryEmltnY1yNSvPrKXu-lb37JtHIisAZqMXLb4vkRz86NgMNOXHmQewRCzKgeNpDVjVrqnUhlwfJy0hwNa71hFMTi9RvOooBfJIo2gqAMnliucTtpAfotq1gdullwFRkZZTXoQGzHovMkkibzQrglQlIqfghyGAnGC7X9oR2YWvF0enMuIpb3yB4hpIB48S8wfbntZDw_sLCibYA7IEqdyfyOrDiy8QBUn4ltIO2uizwgwJXz1Y-Ty5PzVA_2vGH00Bj7ElFReb0IEtt9wfNqtqSfIGZge9hGRrEFmU",
"token_type": "bearer",
"expires_in": 3600
}
Ebay Field | Hemi Field | Description | Type | Max Length | Mandatory (Y/N/C) | Remarks |
---|---|---|---|---|---|---|
access_token | N/A (To be stored in cache.) | Value of access token. When 3PP requests APIs (exclude "getServiceList" API), access token should be contained in a header named "Access-Token". | VARCHAR | 2000 | Y | |
token_type | N/A | Fixed value: "bearer" | VARCHAR | 50 | Y | |
expires_in | N/A (Use this to calculate the expiration date for the cache file.) | Duration of validity of access token | INTEGER | Y |
2.Get StockSnapshot
Because we are not creating products directly from Hemi to OC system will be using their interface for product management and with the use of this call we will be able to get all the internal OCSKU for each of our Hemi SKUs and be able to identify which products are currently part of the OC fulfilment. Please note the stock levels stored for OC in Hemi are just for reference. Per OCSKU, OC will provide a location-specific inventory snapshot of the request time. If this field is null, OC returns all the SKUs' inventory snapshot of the request time. POST https://openapi-uk.orangeconnex.com/openapi/3pp/inventory/v1/snapshot
Request body:
{
"data": [
{
"MFSKUID": null
}
],
"messageId": "20200430030118653",
"timestamp": 1588230078677
}
eBay Field | Hemi Field | Description | Type | Max Length | Mandatory (Y/N/C) | |
---|---|---|---|---|---|---|
data |
||||||
MFSKUID |
“null“ | If this field is null, OC returns all the SKUs' inventory snapshot of the request time. | VARCHAR | 15 | N | |
messageId |
N/A | |||||
timestamp |
NOW() | Current date in timestamp but in miliseconds |
Response:
{
"code": 0,
"data": [
{
"MFSKUID": "OC0000000400371",
"serviceRegionList": [
{
"serviceRegion": "DE",
"inventoryList": [
{
"actualCount": 3,
"inventoryStatus": "INTRAN"
},
{
"actualCount": 300,
"inventoryStatus": "AVL"
},
{
"actualCount": 0,
"inventoryStatus": "RCVD"
},
{
"actualCount": 5,
"inventoryStatus": "RSVALOC"
},
{
"actualCount": 0,
"inventoryStatus": "RSVHO"
},
{
"actualCount": 0,
"inventoryStatus": "RSVAS"
},
{
"actualCount": 0,
"inventoryStatus": "UNF"
}
]
},
{
"serviceRegion": "UK",
"inventoryList": [
{
"actualCount": 0,
"inventoryStatus": "INTRAN"
},
{
"actualCount": 0,
"inventoryStatus": "AVL"
},
{
"actualCount": 0,
"inventoryStatus": "RCVD"
},
{
"actualCount": 0,
"inventoryStatus": "RSVALOC"
},
{
"actualCount": 0,
"inventoryStatus": "RSVHO"
},
{
"actualCount": 0,
"inventoryStatus": "RSVAS"
},
{
"actualCount": 0,
"inventoryStatus": "UNF"
}
]
}
],
"snapshotTime": "2021-10-22T09:56:41+0800",
"sellerSkuId": "GY0005886"
}
],
"message": "test",
"messageId": "20200430030118653"
}
eBay Field | Hemi Field | Description | Type | Max Length | Mandatory (Y/N/C) | |||
---|---|---|---|---|---|---|---|---|
code |
N/A | |||||||
data |
||||||||
MFSKUID |
Product Account Orange Connex > OC SKU | GUID of SKU on the OC platform, which is generated by OC and responded to 3PP when registering SKU. | VARCHAR | 15 | Y | |||
serviceRegionList |
LIST | Y | ||||||
serviceRegion |
Based on the value here we know which item account account to update either eBay UK or eBay DE. At the moment only those two countries are supported | VARCHAR | 50 | Y | ||||
inventoryList |
LIST | Y | ||||||
actualCount |
Product Account Orange Connex > Intransit Stock | |||||||
Product Account Orange Connex > Available Stock | Value is limited to the codes predefined on the left side of the equal sign: INTRAN=in-Transit;AVL=available;Received=RCVD;ReservedAllocated=RSVALOC;ReservedHold=RSVHO;ReservedVAS=RSVAS;UNF=unfulfillable (It might be updated based on operation requirement) | |||||||
We will need to store the In transit stock - “INTRAN“ and the Available stock - "AVL" | VARCHAR | 20 | Y | |||||
inventoryStatus |
Product Account Orange Connex > Intransit Stock | |||||||
Product Account Orange Connex > Available Stock | At snapshot time, this field will get the actual count of each inventory status | INTEGER | Y | |||||
snapshotTime |
Product Account Orange Connex > Stock Updated | SnapshotTime format: date + time zone, UTC ISO8601 ,ex:2018-11-28T20:09:57:001+0800 | VARCHAR | 24 | Y | |||
sellerSkuId | N/A | Used this field to map our internal SKU and based on the serviceRegion we update the correct item account |
We skip it and just return it in the terminal if you manually run the cron.
If we are missing item account this is what we want to do.
Basically should return just for “SKU 123456 item account for eBay UK is missing” | | | |
| message
| | | | N/A | | | | |
| messageId
| | | | N/A | | | | |
| | | | | Product Account Orange Connex > Created in OC | Checkbox which indicated if the SKU is created in the OC portal. Will be set on “yes” if we receive matching sellerSkuId in the response. Consequetly if we have a product which is on “Yes” and is missing from the response we need to set it as “No” | | | |
3. GetOrders Amendments
Since we will need to identify which orders will be fulfilled by eBay and which with other courier we will need to start storing the Fulfillment type which we receives for every eBay order. eBay will separate orders depending on whether they are eBayFulfiled or seller fulfilled – please see explanation below

eBay Field | Hemi Field | Comment | |
---|---|---|---|
OrderArray > Order > TransactionArray > Transaction > Program > Fulfillment | N/A | This container provides details about an order line item being handled by eBay fulfillment. It is only returned for paid orders being fulfilled by eBay or an eBay fulfillment partner. | |
DetailLevel: ReturnAll. Also returned if DetailLevel is not provided on input. | |||
FulfillmentBy | Orders > Marketplace Fulfillment Channel | The value returned in this field indicates the party that is handling fulfillment of the order line item. | |
DetailLevel: ReturnAll. Also returned if DetailLevel is not provided on input. | |||
FulfillmentRefId | Orders Ebay > Fulfillment Ref ID | The value in this field identifies the warehouse where the order line item is located. | |
DetailLevel: ReturnAll. Also returned if DetailLevel is not provided on input. |
<Fulfillment>
<FulfillmentBy> string </FulfillmentBy>
<FulfillmentRefId> string </FulfillmentRefId>
</Fulfillment>
The new fields will be stored in Order Item eBay and also we will need to set the correct Order Item eBay > Type - Fulfilled by eBay. If all
4. Ship Orders Amendments
All order item with Orders > Marketplace Fulfillment Channel = “Fulfilled by eBay” will need to be skipped and not shipped from Hemi. Thus we need to add this logic in the current eBay shipping cron and skip such orders: cron_ebay_007_shipped_orders_update.php
Q&A
Can an order be with eBay Fulfilled items and seller fulfilled items? No, we will have either Seller Fulfilled Order or eBay Fulfilled Order and the order will be separated.