openapi: 3.1.0
info:
version: 25.1126.6886238
x-version-timestamp: 2025-11-26 19:10:23+00:00
title: Addresses Introduction Account Addresses Custom API Entries API
description: 'The Addresses API allows you to organize account addresses. Addresses are a sub-resource of `account` resources, an account can have multiple addresses, such as home, work, and neighbour.
You can use an account address with either [client_credentials access token](/docs/api/authentication/create-an-access-token) or a combination of [implicit access token](/docs/api/authentication/create-an-access-token) and [Account Management authentication](/docs/api/accounts/post-v-2-account-members-tokens) token.
'
contact:
name: Elastic Path
url: https://www.elasticpath.com
email: support@elasticpath.com
license:
url: https://elasticpath.dev
name: MIT
servers:
- url: https://useast.api.elasticpath.com
description: US East
- url: https://euwest.api.elasticpath.com
description: EU West
security:
- BearerToken: []
tags:
- name: Custom API Entries
description: "A **Custom API Entry** is a specific instance of a resource, such as a single wishlist in a Custom API for wishlists.\n\nCustom API Entries can be accessed in two different ways, via the **extension** endpoint, or the **settings** endpoint:\n\n* Extension Endpoint: `/v2/extensions/{custom-api-slug}` - This is the primary endpoint created for use. Most clients should use this endpoint as it adheres to the semantics of the configuration. Retrieve the [OpenAPI Specifications](/docs/api/commerce-extensions/get-open-api-specification) to learn how to interact with this endpoint.\n* Settings Endpoint: `/v2/settings/extensions/custom-apis/{custom-api-id}/entries/` - This endpoint should only be used in cases where you want to interact with your Custom APIs in a generic way in an admin capacity.\n\nCurrently, the distinction between these endpoints is minimal. The extension endpoint uses a slug in the URL path, and the settings endpoint uses an ID. For most use cases involving the new Custom API, we recommend using the extension endpoint.\n\nConceptually, the settings endpoint is analogous to reflection in most programming languages. You use it when you want to operate in a generic way. For example, we used the settings endpoint to build Commerce Manager. Another example is if you need to import and export various types of data from CSV files. Instead of writing multiple scripts for different extension endpoints, you can write one script that operates on the settings endpoint.\n\n## Events\n\nYou can integrate Commerce Extensions with your external systems by observing the appropriate events. For more information, see [Integrations](/docs/api/integrations/integrations-introduction).\n\nGiven you have a Custom API with `api_type` of `wishlist_ext` and you want to perform additional processing when an action is taken, like when a wishlist is created:\n\n```bash\ncurl -X POST https://useast.api.elasticpath.com/v2/extensions/wishlists \\\n -H \"Authorization: Bearer XXXX\" \\\n -H \"Content-Type: application/json\" \\\n -d $ {\n \"data\": {\n \"type\": \"wishlist_ext\",\n \"name\": \"My Wishlist\",\n \"items_count\": 0,\n \"keep_purchased\": false\n }\n }\n```\n\nWhen you [create an integration](/docs/api/integrations/create-integration) with `wishlist_ext.created` in `observes` field.\nThen the configured `webhook` or `aws_sqs` will receive the appropriate message.\n\nYou can configure integrations to observe the following events for your Custom API Entries:\n* Created\n* Updated\n* Deleted\n"
paths:
/v2/settings/extensions/custom-apis/{custom-api-id}/entries:
parameters:
- $ref: '#/components/parameters/CustomAPIID'
post:
tags:
- Custom API Entries
summary: Create a Custom API Entry
operationId: CreateACustomAPIEntry
description: Create a Custom API Entry
requestBody:
$ref: '#/components/requestBodies/CreateCustomAPIEntry'
responses:
'201':
$ref: '#/components/responses/CustomAPIEntry'
'400':
$ref: '#/components/responses/ValidationError'
'403':
$ref: '#/components/responses/ForbiddenError'
'409':
$ref: '#/components/responses/ConflictError'
'413':
$ref: '#/components/responses/PayloadTooLargeError'
description: Payload Too Large. The total size of a Custom API Entry must not exceed 64KB.
'500':
$ref: '#/components/responses/InternalServerError'
'503':
$ref: '#/components/responses/ServiceUnavailable'
get:
tags:
- Custom API Entries
summary: List Custom API Entries
operationId: ListCustomAPIEntries
description: 'Retrieves a list of Custom API Entries
## Filtering
The following operators and attributes are available for [filtering](/guides/Getting-Started/filtering) all Custom API Entries:
| Attribute | Operators | Example |
|---------------|-------------------------------|-----------------------------------------------|
| `id` | `lt`,`le`,`eq`,`gt`,`ge`,`in` | `eq(id,859aeba1-03c2-4822-bd4c-89afce93d7eb)` |
| `created_at` | `lt`,`le`,`eq`,`gt`,`ge` | `ge(created_at,2024-04-29T00:00:00.000Z)` |
| `updated_at` | `lt`,`le`,`eq`,`gt`,`ge` | `le(updated_at,2024-04-29T00:00:00.000Z)` |
The following operators and attributes may be available for filtering Custom API Entries depending on how the [Custom Fields](/docs/api/commerce-extensions/create-a-custom-field) for that Custom API are configured.
| Field type | Operators |
|------------|-----------------------------------------------------------|
| `string` | `lt`,`le`,`eq`,`gt`,`ge`,`in`,`is_null`,`like` |
| `integer` | `lt`,`le`,`eq`,`gt`,`ge`,`in`,`is_null` |
| `float` | `lt`,`le`,`gt`,`ge`,`in`,`is_null` |
| `boolean` | `eq`,`is_null` |
| `list` | `contains`,`contains_any`,`is_null`,`contains_all`(typed) |
Given there is a Custom Field with `"slug": "name"` and `"field_type": "string"`.
When you get all Custom API Entries with query parameter: `?filter=like(name,*wish*)`.
Then you will get all Custom API Entries where `name` contains the string `wish`.
:::warn
For performance reasons, the `is_null` search operator will **NOT** match entries for a custom_field where the custom_entry was last updated before the custom_field existed. Updating the entry will cause the field to exist and match properly.
:::
## Sorting
The following attributes are available for sorting. When specified, the results are sorted in ascending order based on the value of the field. To sort in descending order, prefix the attribute with `-`, for example, `-updated_at`. The default sort order is `created_at` in descending order.
- `id`
- `created_at`
- `updated_at`
## Query Optimization
When working with large data sets, the following practices help reduce query latency and avoid timeouts.
### Choose the right `page[total_method]`
By default, every list request calculates a `lower_bound` total, which counts up to 10,000 matching records. If you only need to know whether a next page exists (for example, in an infinite-scroll UI), set `page[total_method]=observed`. This skips the full count and only checks for one record beyond the current page, which can significantly reduce response times on large data sets.
| Method | Behavior | Best for |
|----------------|---------------------------------------------------------------------------|--------------------------------------------|
| `lower_bound` | Counts up to 10,000 records; reports exact total or indicates lower bound | Displaying a total count to users |
| `observed` | Checks only if a next page exists beyond the current offset and limit | Infinite scroll, cursor-style pagination |
### Skip sorting when order doesn''t matter
Setting `sort=null` disables sorting entirely. If your use case does not require a specific order (for example, background sync jobs), this avoids the overhead of ordering results and can improve throughput.
### Narrow your filters
Queries that filter on Custom Fields are more efficient when the filter is selective. Prefer exact-match operators (`eq`, `in`) over range or wildcard operators (`like`, `lt`/`le`/`gt`/`ge`) where possible, and combine multiple filters to reduce the result set early.
'
parameters:
- $ref: '#/components/parameters/PageOffset'
- $ref: '#/components/parameters/PageLimit'
- $ref: '#/components/parameters/PageTotalMethod'
- $ref: '#/components/parameters/Filter'
- $ref: '#/components/parameters/CustomAPIEntrySort'
- name: timeout
description: 'Specifies how long in milliseconds the request should be allowed to take. The service will return a 422 if the request takes longer than the specified timeout.
'
in: query
schema:
type: integer
minimum: 1
maximum: 20000
responses:
'200':
$ref: '#/components/responses/ListOfCustomAPIEntries'
'400':
$ref: '#/components/responses/BadFilterError'
'403':
$ref: '#/components/responses/ForbiddenError'
'422':
$ref: '#/components/responses/UnprocessableContentError'
'500':
$ref: '#/components/responses/InternalServerError'
/v2/settings/extensions/custom-apis/{custom-api-id}/entries/{custom-api-entry-id}:
parameters:
- $ref: '#/components/parameters/CustomAPIID'
- $ref: '#/components/parameters/CustomAPIEntryID'
get:
tags:
- Custom API Entries
summary: Get a Custom API Entry
operationId: GetACustomEntry
description: Get a Custom API Entry
responses:
'200':
$ref: '#/components/responses/CustomAPIEntry'
'400':
$ref: '#/components/responses/ValidationError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFoundError'
'500':
$ref: '#/components/responses/InternalServerError'
put:
tags:
- Custom API Entries
summary: Update a Custom API Entry
operationId: UpdateACustomEntry
description: Update a Custom API Entry
parameters:
- $ref: '#/components/parameters/IfMatch'
requestBody:
$ref: '#/components/requestBodies/UpdateCustomAPIEntry'
responses:
'200':
$ref: '#/components/responses/CustomAPIEntry'
'201':
$ref: '#/components/responses/CustomAPIEntry'
'400':
$ref: '#/components/responses/ValidationError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFoundError'
'409':
$ref: '#/components/responses/ConflictError'
'412':
$ref: '#/components/responses/PreConditionError'
'413':
$ref: '#/components/responses/PayloadTooLargeError'
description: Payload Too Large. The total size of a Custom API Entry must not exceed 64KB.
'500':
$ref: '#/components/responses/InternalServerError'
'503':
$ref: '#/components/responses/ServiceUnavailable'
delete:
tags:
- Custom API Entries
summary: Delete a Custom API Entry
operationId: DeleteACustomEntry
description: Delete a Custom API Entry
parameters:
- $ref: '#/components/parameters/IfMatch'
responses:
'204':
description: No Content
'400':
$ref: '#/components/responses/ValidationError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFoundError'
'412':
$ref: '#/components/responses/PreConditionError'
'500':
$ref: '#/components/responses/InternalServerError'
'503':
$ref: '#/components/responses/ServiceUnavailable'
components:
parameters:
PageOffset:
name: page[offset]
description: The current offset by number of records, not pages. Offset is zero-based. The maximum records you can offset is 10,000. If no page size is set, the [page length](/docs/api/settings/settings-introduction#page-length) store setting is used.
in: query
required: false
schema:
type: integer
format: int64
minimum: 0
maximum: 10000
example: 0
Filter:
name: filter
in: query
required: false
description: Filter attributes. For more information, see the [Filtering](/guides/Getting-Started/filtering) section.
schema:
type: string
format: string
example: eq(name,"My Wishlist")
PageLimit:
name: page[limit]
description: The maximum number of records per page for this response. You can set this value up to 100. If no page size is set, the [page length](/docs/api/settings/settings-introduction#page-length) store setting is used.
in: query
required: false
schema:
type: integer
format: int64
minimum: 0
example: 100
PageTotalMethod:
name: page[total_method]
description: 'The method used to calculate the total number of matching entries in the response.
'
in: query
required: false
schema:
type: string
enum:
- lower_bound
- observed
default: lower_bound
x-enumDescriptions:
lower_bound: 'Restricts the count of records to at most 10,000. If there are <=10,000 records, the response will indicate it is an exact total, otherwise it will indicate lower_bound.
'
observed: 'Restricts the count of record to check only if there is a next page. For example if your page[offset] is 0, and page[limit] is 25, and there are 200 records, then with page[total_method]=observed, the response will indicate there are 26, so that the client knows there are more records.
'
CustomAPIEntryID:
name: custom-api-entry-id
description: The unique identifier of the Custom API Entry.
in: path
required: true
schema:
type: string
format: uuid
example: 7e067539-6f6c-46e1-8c55-940031b36c6a
IfMatch:
name: If-Match
description: 'When If-Match is set, the value must be W/"{etag_id}". If the value of the header matches, the request completes. If not, HTTP 412 Precondition Failed is returned.
'
in: header
required: true
schema:
type: string
format: string
CustomAPIID:
name: custom-api-id
description: The unique identifier of the Custom API.
in: path
required: true
schema:
type: string
format: uuid
example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
CustomAPIEntrySort:
name: sort
in: query
description: 'Specifies the order in which Custom API Entries will be returned. For more information, see [Sorting](/guides/Getting-Started/sorting).
'
required: false
schema:
type: string
default: -created_at
enum:
- id
- -id
- created_at
- -created_at
- updated_at
- -updated_at
- 'null'
example: id
x-enumDescriptions:
id: Sort by UUID string in ascending order
-id: Sort by UUID string in descending order
created_at: Sort chronologically from oldest to newest creation date
-created_at: Sort chronologically from newest to oldest creation date
updated_at: Sort chronologically from oldest to newest update date
-updated_at: Sort chronologically from newest to oldest update date
'null': Does not apply any sorting (may improve performance if you don't care about sort)
responses:
ListOfCustomAPIEntries:
description: List of Custom API Entries
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/CustomAPIEntry'
meta:
$ref: '#/components/schemas/PaginationMeta'
links:
$ref: '#/components/schemas/PaginationLinks'
ForbiddenError:
description: Forbidden. You do not have permission to access this resource.
content:
application/json:
schema:
$ref: '#/components/schemas/Errors'
examples:
Forbidden Access:
summary: Forbidden error
value: "{\n \"errors\": [\n {\n \"title\": \"Forbidden\",\n \"status\": \"403\",\n \"detail\": \"You do not have permission to access this resource.\"\n }\n ]\n}\n"
NotFoundError:
description: Not found. The requested entity does not exist.
content:
application/json:
schema:
$ref: '#/components/schemas/Errors'
examples:
Not Found:
summary: Requested entity not found
value: "{\n \"errors\": [\n {\n \"title\": \"Not Found\",\n \"status\": \"404\",\n \"detail\": \"Not found\"\n }\n ]\n}\n"
ConflictError:
description: Unable to perform the operation at this time.
content:
application/json:
schema:
$ref: '#/components/schemas/Errors'
examples:
Duplicate Custom API:
summary: Duplicate Custom API
value: "{\n \"errors\": [\n {\n \"title\": \"Conflict\",\n \"status\": \"409\",\n \"detail\": \"custom_api with the given api_type already exists\"\n }\n ]\n}\n"
Duplicate Custom Field:
summary: Duplicate Custom Field
value: "{\n \"errors\": [\n {\n \"title\": \"Conflict\",\n \"status\": \"409\",\n \"detail\": \"custom_field with the given slug already exists\"\n }\n ]\n}\n"
ValidationError:
description: Bad request. The request failed validation.
content:
application/json:
schema:
$ref: '#/components/schemas/Errors'
examples:
Missing Name:
summary: Required field missing
value: "{\n \"errors\": [\n {\n \"title\": \"Bad Request\",\n \"status\": \"400\",\n \"detail\": \"The field 'name' is required.\"\n }\n ]\n}\n"
ServiceUnavailable:
description: The service is temporarily unavailable. This request can be safely retried.
content:
application/json:
schema:
$ref: '#/components/schemas/Errors'
examples:
Service Unavailable:
summary: Service Unavailable
value: "{\n \"errors\": [\n {\n \"detail\": \"An unknown error occurred\",\n \"status\": \"503\",\n \"title\": \"Service Unavailable\"\n }\n ]\n}\n"
UnprocessableContentError:
description: 'Unprocessable Content. The server couldn''t satisfy your request, most likely due to a timeout.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Errors'
examples:
Unprocessable Content:
summary: Unprocessable content
value: "{\n \"errors\": [\n {\n \"title\": \"Unprocessable Content\",\n \"status\": \"422\",\n \"detail\": \"request timed out after 20000 ms.\"\n }\n ]\n}\n"
InternalServerError:
description: Internal server error. There was a system failure in the platform.
content:
application/json:
schema:
$ref: '#/components/schemas/Errors'
examples:
Internal Server Error:
summary: Internal server error
value: "{\n \"errors\": [\n {\n \"title\": \"Internal Server Error\",\n \"status\": \"500\",\n \"detail\": \"there was a problem processing your request\"\n }\n ]\n}\n"
BadFilterError:
description: Bad request. The request failed validation.
content:
application/json:
schema:
$ref: '#/components/schemas/Errors'
examples:
Bad Filter:
summary: Invalid field specified for filter
value: "{\n \"errors\": [\n {\n \"detail\": \"Invalid filter: unknown field [version] specified in search filter, allowed fields are [api_type created_at description id name slug updated_at]\",\n \"status\": \"400\",\n \"title\": \"Bad Request\"\n }\n ]\n}\n"
PayloadTooLargeError:
description: Payload Too Large.
content:
application/json:
schema:
$ref: '#/components/schemas/Errors'
examples:
Payload Too Large:
summary: Requested entity too large
value: "{\n \"errors\": [\n {\n \"title\": \"Request Entity Too Large\",\n \"status\": \"413\",\n \"detail\": \"Maximum entry size reached.\"\n }\n ]\n}\n"
PreConditionError:
description: Precondition Failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Errors'
examples:
Precondition Failed:
summary: Provided ETag does not match the current ETag.
value: "{\n \"errors\": [\n {\n \"title\": \"Precondition Failed\",\n \"status\": \"412\",\n \"detail\": \"The provided ETag 'W/\\\"4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a\\\"', does not match the current ETag 'W/\\\"ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d\\\"'.\"\n }\n ]\n}\n"
CustomAPIEntry:
description: A Custom API Entry
headers:
ETag:
description: 'A unique identifier representing the current version of the resource. When the resource changes, the ETag value will also change. The ETag hash will be the same value as `etag_id`, and is marked as a weak entity tag string. For example: etag: W/"5feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e9", etag_id: 5feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e9
'
schema:
type: string
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/CustomAPIEntry'
examples:
Custom API Entry:
summary: Default Wishlist
value:
data:
id: 7e067539-6f6c-46e1-8c55-940031b36c6a
type: wishlist_ext
name: My Wishlist
items_count: 0
keep_purchased: false
tags:
- birthday
- gifts
links:
self: /v2/extensions/wishlists/7e067539-6f6c-46e1-8c55-940031b36c6a
meta:
timestamps:
created_at: '2017-01-10T11:41:19.244Z'
updated_at: '2017-01-10T11:41:19.244Z'
resource_version": 0
data_size": 6
etag_id": 5feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e9
schemas:
Timestamps:
type: object
properties:
created_at:
type: string
description: Specifies the date the entity is created.
example: '2017-01-10T11:41:19.244Z'
updated_at:
type: string
description: Specifies the date the entity is last updated.
example: '2017-01-10T11:41:19.244Z'
Meta:
type: object
properties:
timestamps:
$ref: '#/components/schemas/Timestamps'
Errors:
required:
- errors
properties:
errors:
type: array
items:
type: object
required:
- status
- title
properties:
status:
type: string
description: The HTTP response code of the error.
format: string
examples:
- '400'
title:
type: string
description: A brief summary of the error.
examples:
- Bad Request
detail:
type: string
description: Optional additional detail about the error.
examples:
- The field 'name' is required
LinkURI:
type:
- string
- 'null'
format: uri
CustomAPIEntry:
type: object
additionalProperties: true
properties:
id:
type: string
description: The unique identifier for the Custom API Entry.
format: uuid
type:
type: string
description: 'Specifies the type of the resource object, use the `api_type` of the [Custom API](/docs/api/commerce-extensions/create-a-custom-api) for Custom API Entry.
'
examples:
- wishlist_ext
links:
type: object
properties:
self:
$ref: '#/components/schemas/LinkURI'
description: Specifies the URI of the Custom API Entry.
example: /v2/extensions/wishlists/7e067539-6f6c-46e1-8c55-940031b36c6a
meta:
allOf:
- $ref: '#/components/schemas/Meta'
- type: object
properties:
data_size:
type: integer
description: 'The approximate size of the data, used to enforce size limits as this value must not exceed 64 KiB. The exact calculation is intentionally unspecified to allow storage optimizations. This value will always be less than or equal to the size of the JSON representation of all field values.
'
default: 0
example: 6
resource_version:
type: integer
description: 'A unique identifier representing the current version of the resource. When the resource changes, the `resource_version` value will also change.
'
default: 0
example: 4
etag_id:
type: string
description: 'A unique identifier representing the current version of the resource that is a hashed string. When the resource changes, the `etag_id` will also change.
'
example: 6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b
PaginationMeta:
type: object
properties:
results:
type: object
properties:
total:
type: integer
description: Total number of results for the entire collection.
total_method:
type: string
description: The method used to calculate the total number results.
enum:
- exact
- lower_bound
- observed
x-enumDescriptions:
exact: Indicates that the total is an exact count of results
lower_bound: When there are more than 10,000 results, we stop counting at 10,000 and report that the count is a lower_bound.
observed: Will indicate if there is at least one more result past the current page, this is the highest performing option as it doesn't require an extra call.
page:
type: object
properties:
limit:
type: integer
description: The maximum number of records for all pages.
example: 100
offset:
type: integer
description: The current offset by number of pages.
example: 0
current:
type: integer
description: The current number of pages.
example: 1
total:
type: integer
description: The total number of pages.
example: 1
PaginationLinks:
type: object
properties:
current:
$ref: '#/components/schemas/LinkURI'
description: Always the current page.
example: /v2/settings/custom-apis?page[offset]=0&page[limit]=100
first:
$ref: '#/components/schemas/LinkURI'
description: Always the first page.
example: /v2/settings/custom-apis?page[offset]=0&page[limit]=100
last:
$ref: '#/components/schemas/LinkURI'
description: Always `null` if there is only one page.
example: /v2/settings/custom-apis?page[offset]=0&page[limit]=100
next:
$ref: '#/components/schemas/LinkURI'
description: Always `null` if there is only one page.
example: null
prev:
$ref: '#/components/schemas/LinkURI'
description: Always `null` if on the first page.
example: null
requestBodies:
CreateCustomAPIEntry:
content:
application/json:
schema:
type: object
required:
- data
properties:
data:
type: object
required:
- type
additionalProperties: true
properties:
type:
type: string
description: 'Specifies the type of the resource object, use the `api_type` of the [Custom API](/docs/api/commerce-extensions/create-a-custom-api) for Custom API Entry.
'
examples:
- wishlist_ext
examples:
Create Example:
summary: Create a Wishlist
value:
data:
type: wishlist_ext
name: My Wishlist
items_count: 0
keep_purchased: false
tags:
- birthday
- gifts
UpdateCustomAPIEntry:
content:
application/json:
schema:
type: object
required:
- data
properties:
data:
type: object
required:
- type
additionalProperties: true
properties:
type:
type: string
description: 'Specifies the type of the resource object, use the `api_type` of the [Custom API](/docs/api/commerce-extensions/create-a-custom-api) for Custom API Entry.
'
examples:
- wishlist_ext
examples:
Update Example:
summary: Update a Wishlist
value:
data:
type: wishlist_ext
name: My Wishlist
items_count: 1
keep_purchased: false
tags:
- birthday
- gifts
- priority
securitySchemes:
BearerToken:
type: http
scheme: bearer