Can't create DraftOrder metafield definition

Admin API scopes: `read_products`, `read_shipping`, `read_draft_orders`, `read_customers`, `write_draft_orders`, `write_orders`, `read_orders`, `write_metaobjects`, `read_metaobjects`, `write_metaobject_definitions`, `read_metaobject_definitions`

async function initDraftMetafield(graphqlClient: GraphqlClient) {
  return await graphqlClient(METAFIELD_DEFINITION_CREATE, {
    variables: { definition: DRAFT_METAFIELD_DEFINITION },
  });
}
export const METAFIELD_DEFINITION_CREATE = `#graphql
  mutation MetafieldDefinitionCreate($definition: MetafieldDefinitionInput!) {
    metafieldDefinitionCreate(definition: $definition) {
      createdDefinition {
        id
        name
        key
      }
      userErrors {
        field
        message
      }
    }
  }`;
export const DRAFT_METAFIELD_DEFINITION: MetafieldDefinitionInput = {
  name: "My Metafield",
  namespace: "my_namespace",
  key: "my_metafield_key",
  description: "Description",
  ownerType: MetafieldOwnerType.Draftorder,
  pin: true,
  type: "single_line_text_field",
  capabilities: {
    adminFilterable: {
      enabled: true,
    },
    smartCollectionCondition: {
      enabled: false,
    },
    uniqueValues: {
      enabled: false,
    },
  },
  access: {
    customerAccount: MetafieldCustomerAccountAccessInput.Read,
    storefront: MetafieldStorefrontAccessInput.PublicRead,
  },
};

I get Failed to handle action: GraphqlQueryError: Access denied for metafieldDefinitionCreate field. Required access: API client to have access to the namespace and the resource type associated with the metafield definition. in the reponse.

It is crazy but it works perfectly fine with ownerType: MetafieldOwnerType.Order

What am I doing wrong?

Just tried to set all the scopes of the app, it still won’t let me create a draft order definition.

1 Like

Hi @madfcat

For the MetafieldDefinitionInput, you should be passing the enums listed in the Shopify.dev docs here for the input fields

Specifically, for the ownerType input, you should pass DRAFTORDER or ORDER, instead of the MetafieldOwnerType.Draftorder value that you are currently passing.

Also the access.customerAccount and access.storefront inputs, should also use the enums listed in the dev docs, in this case, READ and PUBLIC_READ respectively

Additionally, you will also receive an error if you set adminFilterable.enabled: true, as Draft Order and Order metafields are not admin filterable at this time. Currently the only supported owner type for admin metafield filtering is Products, Variants, and Metaobjects.

I have confirmed on my own test store with the same mutation you provided, updating the variables with the information I provided above, does work to create a new metafield definition without error, as long as the app install does have the correct access scopes.

{
    "definition": {
        "name": "My Metafield",
        "namespace": "my_namespace",
        "key": "my_metafield_key",
        "description": "Description",
        "ownerType": "DRAFTORDER",
        "pin": true,
        "type": "single_line_text_field",
        "capabilities": {
            "adminFilterable": {
                "enabled": false
            },
            "smartCollectionCondition": {
                "enabled": false
            },
            "uniqueValues": {
                "enabled": false
            }
        },
        "access": {
            "customerAccount": "READ",
            "storefront": "PUBLIC_READ"
        }
    }
}

If the Access Denied error continues after making these updates, I would recommend confirming what access scopes are actually enabled on the app install. This can be checked with the appInstallation query, retrieving the accessScopes field.

1 Like

MetafieldOwnerType.Draftorder is coming from the codegen generated schema.It is Typescript enum. So what you are suggesting, is already written in my code.
MetafieldOwnerType.Draftorder has value”DRAFTORDER”. Again, it works with MetafieldOwnerType.Order


