---
title: Shop User Custom Data
description: Use the Shop User Custom Data API to store and retrieve custom data on Shop users.
source_url:
  html: https://shopify.dev/docs/api/shop-user-custom-data
  md: https://shopify.dev/docs/api/shop-user-custom-data.md
---

# Shop User Custom Data

**Caution:**

Work In Progress: This API is in closed beta.

You can use the Shop User Custom Data API to store and retrieve custom data on [Shop](https://shop.app) users as well as define [Shopify Functions](https://shopify.dev/docs/api/functions/index) that refer to custom data set on a Shop user.

This guide shows you how to manage Shop User Custom Data using the GraphQL Admin API.

***

## Requirements

Usage of the Shop User Custom Data API is by invitation only.

* For managing metafield definitions, you need a `client_id` and `client_secret` provided by the Shop team.
* For setting or getting metafields, you need user Access Tokens provided by the Shop system (for example, as a result of a [sign in with Shop flow](https://help.shopify.com/en/manual/customers/customer-accounts/classic-customer-accounts#sign-in-with-shop), or as part of an order created event to your webhook).

***

## Endpoints

### For Managing Metafield Definitions

```text
https://shop.app/api/{api-version}/partners/graphql.json
```

Authorization is with a `Basic Auth` HTTP header:

```text
Authorization: Basic base64-encode({client_id}:{client_secret})
```

In other words, the word `Basic`, followed by a base64-encoded string of your `client_id` and `client_secret`, separated by a `:`.

### For Managing Metafields

```text
https://shop.app/api/{api-version}/users/graphql.json
```

Authorization is with a `Bearer Auth` HTTP header:

```text
Authorization: Bearer {access_token}
```

In other words, user-scoped authorization using a user's Access Token.

***

## Managing Metafield Definitions

### Create

The following example creates a metafield definition for a key called `acme-id`, with [metafield type](https://shopify.dev/docs/apps/custom-data/metafields/types) `single_line_text_field`.

The supported metafield types are:

* `boolean`

* `date_time`

* `json`

* `multi_line_text_field`

* `number_decimal`

* `number_integer`

* `single_line_text_field`

  We expect to support all [metafield types](https://shopify.dev/docs/apps/custom-data/metafields/types) eventually.

  `SHOP_USER` is the only allowed `ownerType` for this API endpoint.

## POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json

## GraphQL mutation

```graphql
mutation MetafieldDefinitionCreate($definition: MetafieldDefinitionCreateInput!) {
  metafieldDefinitionCreate(definition: $definition) {
    createdDefinition {
      id
      name
      key
      # add other return fields
    }
    userErrors {
      field
      message
      code
    }
  }
}
```

## Variables

```json
{
  "definition": {
    "name": "Acme ID",
    "key": "acme-id",
    "description": "Membership gives Shop Users special discounts on participating Stores",
    "type": "single_line_text_field",
    "ownerType": "SHOP_USER"
  }
}
```

## JSON response

```json
{
  "metafieldDefinitionCreate": {
    "createdDefinition": {
      "id": "gid://shopapp/MetafieldDefinition/1071456108",
      "name": "Acme ID",
      "key": "acme-id"
    },
    "userErrors": []
  }
}
```

### Update

The following mutation updates the name of a metafield definition to "Acme Identifier". The `key` in the `$definition` determines which definition to update. You can update only the name and description of a metafield definition. Metafields for the metafield definition are not impacted.

## POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json

## GraphQL mutation

```graphql
mutation MetafieldDefinitionUpdate($definition: MetafieldDefinitionUpdateInput!) {
  metafieldDefinitionUpdate(definition: $definition) {
    updatedDefinition {
      id
      name
      key
      # add other return fields
    }
    userErrors {
      field
      message
      code
    }
  }
}
```

## Variables

```json
{
  "definition": {
    "name": "Acme Identifier",
    "key": "acme-id",
    "ownerType": "SHOP_USER"
  }
}
```

## JSON response

```json
{
  "metafieldDefinitionUpdate": {
    "updatedDefinition": {
      "id": "gid://shopapp/MetafieldDefinition/1071456108",
      "name": "Acme ID",
      "key": "acme-id"
    },
    "userErrors": []
  }
}
```

### Delete

The following example deletes not only the metafield definition for `acme-id`, but also deletes all metafields that use this definition.

## POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json

## GraphQL mutation

```graphql
mutation MetafieldDefinitionDelete($identifier: HasMetafieldsIdentifier!) {
  metafieldDefinitionDelete(identifier: $identifier) {
    deletedDefinition {
      id
      name
      key
      # add other return fields
    }
    userErrors {
      field
      message
      code
    }
  }
}
```

## Variables

```json
{
  "identifier": {
    "key": "acme-id",
  }
}
```

## JSON response

```json
{
  "metafieldDefinitionDelete": {
    "deletedDefinition": {
      "id": "gid://shopapp/MetafieldDefinition/1071456108",
      "name": "Acme ID",
      "key": "acme-id"
    },
    "userErrors": []
  }
}
```

### Get a Metafield​Definition

The following example retrieves the metafield definition for `acme-id`.

## POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json

## GraphQL query

```graphql
query MetafieldDefinition($identifier: HasMetafieldsIdentifier) {
  metafieldDefinition(identifier: $identifier) {
    definition {
      name
      key
      description
      ownerType
      type
    }
    userErrors {
      field
      message
      code
    }
  }
}
```

## Variables

```json
{
  "identifier": {
    "key": "acme-id",
  }
}
```

## JSON response

```json
{
  "data": {
    "metafieldDefinition": {
      "definition": {
        "name": "Acme ID",
        "key": "acme-id",
        "description": "Identifier for User in Acme DB",
        "ownerType": "SHOP_USER",
        "type": "single_line_text_field"
      },
      "userErrors": []
    }
  }
}
```

Note: if no identifier is supplied, all metafield definitions the client can access will be returned.

***

## Managing Metafields

### Set

Note that you can return an `ownerId` for the metafield that you set, but you don't need it in the input as Access Token in the Authorization header determines the user (and thus `ownerId`).

## POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json

## GraphQL mutation

```graphql
mutation MetafieldsSet($metafields: [MetafieldSetInput!]) {
  metafieldsSet(metafields: $metafields) {
    metafields {
      namespace
      key
      value
      ownerId
    }
    userErrors {
      field
      message
      code
    }
  }
}
```

## Variables

```json
{
  "metafields": [{
    "key": "acme-id",
    "value": "123ABC"
  }]
}
```

## JSON response

```json
{
  "metafieldsSet": {
    "metafields": [{
      "key": "acme-id",
      "value": "123ABC",
      "ownerId": "gid://shopapp/User/1",
    }],
    "userErrors": []
  }
}
```

### Delete

Note that this query is scoped by user, so the Access Token determines the user for which we're deleting metafields.

## POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json

## GraphQL mutation

```graphql
mutation MetafieldsDelete($identifiers: [HasMetafieldsIdentifier!]) {
  metafieldsDelete(identifiers: $identifiers) {
    deletedMetafields {
      ownerId
      key
      value
    }
    userErrors {
      field
      message
      code
    }
  }
}
```

## Variables

```json
{
  "identifiers": [{"key": "acme-id" }]
}
```

## JSON response

```json
{
  "metafieldsDelete": {
    "deletedMetafields": [
      {
        "ownerId": "gid://shopapp/User/1",
        "key": "acme-id",
        "value": "123ABC"
      }
    ],
    "userErrors": []
  }
}
```

### Retrieve a Metafield for a Metafield​Definition on a User

Note that this query is scoped by user, so the Access Token determines the user for which we're querying metafields.

## POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json

## GraphQL query

```graphql
query Metafields($identifiers: [HasMetafieldsIdentifier!]) {
  metafields(identifiers: $identifiers) {
    metafields {
      key
      value
      ownerId
   }
   userErrors {
    field
    message
    code
   }
  }
}
```

## Variables

```json
{
  "identifiers": [{"key": "acme-id"}]
}
```

## JSON response

```json
{
  "data": {
    "metafields": {
      "metafields": {
        "key": "acme-id",
        "value": "124ABC",
        "ownerId": "gid://shopapp/User/1",
      },
      "userErrors": []
    }
  }
}
```

***

## Namespaces

All clients have an implicit reserved namespace in the Shop User Custom Data API. All metafield actions default to using this namespace.

If you want to address a field within a namespace other than the default, you can add the 'namespace' argument to the identifier.

In the following example, the metafield `age` is available within the `facts` namespace. The value of this definition can be viewed on a given user using the `metafields` query with `facts` supplied to the namespace argument in the identifier.

### Retrieve a Metafield for a Metafield​Definition on a User

## POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json

## GraphQL query

```graphql
query Metafield($identifier: HasMetafieldsIdentifier!) {
  metafield(identifier: $identifier) {
    metafield {
      value
      ownerId
      definition {
        key
        namespace
      }
   }
   userErrors {
    field
    message
    code
   }
  }
}
```

## Variables

```json
{
  "identifiers": [{"namespace": "facts", "key": "age"}]
}
```

## JSON response

```json
{
  "data": {
    "metafield": {
      "metafield": {
        "value": "24",
        "ownerId": "gid://shopapp/User/1",
        "definition": {
          "key": "age"
          "namespace": "facts"
        }
      },
      "userErrors": []
    }
  }
}
```

### Retrieve multiple Metafields for Metafield​Definitions on a User

Returns a paginated list of metafields for all of the included identifiers, skips identifiers that cannot be found.

Accepts pagination parameters:

* `after`: An optional string that returns the elements that come after the specified cursor.
* `before`: An optional string that returns the elements that come before the specified cursor.
* `first`: An optional integer that specifies that the query returns the first 'n' elements from the list.
* `last`: An optional integer that specifies that the query returns the last 'n' elements from the list.
* `reverse`: An optional boolean that specifies the query returns elements from the list in reverse order.
* `sort_key`: An optional string that specifies the sort order of the underlying list. Currently, 'KEY' and 'NAME' are the only supported options.

## POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json

## GraphQL query

```graphql
query Metafields($identifiers: [HasMetafieldsIdentifier!]) {
  metafields(identifiers: $identifiers) {
    edges {
      nodes {
        value
        ownerId
        definition {
          key
          namespace
          description
          type { name }
        }
      }
    }
    userErrors {
      field
      message
      code
    }
  }
}
```

## Variables

```json
{
  "identifiers": [{"namespace": "facts", "key": "age"}]
}
```

## JSON response

```json
{
    "data": {
        "metafields": {
            "edges": [
                {
                    "node": {
                        "value": "24",
                        "definition": {
                            "key": "age",
                            "namespace": "facts",
                        }
                    }
                }
            ],
            "pageInfo": {
                "hasNextPage": false,
                "hasPreviousPage": false,
                "startCursor": "MQ",
                "endCursor": "MQ"
            }
        }
    }
}
```

***

## Related References

* [Metafields](https://shopify.dev/docs/apps/build/custom-data/metafields)
* [Metafield definitions](https://shopify.dev/docs/apps/build/custom-data/metafields/definitions)

***