Custom endpoints let you offer pickup points from any source not covered by our built-in carrier integrations. This feature requires Shopify Plus and a developer to implement the endpoint.
How it works
In Shopify Admin → Atlas Pickup Points, open the pickup point configuration, select Custom as the carrier, and paste your endpoint URL. Each time pickup points are displayed, Atlas makes a GET request to your endpoint with the following query parameters:
| Parameter | Name | Description |
|---|---|---|
| lat | Latitude | Latitude of the buyer’s shipping address or their position on the map |
| lng | Longitude | Longitude of the buyer’s shipping address or their position on the map |
| country_code | Country code | Country code (ISO 3166-1 alpha-2) of the buyer’s shipping address. Does not change if the buyer moves the map to a different country. |
| q | Search query | Optional: search query from the list view. Search can be enabled in the custom endpoint settings. |
If your endpoint requires additional options, you can pass them as query parameters and they will be merged with the parameters above.
Authentication
If your endpoint requires authentication, you can add a secret in the custom endpoint settings. Atlas will send it as the x-atlas-pickup-points-secret header with every request, allowing your endpoint to verify that the request is coming from Atlas.
Your endpoint must respond with JSON in the 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": [
{
"key": "type",
"value": "PUDO"
}
]
},
{
"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": [
{
"key": "type",
"value": "LOCKER"
}
]
}
]
}
Response
Response object
| Key | Required | Type | Description |
|---|---|---|---|
| locations | true | Location[] | List of available pickup points for the requested coordinates |
| error_message | false | String | Error message visible in the network response (not shown in the UI) |
Location object
| Key | Required | Type | Description |
|---|---|---|---|
| code | true | String | Unique identifier of the pickup point |
| address | true | Address | Pickup point address |
| details | true | Details | Pickup point details |
| attributes | false | Attributes[] | Additional attributes that will be passed to the order |
| icon_url | false | String | URL of the map pin icon. Should be a PNG hosted on Shopify CDN. |
Address object
| Key | Required | Type | Description |
|---|---|---|---|
| address1 | true | String | First line of the address (street and number) |
| address2 | false | String | Second line of the address (not visible to the buyer) |
| city | true | String | City |
| zip | true | String | Postal code |
| country_code | true | String | Country code ISO 3166-1 alpha-2 |
| latitude | true | Float | Latitude |
| longitude | true | Float | Longitude |
Details object
| Key | Required | Type | Description |
|---|---|---|---|
| name | true | String | Location name, displayed to the buyer |
| description | false | String | Description of the location, displayed to the buyer |
| business_hours | false | BusinessHour[] | List of opening hours. If unknown or 24/7, send empty array. |
| open_24_hours | false | Boolean | Is the location open 24/7? If unknown, send false. |
BusinessHour object
| Key | Required | Type | Description |
|---|---|---|---|
| day | true | Enum: MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY SUNDAY | Day of the week |
| opening_time | true | String | Time in 24h format, for example: 01 or 23 |
| closing_time | true | String | Time in 24h format, for example: 01 or 23 |
Attributes object
| Key | Required | Type | Description |
|---|---|---|---|
| key | true | String | Key of the attribute |
| value | true | String / Boolean / Number | Value 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;
}[];
open_24_hours: boolean;
};
attributes: {
key: string;
value: string | number | boolean;
}[];
icon_url?: string | null;
}[];
};
Implementation tips
Hosting options
We recommend Heroku, AWS Lambda, or Cloudflare Workers. For the best performance and lowest latency, deploy in the EU region, preferably AWS eu-west-1 (Ireland), where our infrastructure is located.
For static locations (up to 50):
- Create a JSON file with your locations
- Upload it in Shopify Admin → Content → Files
- Use the CDN URL as your endpoint
Troubleshooting
If you receive a CUSTOM_INTEGRATION_INVALID_RESPONSE error:
- Open your browser’s Developer Tools
- Go to the Network tab
- Find the request to the
/locationsendpoint - 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.