1578 lines
33 KiB
Plaintext
1578 lines
33 KiB
Plaintext
import SectionContainer from "@/components/Section/Container"
|
|
import DividedMarkdownLayout from "@/layouts/DividedMarkdown"
|
|
import {
|
|
DividedMarkdownContent,
|
|
DividedMarkdownCode
|
|
} from "@/layouts/DividedMarkdown/Sections"
|
|
import Section from "@/components/Section"
|
|
import { CodeTabs, CodeTab, H1, Prerequisites } from "docs-ui"
|
|
import { Feedback } from "@/components/Feedback"
|
|
|
|
import ClientLibraries from "./client-libraries.mdx"
|
|
|
|
<Section checkActiveOnScroll>
|
|
|
|
<SectionContainer noTopPadding={true}>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
<H1 className={"!h2-docs scroll-m-[184px] lg:scroll-m-[264px]"} id="introduction">Medusa V2 Store API Reference</H1>
|
|
|
|
This API reference includes Medusa v2's Store APIs, which are REST APIs exposed by the Medusa application. They are used to create a storefront for your commerce store, such as a webshop or a commerce mobile app.
|
|
|
|
All API Routes are prefixed with `/store`. So, during development, the API Routes will be available under the path `http://localhost:9000/store`. For production, replace `http://localhost:9000` with your Medusa application URL.
|
|
|
|
<Feedback
|
|
extraData={{
|
|
section: "introduction"
|
|
}}
|
|
question="Was this section helpful?"
|
|
/>
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<ClientLibraries />
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
</SectionContainer>
|
|
|
|
<SectionContainer noTopPadding={true}>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
## Authentication
|
|
|
|
There are two ways to send authenticated requests to the Medusa application: Using a JWT token or using a Cookie Session ID.
|
|
|
|
### 1. Bearer Authorization with JWT Tokens
|
|
|
|
Use a JWT token in a request's bearer authorization header to send authenticated requests. Authentication state is managed by the client, which is ideal for Jamstack applications and mobile applications.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
#### How to Obtain the JWT Token
|
|
|
|
To obtain a JWT token, send a request to the [authentication route](#auth_postactor_typeauth_provider) passing it the customer's email and password in the request body.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Obtain JWT token"
|
|
token = await sdk.auth.login("customer", "emailpass", {
|
|
email,
|
|
password
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Obtain JWT token"
|
|
curl -X POST '{backend_url}/auth/customer/emailpass' \
|
|
-H 'Content-Type: application/json' \
|
|
--data-raw '{
|
|
"email": "user@example.com",
|
|
"password": "supersecret"
|
|
}'
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
If authenticated successfully, an object is returned in the response with the property `token` being the JWT token.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
```json title="Example response"
|
|
{
|
|
"token": "123..."
|
|
}
|
|
```
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
#### How to Use the JWT Token
|
|
|
|
To use the JWT token, pass it in the authorization bearer header.
|
|
|
|
If you're using the JS SDK, the `login` method automatically sets the token for you and passes it to subsequent requests. You can also set the token manually using the `client.setToken` method.
|
|
|
|
<Note>
|
|
|
|
Make sure you've set the `auth.type` configuration of the JS SDK to `jwt` to use the JWT token. Learn more in the [JS SDK configurations](!resources!/js-sdk#js-sdk-configurations).
|
|
|
|
</Note>
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
```bash title="Use JWT token"
|
|
Authorization: Bearer {jwt_token}
|
|
```
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### 2. Cookie Session ID
|
|
|
|
When you authenticate a customer and create a cookie session ID for them, the cookie session ID is passed automatically when sending the request from the browser, or with tools like Postman.
|
|
|
|
### How to Obtain the Cookie Session
|
|
|
|
To obtain a cookie session ID, you must have a [JWT token for bearer authentication](#1-bearer-authorization-with-jwt-tokens).
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
Then, if you're using the JS SDK, make sure the `auth.type` configuration is set to `session`, as explained in the [JS SDK configurations](!resources!/js-sdk#js-sdk-configurations) guide. The `auth.login` method will handle setting the session cookie and passing it in subsequent requests.
|
|
|
|
If you're not using the JS SDK, send a request to the [session authentication API route](#auth_postsession). To view the cookie session ID, pass the `-v` option to the `curl` command.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
```bash title="Obtain cookie session"
|
|
curl -v -X POST '{backend_url}/auth/session' \
|
|
--header 'Authorization: Bearer {jwt_token}'
|
|
```
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
If you send the `cURL` request, the headers will be logged in the terminal as well as the response. You
|
|
should find in the headers a Cookie header.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
```bash title="Logged cookie session"
|
|
Set-Cookie: connect.sid=s%3A2Bu8B...;
|
|
```
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
#### How to Use the Cookie Session ID in cURL
|
|
|
|
If you're using the JS SDK, it will pass the cookie session with every request automatically after you use the `auth.login` method.
|
|
|
|
If you're not using the JS SDK, copy the value after `connect.sid` (without the `;` at the end) and pass
|
|
it as a cookie in subsequent requests.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
```bash title="Use cookie session"
|
|
curl '{backend_url}/store/products' \
|
|
-H 'Cookie: connect.sid={sid}'
|
|
```
|
|
|
|
Where `{sid}` is the value of `connect.sid` that you copied.
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
#### Including Credentials in the Fetch API
|
|
|
|
If you're sending requests using JavaScript's Fetch API, you must pass the `credentials` option
|
|
with the value `include` to all the requests you're sending.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
```js title="Include credentials in fetch"
|
|
fetch(`<BACKEND_URL>/store/products`, {
|
|
credentials: "include",
|
|
})
|
|
```
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<Feedback
|
|
extraData={{
|
|
section: "authentication-cookie"
|
|
}}
|
|
question="Was this section helpful?"
|
|
/>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
</SectionContainer>
|
|
|
|
<SectionContainer noTopPadding={true}>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
## Publishable API Key
|
|
|
|
You must pass a publishable API key in the header of your requests to the store API routes.
|
|
|
|
Publishable API Keys sets the scope of your request to one or more sales channels. This ensures you only
|
|
retrieve products available in the publishable API key's sales channels, retrieve correct inventory details,
|
|
and associate placed orders with the specified sales channel.
|
|
|
|
### How to Create a Publishable API Key
|
|
|
|
Create a publishable API key either using the [admin REST APIs](https://docs.medusajs.com/api/admin#api-keys_postapikeys), or using the [Medusa Admin](!user-guide!/settings/developer/publishable-api-keys#create-publishable-api-key).
|
|
|
|
### How to Use a Publishable API Key
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
If you're using the JS SDK, set the publishable API key in the JS SDK's configurations.
|
|
|
|
If you're not using the JS SDK, pass the publishable API key in the header `x-publishable-api-key` in all your requests to the store APIs.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Use publishable API key"
|
|
import Medusa from "@medusajs/js-sdk"
|
|
|
|
export const sdk = new Medusa({
|
|
// other configurations...
|
|
publishableKey: "{your_publishable_api_key}",
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Use publishable API key"
|
|
curl 'http://localhost:9000/store/products' \
|
|
-H 'x-publishable-api-key: {your_publishable_api_key}'
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
Where `{your_publishable_api_key}` is the token of the publishable API key. When using the JS SDK, set the value as an environment variable.
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<Feedback
|
|
extraData={{
|
|
section: "publishable-api-key"
|
|
}}
|
|
question="Was this section helpful?"
|
|
/>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
</SectionContainer>
|
|
|
|
<SectionContainer noTopPadding={true}>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
## HTTP Compression
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
If you've enabled HTTP Compression in your Medusa configurations, and you
|
|
want to disable it for some requests, you can pass the `x-no-compression`
|
|
header in your requests.
|
|
|
|
If you're using the JS SDK, every method accepts a `headers` parameter as the last parameter. You can pass in it custom headers, including the `x-no-compression` header.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Disable HTTP compression"
|
|
sdk.store.product.list({
|
|
limit,
|
|
offset,
|
|
}, {
|
|
"x-no-compression": "false",
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Disable HTTP compression"
|
|
x-no-compression: false
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<Feedback
|
|
extraData={{
|
|
section: "http-compression"
|
|
}}
|
|
question="Was this section helpful?"
|
|
/>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
</SectionContainer>
|
|
|
|
<SectionContainer noTopPadding={true}>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
## Manage Metadata
|
|
|
|
Many data models in Medusa, such as products and carts, have a `metadata` field that allows you to store custom information in key-value pairs.
|
|
|
|
When setting or updating the `metadata` field using the relevant API routes, Medusa will merge the new metadata with the existing metadata.
|
|
|
|
<Note>
|
|
|
|
The instructions in this section apply to any [JSON property in a data model](!docs!/learn/fundamentals/data-models/json-properties).
|
|
|
|
</Note>
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Accepted Values in Metadata
|
|
|
|
The `metadata` is an object of key-value pairs, where the keys are strings and the values can be one of the following types:
|
|
|
|
- String
|
|
- An empty string deletes the property from the metadata.
|
|
- Number
|
|
- Boolean
|
|
- Date
|
|
- Object
|
|
- Arrays of any of the above types
|
|
|
|
The `metadata` is not validated, so you can store any custom data in it.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
```ts title="Metadata Example"
|
|
{
|
|
"metadata": {
|
|
"category": "electronics",
|
|
"views": 1500,
|
|
"is_featured": true,
|
|
"tags": ["new", "sale"],
|
|
"details": {
|
|
"warranty": "2 years",
|
|
"origin": "USA"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Add or Update New Property in Metadata
|
|
|
|
To add or update a property in the `metadata`, pass the property in the request body as a key-value pair. This won't affect existing properties in the metadata.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-with-result">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Add new metadata property"
|
|
sdk.store.cart.updateLineItem(
|
|
"cart_123",
|
|
"li_123",
|
|
{
|
|
metadata: {
|
|
new_property: "value"
|
|
}
|
|
}
|
|
)
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="Result" value="result">
|
|
|
|
```json title="Result"
|
|
{
|
|
"id": "cart_123",
|
|
"items": [
|
|
{
|
|
"id": "li_123",
|
|
"metadata": {
|
|
"new_property": "value",
|
|
"old_property": "value"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Update Nested Objects in Metadata
|
|
|
|
When updating a nested object in the `metadata`, you must pass the entire object in the request body.
|
|
|
|
Medusa doesn't merge nested objects, so if you pass a partial object, the existing properties in the nested object will be removed.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-with-result">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Update nested object in metadata"
|
|
sdk.store.cart.updateLineItem(
|
|
"cart_123",
|
|
"li_123",
|
|
{
|
|
metadata: {
|
|
nested_object: {
|
|
property1: "value1",
|
|
property2: "value2"
|
|
}
|
|
}
|
|
}
|
|
)
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="Result" value="result">
|
|
|
|
```json title="Result"
|
|
{
|
|
"id": "cart_123",
|
|
"items": [
|
|
{
|
|
"id": "li_123",
|
|
"metadata": {
|
|
"nested_object": {
|
|
"property1": "value1",
|
|
"property2": "value2"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Remove Property from Metadata
|
|
|
|
To remove a property from the `metadata`, pass the property in the request body with an empty string value. This will remove the property from the `metadata` without affecting other properties.
|
|
|
|
<Feedback
|
|
extraData={{
|
|
section: "metadata"
|
|
}}
|
|
question="Was this section helpful?"
|
|
/>
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-with-result">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Remove metadata property"
|
|
sdk.store.cart.updateLineItem(
|
|
"cart_123",
|
|
"li_123",
|
|
{
|
|
metadata: {
|
|
property_to_remove: ""
|
|
}
|
|
}
|
|
)
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="Result" value="result">
|
|
|
|
```json title="Result"
|
|
{
|
|
"id": "cart_123",
|
|
"items": [
|
|
{
|
|
"id": "li_123",
|
|
"metadata": {
|
|
"other_property": "value"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
</SectionContainer>
|
|
|
|
<SectionContainer noTopPadding={true}>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
## Select Fields and Relations
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
Many API Routes accept a `fields` query that allows you to select which fields and relations should be returned in a record.
|
|
Fields and relations are separated by a comma `,`.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Select fields"
|
|
sdk.store.product.list({
|
|
fields: "title,handle"
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Select fields"
|
|
curl 'localhost:9000/store/products?fields=title,handle'
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
This returns only the `title` and `handle` fields of a product.
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Fields Operator
|
|
|
|
By default, only the selected fields and relations are returned in the response.
|
|
|
|
Before every field or relation, you can pass one of the following operators to change the default behavior:
|
|
|
|
- `+`: Add the field to the fields returned by default. For example, `+title` returns the `title` field along with the fields returned by default.
|
|
- `-`: Remove the field from the fields returned by default. For example, `-handle` removes the `handle` field from the fields returned by default.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Select relations"
|
|
sdk.store.product.list({
|
|
fields: "+title,-handle"
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Select relations"
|
|
curl 'localhost:9000/store/products?fields=+title,-handle'
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
This returns the products, each of them having their `title` field, but without the `handle` field.
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing codeContentClassName="mt-3">
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Select Relations
|
|
|
|
To select a relation, pass to `fields` the relation name prefixed by `*`.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Select relations"
|
|
sdk.store.product.list({
|
|
fields: "*variants"
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Select relations"
|
|
curl 'localhost:9000/store/products?fields=*variants'
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
This returns the variants of each product.
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
To select multiple relations, pass each of the relations with the `*` prefix, separated by a comma.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Select relation's fields"
|
|
sdk.store.product.list({
|
|
fields: "*variants,*options"
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Select relation's fields"
|
|
curl 'localhost:9000/store/products?fields=*variants,*options'
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
This returns the variants and options of each product.
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Select Fields in a Relation
|
|
|
|
The `*` prefix selects all fields of the relation's data model.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
To select a specific field, pass a `.<field>` suffix instead of the `*` prefix. For example, `variants.title`.
|
|
|
|
To specify multiple fields, pass each of the fields with the `<relation>.<field>` format, separated by a comma. You can do the same for multiple relations.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Select relation's fields"
|
|
sdk.store.product.list({
|
|
fields: "variants.title,variants.sku,options.title"
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Select relation's fields"
|
|
curl 'localhost:9000/store/products?fields=variants.title,variants.sku,options.title'
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
This returns the variants and options of each product, but the variants only have their `id`, `title`, and `sku` fields, and the options only have their `id` and `title` fields. The `id` is always included.
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Select Custom Linked Data Models
|
|
|
|
Most of the API routes that accept a `fields` query parameter allow you to specify custom linked data models. For example, if you linked a `Brand` to a `Product`, you can pass `brand` in the `fields` query parameter to retrieve the brand of each product.
|
|
|
|
However, some API routes restrict the fields and relations you can retrieve. To learn about those API routes and how to override the allowed fields and relations, refer to the [Retrieve Custom Linked Data Models from Medusa's API routes](!docs!/learn/fundamentals/api-routes/retrieve-custom-links) documentation.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<Feedback
|
|
extraData={{
|
|
section: "select-fields"
|
|
}}
|
|
question="Was this section helpful?"
|
|
/>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
</SectionContainer>
|
|
|
|
<SectionContainer noTopPadding={true}>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
## Query Parameter Types
|
|
|
|
|
|
This section covers how to pass some common data types as query parameters.
|
|
|
|
This is useful if you're sending requests to the API Routes using cURL or Postman.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing codeContentClassName="mt-3">
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Strings
|
|
|
|
|
|
You can pass a string value in the form of `<parameter_name>=<value>`.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="String filter"
|
|
sdk.store.product.list({
|
|
title: "Shirt"
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="String filter"
|
|
curl "http://localhost:9000/store/products?title=Shirt"
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
If the string has any characters other than letters and numbers, you must
|
|
encode them. For example, if the string has spaces, you can encode the space with `+` or
|
|
`%20`.
|
|
|
|
When using the JS SDK, you can pass the string directly to the query parameter. The JS SDK will encode the string for you.
|
|
|
|
You can use tools like [this one](https://www.urlencoder.org/) to learn how
|
|
a value can be encoded.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Encoded string filter"
|
|
sdk.store.product.list({
|
|
title: "Blue Shirt"
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Encoded string filter"
|
|
curl "http://localhost:9000/store/products?title=Blue%20Shirt"
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing codeContentClassName="mt-3">
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Integers
|
|
|
|
You can pass an integer value in the form of `<parameter_name>=<value>`.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Integer filter"
|
|
sdk.store.product.list({
|
|
offset: 1
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Integer filter"
|
|
curl "http://localhost:9000/store/products?offset=1"
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing codeContentClassName="mt-3">
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Boolean
|
|
|
|
|
|
You can pass a boolean value in the form of `<parameter_name>=<value>`.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Boolean filter"
|
|
sdk.store.product.list({
|
|
is_giftcard: true
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Boolean filter"
|
|
curl "http://localhost:9000/store/products?is_giftcard=true"
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing codeContentClassName="mt-3">
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Date and DateTime
|
|
|
|
|
|
You can pass a date value in the form `<parameter_name>=<value>`. The date
|
|
must be in the format `YYYY-MM-DD`.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Date filter"
|
|
sdk.store.product.list({
|
|
created_at: { $lt: "2023-02-17" }
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Date filter"
|
|
curl -g "http://localhost:9000/store/products?created_at[$lt]=2023-02-17"
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
You can also pass the time using the format `YYYY-MM-DDTHH:MM:SSZ`. Please
|
|
note that the `T` and `Z` here are fixed.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Date and time filter"
|
|
sdk.store.product.list({
|
|
created_at: { $lt: "2023-02-17T07:22:30Z" }
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Date and time filter"
|
|
curl -g "http://localhost:9000/store/products?created_at[$lt]=2023-02-17T07:22:30Z"
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing codeContentClassName="mt-3">
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Array
|
|
|
|
Array filters can be passed either as:
|
|
|
|
- `<parameter_name>[]=<value1>,<value2>`, separating the values by a comma.
|
|
- `<parameter_name>[]=<value1>&<parameter_name>[]=<value2>`, passing each value as a separate query parameter. You can also specify the index of each
|
|
parameter in the brackets `<parameter_name>[0]=<value>`.
|
|
|
|
When using the JS SDK, you can pass the array directly to the query parameter. The JS SDK will handle the rest.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="array-filter">
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Array filter"
|
|
sdk.store.product.list({
|
|
sales_channel_id: ["sc_123", "sc_456"]
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
<CodeTab label="Comma-separated" value="comma-separated">
|
|
|
|
```bash
|
|
curl -g "http://localhost:9000/store/products?sales_channel_id[]=sc_123,sc_456"
|
|
```
|
|
|
|
</CodeTab>
|
|
<CodeTab label="Separate parameters" value="separate-query-parameters">
|
|
|
|
```bash
|
|
curl -g "http://localhost:9000/store/products?sales_channel_id[]=sc_123&sales_channel_id[]=sc_456"
|
|
```
|
|
|
|
</CodeTab>
|
|
</CodeTabs>
|
|
|
|
Note that the `-g` parameter passed to `curl` disables errors being thrown
|
|
for using the brackets. Read more
|
|
[here](https://curl.se/docs/manpage.html#-g).
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing codeContentClassName="mt-3">
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Object
|
|
|
|
|
|
Object parameters must be passed as separate query parameters in the form
|
|
`<parameter_name>[<key>]=<value>`.
|
|
|
|
When using the JS SDK, you can pass the object directly to the query parameter. The JS SDK will handle the rest.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Object filter"
|
|
sdk.store.product.list({
|
|
created_at: { $lt: "2023-02-17", $gt: "2022-09-17" }
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Object filter"
|
|
curl -g "http://localhost:9000/store/products?created_at[$lt]=2023-02-17&created_at[$gt]=2022-09-17"
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<Feedback
|
|
extraData={{
|
|
section: "query-parameters"
|
|
}}
|
|
question="Was this section helpful?"
|
|
/>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
</SectionContainer>
|
|
|
|
<SectionContainer noTopPadding={true}>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
## Pagination
|
|
|
|
|
|
### Query Parameters
|
|
|
|
|
|
In listing API Routes, such as list products, you can control the pagination using the query parameters `limit` and `offset`.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
`limit` is used to specify the maximum number of items to be returned in the response. `offset` is used to specify how many items to skip before returning the resulting records.
|
|
|
|
|
|
Use the `offset` query parameter to change between pages. For example, if the limit is `50`, at page `1` the offset should be `0`; at page `2` the offset should be `50`, and so on.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Pagination query parameters"
|
|
sdk.store.product.list({
|
|
limit: 5,
|
|
offset: 0
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Pagination query parameters"
|
|
curl "http://localhost:9000/store/products?limit=5&offset=0"
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Response Fields
|
|
|
|
|
|
In the response of listing API Routes, aside from the records retrieved,
|
|
there are three pagination-related fields returned:
|
|
|
|
|
|
- `limit`: the maximum number of items that can be returned in the response.
|
|
- `offset`: the number of items that were skipped before the records in the result.
|
|
- `count`: the total number of available items of this data model. It can be used to determine how many pages are there.
|
|
|
|
|
|
For example, if the `count` is `100` and the `limit` is `50`, divide the
|
|
`count` by the `limit` to get the number of pages: `100/50 = 2 pages`.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing codeContentClassName="mt-3">
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
### Sort Order
|
|
|
|
|
|
The `order` field (available on API Routes that support pagination) allows you to
|
|
sort the retrieved items by a field of that item.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Ascending sort by a field"
|
|
sdk.store.product.list({
|
|
order: "created_at"
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Ascending sort by a field"
|
|
curl "http://localhost:9000/store/products?order=created_at"
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
This sorts the products by their `created_at` field in the ascending order.
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
By default, the sort direction is ascending. To change it to
|
|
descending, pass a dash (`-`) before the field name.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-examples">
|
|
|
|
<CodeTab label="JS SDK" value="js-sdk">
|
|
|
|
```js title="Descending sort by a field"
|
|
sdk.store.product.list({
|
|
order: "-created_at"
|
|
})
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="cURL" value="curl">
|
|
|
|
```bash title="Descending sort by a field"
|
|
curl "http://localhost:9000/store/products?order=-created_at"
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
This sorts the products by their `created_at` field in the descending order.
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<Feedback
|
|
extraData={{
|
|
section: "pagination"
|
|
}}
|
|
question="Was this section helpful?"
|
|
/>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
</SectionContainer>
|
|
|
|
<SectionContainer noTopPadding={true}>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
## Workflows
|
|
|
|
While browsing this reference, you'll find some API routes mention what workflow is used in them.
|
|
|
|
If you click on the workflow, you'll view a reference of that workflow, including its hooks.
|
|
|
|
This is useful if you want to extend an API route and pass additional data or perform custom actions.
|
|
|
|
Refer to [this guide](!docs!/learn/customization/extend-features/extend-create-product) to find an example of extending an API route.
|
|
|
|
<Feedback
|
|
extraData={{
|
|
section: "workflows"
|
|
}}
|
|
question="Was this section helpful?"
|
|
/>
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
</SectionContainer>
|
|
|
|
<SectionContainer noTopPadding={true}>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
## Localization
|
|
|
|
<Prerequisites
|
|
items={[
|
|
{
|
|
text: "Translation Module Configured",
|
|
link: "!resources!/commerce-modules/translation#configure-translation-module",
|
|
}
|
|
]}
|
|
/>
|
|
|
|
Medusa's Store APIs support localization of core and custom data models. Refer to the [Translation Module](!resources!/commerce-modules/translation) guide to learn about supported core data models, and how to [configure translations for custom data models](!resources!/commerce-modules/translation/custom-data-models).
|
|
|
|
By default, the Store APIs returns the original data without localization.
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout addYSpacing>
|
|
|
|
<DividedMarkdownContent>
|
|
|
|
You can set the locale of a request using one of the following methods:
|
|
|
|
- Use the JS SDK's `setLocale` method. The JS SDK will automatically include the locale in the `x-medusa-locale` header of subsequent requests.
|
|
- Pass the `locale` query parameter to the relevant API route. By default, all `/store` API routes support the `locale` query parameter.
|
|
- Set the `x-medusa-locale` header in the API request to the relevant API route. By default, all `/store` API routes support the `x-medusa-locale` header.
|
|
|
|
Locales are in the [IETF BCP 47](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1) format, such as `en-US` for American English, or `fr-FR` for French.
|
|
|
|
The returned data will be in the specified locale if a translation exists. Otherwise, it will fall back to the original data.
|
|
|
|
Learn more in the [Storefront Localization guide](!resources!/storefront-development/localization).
|
|
|
|
</DividedMarkdownContent>
|
|
|
|
<DividedMarkdownCode>
|
|
|
|
<CodeTabs group="request-localization-examples">
|
|
|
|
<CodeTab label="Using JS SDK" value="js-sdk">
|
|
|
|
```js
|
|
sdk.setLocale("fr-FR")
|
|
// products content will be in French
|
|
const { products } = await sdk.store.product.list()
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
<CodeTab label="Using Query Parameter" value="query-param">
|
|
|
|
```bash
|
|
curl "http://localhost:9000/store/products?locale=fr-FR" \
|
|
-H 'x-publishable-api-key: {your_publishable_api_key}'
|
|
```
|
|
|
|
</CodeTab>
|
|
<CodeTab label="Using Header" value="header">
|
|
|
|
```bash
|
|
curl "http://localhost:9000/store/products" \
|
|
-H 'x-publishable-api-key: {your_publishable_api_key}' \
|
|
-H "x-medusa-locale: fr-FR"
|
|
```
|
|
|
|
</CodeTab>
|
|
|
|
</CodeTabs>
|
|
|
|
|
|
</DividedMarkdownCode>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
<DividedMarkdownLayout>
|
|
|
|
<Feedback
|
|
extraData={{
|
|
section: "localization"
|
|
}}
|
|
question="Was this section helpful?"
|
|
/>
|
|
|
|
</DividedMarkdownLayout>
|
|
|
|
</SectionContainer>
|
|
|
|
</Section> |