Skip to content

App-exclusive prices on Shopify through the API

This page describes how a development team, whether the merchant’s, their ERP’s or a third party’s, can manage app-exclusive prices on a Shopify store on their own. It is useful, for example, to sync prices from an ERP or a PIM without going through the Reskyt editor.

It applies to Shopify only. The only public Reskyt API documented is the push notifications one.

The exclusive price of a variant is stored in a standard Shopify metafield on that variant. Two pieces read it:

PieceWhat it does with the metafield
Reskyt Shopify FunctionApplies the price at checkout
Reskyt theme blockShows the price on the product page and in collections, in Liquid themes

No database or API of Reskyt’s own is involved. Anyone with write access to the store’s Admin API can write the metafield.

  1. An automatic discount already created in the store. The metafield only has an effect at checkout if the automatic discount “Reskyt — Precio Catálogo App”, which the Function is bound to, exists. It is created the first time someone saves a Catalog price rule from the Reskyt app editor in Shopify (Promotions → New rule). Doing it once per store is enough. If the editor has never been used, writing the metafield has no effect.
  2. An app of your own, private or custom, with the write_products scope on that store, to use the Admin GraphQL API.
  3. The Reskyt app embed active in the theme, required so that app orders are identified as such. See Shopify.
FieldValue
Resource (ownerType)PRODUCTVARIANT. Written per variant, not per product
Namespacereskyt
Keycatalog_price
Typejson
{
"price": 19.99,
"ruleId": "my-integration",
"customerTag": "wholesale",
"from": "2026-01-01T00:00:00Z",
"until": "2026-01-31T23:59:59Z"
}
FieldRequiredDescription
priceYesFixed price, not a percentage, that the app user will see and pay for that variant, in the store currency
ruleIdNoFree identifier for your own tracking. Reskyt does not use it
customerTagNoShopify customer tag, not the native Segment. If set, the price only applies to logged-in customers who have that exact tag. If omitted, it applies to any app user
from, untilNoInformational only. The Function does not read them: as long as the metafield exists, the price is active

The price is applied at checkout when all of these conditions are met:

  1. The order comes from the app, that is, the cart has the __reskyt_app_origin attribute set to true.
  2. The metafield price is lower than the unit price the line currently has in the cart. If it is equal or higher, no discount is applied.
  3. If the value includes customerTag, the customer is logged in and has that tag.

from and until are not enforced. If the price must have a start and an end date, the integration must write the metafield at the start and delete it at the end, for example with a scheduled process of your own.

1. Get the variant identifier from its SKU

query FindVariantBySku($query: String!) {
productVariants(first: 1, query: $query) {
nodes { id }
}
}

Variables:

{ "query": "sku:YOUR-SKU" }

2. Write the metafield

mutation SetCatalogPrice($metafields: [MetafieldsSetInput!]!) {
metafieldsSet(metafields: $metafields) {
metafields { id }
userErrors { field message }
}
}

Variables:

{
"metafields": [
{
"ownerId": "gid://shopify/ProductVariant/1234567890",
"namespace": "reskyt",
"key": "catalog_price",
"type": "json",
"value": "{\"price\":19.99,\"customerTag\":\"wholesale\"}"
}
]
}

The value field is a string containing the JSON. Request limits and the number of metafields per operation are those of the Shopify Admin API.

For a variant to stop having an exclusive price, the metafield must be deleted. Leaving it at 0 or null does not deactivate it.

mutation DeleteCatalogPrice($metafields: [MetafieldIdentifierInput!]!) {
metafieldsDelete(metafields: $metafields) {
deletedMetafields { key namespace ownerId }
userErrors { field message }
}
}

Variables:

{
"metafields": [
{
"ownerId": "gid://shopify/ProductVariant/1234567890",
"namespace": "reskyt",
"key": "catalog_price"
}
]
}

Writing the metafield makes the price be charged at checkout. Whether the buyer sees it in the store is a separate matter, and it does not affect the charge.

StorefrontWhat to do
Liquid themeThe Reskyt theme block shows the price. There is also an equivalent code snippet for custom themes
Headless, such as Hydrogen or OxygenThe frontend reads the metafield from the Storefront API and shows it where appropriate

In a Liquid theme, the Reskyt theme extension adds the __reskyt_app_origin attribute to the cart when it detects the app. In a headless storefront that extension does not run. The team building the frontend must add the same attribute when it detects that the visitor comes from the app, using the Storefront API cartAttributesUpdate mutation:

{ "key": "__reskyt_app_origin", "value": "true" }

Without that attribute, checkout does not apply the exclusive price.

  1. Confirm that a Catalog price rule has been created once from the Reskyt editor in the store.
  2. Create an app of your own with the write_products scope and get its token.
  3. For each variant, look up its identifier by SKU and write reskyt.catalog_price as JSON.
  4. If the price has an end date, delete the metafield from your own process.
  5. If you use a customerTag, check that the tag is already used in an editor rule.
  6. If the storefront is headless, add the __reskyt_app_origin cart attribute and show the price from your frontend.