> ## Documentation Index
> Fetch the complete documentation index at: https://docs.launchmystore.io/llms.txt
> Use this file to discover all available pages before exploring further.

# List Metafields

> List the metafields your app has written

# List Metafields

Returns metafields written by **your app** (scoped by `appId`). Filter by
owner type, owner id, namespace, or key.

<Note>
  This endpoint returns only the metafields your app has written. To list
  all metafields on a resource (including those written by other apps or
  merchants), the merchant must use the Admin API
  (`GET /metafields?ownerType=...&ownerId=...`).
</Note>

## Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.launchmystore.io/api/v1/metafields.json?owner_type=product&owner_id=<productId>" \
    -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
  ```

  ```javascript Node.js theme={null}
  const url = new URL('https://api.launchmystore.io/api/v1/metafields.json');
  url.searchParams.set('owner_type', 'product');
  url.searchParams.set('owner_id', productId);

  const response = await fetch(url, {
    headers: { Authorization: `Bearer ${accessToken}` },
  });
  const { data } = await response.json();
  ```
</CodeGroup>

## Required scope

`read_metafields`

## Query parameters

<ParamField query="owner_type" type="string">
  Filter by owner type. One of `shop`, `product`, `variant`,
  `collection`, `customer`, `order`, `page`, `blog`, `article`. **Lowercase
  only.** Both casings are accepted: `owner_type` and `ownerType` behave identically.
</ParamField>

<ParamField query="owner_id" type="string">
  Filter by the owning resource id. Not enforced by the API, but
  strongly recommended for every owner type *except* `shop` — without it
  you get all rows of that owner type. Both casings are accepted:
  `owner_id` and `ownerId` behave identically.
</ParamField>

<ParamField query="namespace" type="string">
  Filter by namespace.
</ParamField>

<ParamField query="key" type="string">
  Filter by exact key.
</ParamField>

<ParamField query="page" type="integer" default="1">
  1-indexed page number.
</ParamField>

<ParamField query="limit" type="integer" default="50">
  Items per page. The API applies no hard cap; keep requests to 250 or
  fewer as a practical limit.
</ParamField>

## Response

<ResponseField name="status" type="integer">
  HTTP status code (200 on success).
</ResponseField>

<ResponseField name="state" type="string">
  `success` or `error`.
</ResponseField>

<ResponseField name="data.metafields" type="array">
  Array of metafield objects.

  <Expandable title="Metafield Object">
    Raw DB row (camelCase). The value is **not** decoded — it is returned as
    the stored string.
    <ResponseField name="metafieldId" type="string">UUID</ResponseField>
    <ResponseField name="namespace" type="string">e.g. `custom`</ResponseField>
    <ResponseField name="key" type="string">e.g. `warranty_years`</ResponseField>
    <ResponseField name="value" type="string">the stored string (canonical wire form; scalars stringified, compound types JSON-encoded). Not decoded.</ResponseField>
    <ResponseField name="type" type="string">the stored type</ResponseField>
    <ResponseField name="ownerType" type="string">resource kind</ResponseField>
    <ResponseField name="ownerId" type="string">resource id</ResponseField>
    <ResponseField name="appId" type="string">your app's id (always your own)</ResponseField>
    <ResponseField name="createdAt" type="string">ISO timestamp</ResponseField>
    <ResponseField name="updatedAt" type="string">ISO timestamp</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="data.total" type="integer">Total matching records.</ResponseField>
<ResponseField name="data.page" type="integer">Current page.</ResponseField>
<ResponseField name="data.limit" type="integer">Page size.</ResponseField>

## Example response

```json theme={null}
{
  "status": 200,
  "state": "success",
  "data": {
    "metafields": [
      {
        "metafieldId": "e607f43e-9251-451e-a45c-38bf28d61154",
        "namespace": "custom",
        "key": "badge",
        "value": "BESTSELLER",
        "type": "single_line_text_field",
        "ownerType": "product",
        "ownerId": "e5f6a7b8-9c0d-4e1f-a2b3-c4d5e6f7a8b9",
        "appId": "your-app-id",
        "createdAt": "2026-05-09T13:32:53.135Z",
        "updatedAt": "2026-05-09T13:32:53.135Z"
      },
      {
        "metafieldId": "48b24b31-b1a4-4997-9827-a1668a886ea6",
        "namespace": "custom",
        "key": "warranty_years",
        "value": "5",
        "type": "number_integer",
        "ownerType": "product",
        "ownerId": "e5f6a7b8-9c0d-4e1f-a2b3-c4d5e6f7a8b9",
        "appId": "your-app-id",
        "createdAt": "2026-05-09T13:32:53.135Z",
        "updatedAt": "2026-05-09T13:32:53.135Z"
      }
    ],
    "total": 2,
    "page": 1,
    "limit": 50
  }
}
```

## Error codes

| Code | Description |
| - | - |
| `UNAUTHORIZED` | Invalid or missing access token |
| `FORBIDDEN` | App doesn't have `read_metafields` scope |
| `VALIDATION_ERROR` | Invalid `ownerType` value |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.