/** Possible types of a metafield's owner resource. */
export enum MetafieldOwnerType {
  /** The Api Permission metafield owner type. */
  ApiPermission = 'API_PERMISSION',
  /** The Article metafield owner type. */
  Article = 'ARTICLE',
  /** The Blog metafield owner type. */
  Blog = 'BLOG',
  /** The Cart Transform metafield owner type. */
  Carttransform = 'CARTTRANSFORM',
  /** The Collection metafield owner type. */
  Collection = 'COLLECTION',
  /** The Company metafield owner type. */
  Company = 'COMPANY',
  /** The Company Location metafield owner type. */
  CompanyLocation = 'COMPANY_LOCATION',
  /** The Customer metafield owner type. */
  Customer = 'CUSTOMER',
  /** The Delivery Customization metafield owner type. */
  DeliveryCustomization = 'DELIVERY_CUSTOMIZATION',
  /** The Discount metafield owner type. */
  Discount = 'DISCOUNT',
  /** The draft order metafield owner type. */
  Draftorder = 'DRAFTORDER',
  /** The Fulfillment Constraint Rule metafield owner type. */
  FulfillmentConstraintRule = 'FULFILLMENT_CONSTRAINT_RULE',
  /** The GiftCardTransaction metafield owner type. */
  GiftCardTransaction = 'GIFT_CARD_TRANSACTION',
  /** The Location metafield owner type. */
  Location = 'LOCATION',
  /** The Market metafield owner type. */
  Market = 'MARKET',
  /**
   * The Media Image metafield owner type.
   * @deprecated `MEDIA_IMAGE` is deprecated.
   */
  MediaImage = 'MEDIA_IMAGE',
  /** The Order metafield owner type. */
  Order = 'ORDER',
  /** The Order Routing Location Rule metafield owner type. */
  OrderRoutingLocationRule = 'ORDER_ROUTING_LOCATION_RULE',
  /** The Page metafield owner type. */
  Page = 'PAGE',
  /** The Payment Customization metafield owner type. */
  PaymentCustomization = 'PAYMENT_CUSTOMIZATION',
  /** The Product metafield owner type. */
  Product = 'PRODUCT',
  /** The Product Variant metafield owner type. */
  Productvariant = 'PRODUCTVARIANT',
  /** The Selling Plan metafield owner type. */
  SellingPlan = 'SELLING_PLAN',
  /** The Shop metafield owner type. */
  Shop = 'SHOP',
  /** The Validation metafield owner type. */
  Validation = 'VALIDATION'
}

Concerning the scopes, I tried to allow all the scopes for the app. So, it feels like not a scope problem but a Shopify bug.

The other question is which scopes are needed for this mutation to work for the draft order metafield?

Hi @madfcat,

That’s good to know you are passing the correct enums for the mutation.

For the access scopes, you are required to have the scopes needed for the specific resource type. In this case to create a draft order metafield definition, you need the read_draft_orders and write_draft_orders scopes, which you did mention that you have already.

If you added these scopes after installing the app on the store, it is possible that your app configuration has the scopes listed, but the shop’s current app installation does not.

Depending on the installation method your app uses, you do need to update existing app installations when adding new scopes to your app configuration, and the merchant does need to approve the new scopes added.

You can see what scopes a specific shop’s app install has enabled via the appInstallation query I mentioned above.

If the app install is missing a scope that you have added to your app configuration after the app was installed, you can update the scopes on the specific store with the following documentation:

If you can confirm that the store where you are getting the error, does have the correct read_draft_orders and write_draft_orders scopes via the appInstallation query. We can help look into it further but we will need more specific details from an actual example API call that failed. Please provide the following details from the actual HTTP Request and Response experiencing the error for us to help further:

  • The full plain text HTTP Request, including URL, Body, and Headers (no access tokens)
  • The full plain text HTTP Response, including Body and Headers

I am not using the app installed. I am using a private app created from Apps and sales channels → Develop apps. My app is not listed with the appInstallation

Can you share the following information and we can definitely help look into it further:

  • the app name
  • full shop .myshopify.com url
  • an x-request-id from the HTTP Response Headers from an API call that returned the error