Skip to content

Custom endpoint

You can use a custom endpoint if you would like to offer pickup points that are not provided by our app. To get this to work, you will need the help of a developer. This guide is meant for developers.

How does it work?

When creating a pickup point rate, once you select Custom endpoint, you will be able to paste your endpoint URL. Each time pickup points are displayed, we will be making a GET request to that endpoint. Each request will be made with the following query parameters:

ParameterNameDescription
latLatitudeLatitude of user shipping address or his position on the map
lngLongitudeLongitude of user shipping address or his position on the map
country_codeCountry codeCountry code (ISO 3166-1 alpha-2) of user shipping address. It won’t change if user moves map to different country.
qSearch queryOptional: search query on the list view, search can be enabled in Custom endpoint settings

If your endpoint requires options, you can pass them as query parameters as well and they will be merged with above.

Your endpoint is expected to respond with JSON in following format:

{
"locations": [
{
"code": "019889",
"address": {
"address1": "19 BOULEVARD GALLIENI",
"address2": null,
"city": "NEUILLY PLAISANCE",
"zip": "93360",
"country_code": "FR",
"latitude": 48.8532417,
"longitude": 2.514444
},
"details": {
"name": "NEW HIGH TECH GSM",
"description": null,
"business_hours": [
{
"day": "MONDAY",
"opening_time": "08:00",
"closing_time": "21:00"
},
{
"day": "TUESDAY",
"opening_time": "08:00",
"closing_time": "21:00"
},
{
"day": "WEDNESDAY",
"opening_time": "08:00",
"closing_time": "21:00"
},
{
"day": "THURSDAY",
"opening_time": "08:00",
"closing_time": "21:00"
},
{
"day": "FRIDAY",
"opening_time": "08:00",
"closing_time": "21:00"
},
{
"day": "SATURDAY",
"opening_time": "08:00",
"closing_time": "21:00"
},
{
"day": "SUNDAY",
"opening_time": "09:00",
"closing_time": "20:00"
}
],
"open_24_hours": false
},
"attributes": [],
"icon_url": "https://example.com/pin-mondial-relay-pudo.png"
},
{
"code": "014514",
"address": {
"address1": "32 RUE ROGER-SALENGRO",
"address2": null,
"city": "FONTENAY SOUS BOIS",
"zip": "94120",
"country_code": "FR",
"latitude": 48.855606,
"longitude": 2.474787
},
"details": {
"name": "LOCKER 24/7 INTERMARCH ROGER SA",
"description": null,
"business_hours": [],
"open_24_hours": true
},
"attributes": [],
"icon_url": "https://example.com/pin-mondial-relay-apm.png"
},
{
"code": "003583",
"address": {
"address1": "4 SQUARE GEORGES PITTOEFF",
"address2": null,
"city": "CHAMPIGNY SUR MARNE",
"zip": "94500",
"country_code": "FR",
"latitude": 48.8262074,
"longitude": 2.5112624
},
"details": {
"name": "D MARKET",
"description": null,
"business_hours": [
{
"day": "MONDAY",
"opening_time": "09:00",
"closing_time": "14:00"
},
{
"day": "MONDAY",
"opening_time": "15:00",
"closing_time": "22:00"
},
{
"day": "TUESDAY",
"opening_time": "09:00",
"closing_time": "14:00"
},
{
"day": "TUESDAY",
"opening_time": "15:00",
"closing_time": "22:00"
},
{
"day": "WEDNESDAY",
"opening_time": "09:00",
"closing_time": "14:00"
},
{
"day": "WEDNESDAY",
"opening_time": "15:00",
"closing_time": "22:00"
},
{
"day": "THURSDAY",
"opening_time": "09:00",
"closing_time": "14:00"
},
{
"day": "THURSDAY",
"opening_time": "15:00",
"closing_time": "22:00"
},
{
"day": "FRIDAY",
"opening_time": "09:00",
"closing_time": "14:00"
},
{
"day": "FRIDAY",
"opening_time": "15:00",
"closing_time": "22:00"
},
{
"day": "SATURDAY",
"opening_time": "09:00",
"closing_time": "22:00"
},
{
"day": "SUNDAY",
"opening_time": "13:00",
"closing_time": "21:00"
}
],
"open_24_hours": false
},
"attributes": [],
"icon_url": "https://example.com/pin-mondial-relay-pudo.png"
}
]
}

Response

Response object

KeyRequiredTypeDescription
locationstrueLocation[]Contains data of all available locations for requested lng/lat
error_messagefalseStringError shown to the end user. Currently not surfaced in UI, but visible in network request response

Location object

KeyRequiredTypeDescription
codetrueStringCarrier given identifier
addresstrueAddress
detailstrueDetails
attributesfalseAttributes[]List of additional attributes that will be passed to the order
icon_urlfalseStringURL to the icon that will be displayed on the map - should be PNG hosted on Shopify CDN

Address object

KeyRequiredTypeDescription
address1trueStringThe first line of the address: street and number
address2falseStringSecond line of the address
citytrueStringCity
ziptrueStringPostal code
country_codetrueStringCountry code ISO 3166-1 alpha-2
latitudetrueFloatLatitude
longitudetrueFloatLongitude

Details object

KeyRequiredTypeDescription
nametrueStringLocation name, displayed to end user
descriptionfalseStringDescription of the location, displayed to end user
business_hoursfalseBusinessHour[]List of opening hours, if unknown or 24/7 send empty array
open_24_hoursfalseBooleanIs the location open 24/7? If unknown: send false

BusinessHour object

KeyRequiredTypeDescription
daytrueEnum: MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY SUNDAYDay of the week
opening_timetrueStringTime in 24h format, for example: 1:00 or 23:49
closing_timetrueStringAs above

Attributes object

KeyRequiredTypeDescription
keytrueStringKey of the attribute
valuetrueString / Boolean / NumberValue of the attribute

TypeScript type

type CustomIntegrationResponse = {
error_message?: string | null;
locations: {
code: string;
address: {
address1: string;
address2?: string | null;
city: string;
zip: string;
longitude: number;
latitude: number;
country_code: string;
};
details: {
name: string;
description?: string | null;
business_hours?:
| {
day: "MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY" | "SUNDAY";
opening_time: string;
closing_time: string;
}[]
| null;
open_24_hours?: boolean;
};
attributes?:
| {
[key: string]: string | number | boolean;
}[]
| null;
icon_url?: string | null;
}[];
};

Implementation tips

Hosting options

For dynamic providers, we recommend using Cloudflare Workers:

  • Fast global response times
  • Free tier available
  • Easy deployment and maintenance

For static locations (up to 50):

  1. Create a JSON file with your locations
  2. Upload it to Shopify CDN via the Content tab
  3. Use the CDN URL as your endpoint

Note: The CDN URL will change after each file update due to Shopify’s CDN versioning system. Make sure to update the endpoint URL in your settings after uploading a new version.

Troubleshooting

If you receive a CUSTOM_INTEGRATION_INVALID_RESPONSE error:

  1. Open your browser’s Developer Tools
  2. Go to the Network tab
  3. Find the request to /locations endpoint
  4. Inspect the response to see detailed error information

While we don’t assist with implementation, our support team is happy to help with debugging issues.

Changelog

20 Aug, 2024

  • Added country_code query parameter

11 Jul, 2024

  • We removed features property. Instead you can manage features within the pickup point rate settings.

12 Mar, 2024

  • We removed distance_meters property. Instead we will calculate distance based on location lng / lat. If you respond with distance_meters - it will be ignored, you can remove it from your API.