Tutorials

How to query related resources with the API

Dan Rowden  ·  March 31, 2023

The Lemon Squeezy API lets you easily access and manage your store programatically but sometimes multiple API requests are needed to load related data.

In this quick tutorial, we'll go through some examples of using "includes" to load multiple data objects into a single API request.

Products and variants

This first example loads variant data when querying products. This is really useful if you are saving product data locally in your application because you need variant IDs to change a subscriber's plan.

Typically you may query the products list and then use the URLs returned in the data.relationships.variants.links object to get data for each product's variants. If you do this, you'll end up making multiple API requests:

  • GET https://api.lemonsqueezy.com/v1/products
  • GET https://api.lemonsqueezy.com/v1/products/{product_id}/variants
  • GET https://api.lemonsqueezy.com/v1/products/{product_id}/variants
  • GET https://api.lemonsqueezy.com/v1/products/{product_id}/variants
  • etc

This isn't the ideal way to get the data you need from the API and I'll show you why. Here is an example response from the /products endpoint. Note the variant relationship URLs for each product, which could be used to query each product's variants.

GET https://api.lemonsqueezy.com/v1/products { ... "data": [ { "type": "products", "id": "1", "attributes": { "store_id": 1, "name": "Example Product", "slug": "example-product", "description": "

Lorem ipsum...

", "status": "published", "status_formatted": "Published", "thumb_url": "https://app.lemonsqueezy.com/storage/media/1/1c40f227-aed5-4321-9ffc-62f37a06c9a0.jpg", "large_thumb_url": "https://app.lemonsqueezy.com/storage/media/1/1c40f227-aed5-4321-9ffc-62f37a06c9a0.jpg", "price": 999, "price_formatted": "$9.99", "from_price": null, "to_price": null, "pay_what_you_want": false, "buy_now_url": "https://my-store.lemonsqueezy.com/checkout/buy/0a841cf5-4cc2-4bbb-ae5d-9529d97deec6", "created_at": "2021-05-27T12:54:47.000000Z", "updated_at": "2021-07-14T11:25:24.000000Z", "test_mode": false }, "relationships": { "store": { "links": { "related": "https://api.lemonsqueezy.com/v1/products/1/store", "self": "https://api.lemonsqueezy.com/v1/products/1/relationships/store" } }, "variants": { "links": { "related": "https://api.lemonsqueezy.com/v1/products/1/variants", "self": "https://api.lemonsqueezy.com/v1/products/1/relationships/variants" } } }, "links": { "self": "https://api.lemonsqueezy.com/v1/products/1" } }, {...}, {...} ] ... }

As you can see, this method is cumbersome, needs a lot of API calls and can get out of hand very quickly if you have a handful of products and variants. You also risk hitting rate limits by requesting the API so frequently.

Instead, we should look to load related resources in a single API call. In this case we should be loading related variants into the products request. To do this, we can use the include query parameter in the request:

GET https://api.lemonsqueezy.com/v1/products?include=variants

Using this one API request, we get all the data we need. It just needs some digesting to ensure all the data is ready to use.

This is an example response:

GET https://api.lemonsqueezy.com/v1/products?include=variants { "meta": { "page": { "currentPage": 1, "from": 1, "lastPage": 1, "perPage": 10, "to": 10, "total": 10 } }, "jsonapi": { "version": "1.0" }, "links": { "first": "https://api.lemonsqueezy.com/v1/products?page%5Bnumber%5D=1&page%5Bsize%5D=10&sort=name", "last": "https://api.lemonsqueezy.com/v1/products?page%5Bnumber%5D=1&page%5Bsize%5D=10&sort=name" }, "data": [ { "type": "products", "id": "1", "attributes": { "store_id": 1, "name": "Example Product", "slug": "example-product", "description": "

Lorem ipsum...

", "status": "published", "status_formatted": "Published", "thumb_url": "https://app.lemonsqueezy.com/storage/media/1/1c40f227-aed5-4321-9ffc-62f37a06c9a0.jpg", "large_thumb_url": "https://app.lemonsqueezy.com/storage/media/1/1c40f227-aed5-4321-9ffc-62f37a06c9a0.jpg", "price": 999, "price_formatted": "$9.99", "from_price": null, "to_price": null, "pay_what_you_want": false, "buy_now_url": "https://my-store.lemonsqueezy.com/checkout/buy/0a841cf5-4cc2-4bbb-ae5d-9529d97deec6", "created_at": "2021-05-27T12:54:47.000000Z", "updated_at": "2021-07-14T11:25:24.000000Z", "test_mode": false }, "relationships": { ... }, "links": { ... } }, {...}, {...} ], "included": [ { "type": "variants", "id": "1", "attributes": { "product_id": 1, "name": "Default", "slug": "537b22ba-fcc9-452a-9021-c3cabe3985cf", "description": "

This is the variant description.

", "price": 999, "is_subscription": true, "interval": "month", "interval_count": 1, "has_free_trial": false, "trial_interval": "day", "trial_interval_count": 30, "pay_what_you_want": false, "min_price": 0, "suggested_price": 0, "has_license_keys": false, "license_activation_limit": 5, "is_license_limit_unlimited": false, "license_length_value": 1, "license_length_unit": "years", "is_license_length_unlimited": false, "sort": 0, "status": "pending", "status_formatted": "Pending", "created_at": "2021-05-27T12:54:47.000000Z", "updated_at": "2021-07-14T11:25:24.000000Z", "test_mode": false }, "relationships": { "product": { "links": { "related": "https://api.lemonsqueezy.com/v1/variants/1/product", "self": "https://api.lemonsqueezy.com/v1/variants/1/relationships/product" } }, "files": { "links": { "related": "https://api.lemonsqueezy.com/v1/variants/1/files", "self": "https://api.lemonsqueezy.com/v1/variants/1/relationships/files" } }, "price-model": { "links": { "related": "https://api.lemonsqueezy.com/v1/variants/1/price-model", "self": "https://api.lemonsqueezy.com/v1/variants/1/relationships/price-model" } } }, "links": { "self": "https://api.lemonsqueezy.com/v1/variants/1" } }, {...}, {...} ] }

data contains a list of products and included contains the objects requested via the include query parameter.

If you want, you can even include multiple related resources, like ?include=variants,store. If you do this, included would contain a mixed list of Variant and Store objects.

Now you know the basics of how to request related resources, I'm going to show a few other example requests and responses to help you out when building an API integration.

A product and its store

This next example loads store data when querying a single product.

GET https://api.lemonsqueezy.com/v1/products/1?include=store

In this response you'll get a single Product object in the data key, and a single Store object in included.

{ "jsonapi": { "version": "1.0" }, "links": { "self": "https://api.lemonsqueezy.com/v1/products/1" }, "data": { "type": "products", "id": "1", "attributes": { "store_id": 1, "name": "Example Product", "slug": "example-product", "description": "

Lorem ipsum...

", "status": "published", "status_formatted": "Published", "thumb_url": "https://app.lemonsqueezy.com/storage/media/1/1c40f227-aed5-4321-9ffc-62f37a06c9a0.jpg", "large_thumb_url": "https://app.lemonsqueezy.com/storage/media/1/1c40f227-aed5-4321-9ffc-62f37a06c9a0.jpg", "price_formatted": "$9.99", "price": 999, "from_price": null, "to_price": null, "pay_what_you_want": false, "buy_now_url": "https://my-store.lemonsqueezy.com/checkout/buy/0a841cf5-4cc2-4bbb-ae5d-9529d97deec6", "created_at": "2021-05-27T12:54:47.000000Z", "updated_at": "2021-07-14T11:25:24.000000Z", "test_mode": false }, "relationships": { "store": { "links": { "related": "https://api.lemonsqueezy.com/v1/products/1/store", "self": "https://api.lemonsqueezy.com/v1/products/1/relationships/store" }, "data": { "type": "stores", "id": "1" } }, "variants": { "links": { "related": "https://api.lemonsqueezy.com/v1/products/1/variants", "self": "https://api.lemonsqueezy.com/v1/products/1/relationships/variants" } } }, "links": { "self": "https://api.lemonsqueezy.com/v1/products/1" } }, "included": [ { "type": "stores", "id": "1", "attributes": { "name": "Demo App", "slug": "demo-app-123", "domain": "demo-app-123.lemonsqueezy.com", "url": "https://demo-app-123.lemonsqueezy.com", "avatar_url": "https://lemonsqueezy-staging.imgix.net/avatars/stores/1/8rJPdCMEFSUpklK6F8w4B2yDa9O4nr50CsBa10ZP.png", "plan": "free", "country": "FR", "country_nicename": "France", "currency": "EUR", "total_sales": 0, "total_revenue": 0, "thirty_day_sales": 0, "thirty_day_revenue": 0, "created_at": "2021-05-20T10:47:38.000000Z", "updated_at": "2021-05-20T10:47:38.000000Z" }, "relationships": { "products": { "links": { "related": "https://api.lemonsqueezy.com/v1/stores/1/products", "self": "https://api.lemonsqueezy.com/v1/stores/1/relationships/products" } }, "orders": { "links": { "related": "https://api.lemonsqueezy.com/v1/stores/1/orders", "self": "https://api.lemonsqueezy.com/v1/stores/1/relationships/orders" } }, "subscriptions": { "links": { "related": "https://api.lemonsqueezy.com/v1/stores/1/subscriptions", "self": "https://api.lemonsqueezy.com/v1/stores/1/relationships/subscriptions" } }, "discounts": { "links": { "related": "https://api.lemonsqueezy.com/v1/stores/1/discounts", "self": "https://api.lemonsqueezy.com/v1/stores/1/relationships/discounts" } }, "license-keys": { "links": { "related": "https://api.lemonsqueezy.com/v1/stores/1/license-keys", "self": "https://api.lemonsqueezy.com/v1/stores/1/relationships/license-keys" } } }, "links": { "self": "https://api.lemonsqueezy.com/v1/stores/1" } } ] }

Subscriptions and customers

This next example loads customer data when querying subscriptions.

GET https://api.lemonsqueezy.com/v1/subscriptions?include=customer

In this response you'll get a list of Subscription objects in the data key, and a list of Customer objects in included.

{ "meta": { "page": { "currentPage": 1, "from": 1, "lastPage": 1, "perPage": 10, "to": 9, "total": 9 } }, "jsonapi": { "version": "1.0" }, "links": { "first": "https://api.lemonsqueezy.com/v1/subscriptions?include=customer&page%5Bnumber%5D=1&page%5Bsize%5D=10&sort=-createdAt", "last": "https://api.lemonsqueezy.com/v1/subscriptions?include=customer&page%5Bnumber%5D=1&page%5Bsize%5D=10&sort=-createdAt" }, "data": [ { "type": "subscriptions", "id": "1", "attributes": { "store_id": 1, "customer_id": 1, "order_id": 1, "order_item_id": 1, "product_id": 1, "variant_id": 1, "product_name": "Example Product", "variant_name": "Example Variant", "user_name": "Darlene Daugherty", "user_email": "[email protected]", "status": "active", "status_formatted": "Active", "card_brand": "visa", "card_last_four": "42424", "pause": null, "cancelled": false, "trial_ends_at": null, "billing_anchor": 12, "first_subscription_item": { "id": 1, "subscription_id": 1, "price_id": 1, "quantity": 5, "created_at": "2021-08-11T13:47:28.000000Z", "updated_at": "2021-08-11T13:47:28.000000Z" }, "urls": { "update_payment_method": "https://my-store.lemonsqueezy.com/subscription/1/payment-details?expires=1666869343&signature=9985e3bf9007840aeb3951412be475abc17439c449c1af3e56e08e45e1345413", "customer_portal": "https://my-store.lemonsqueezy.com/billing?expires=1666869343&signature=82ae290ceac8edd4190c82825dd73a8743346d894a8ddbc4898b97eb96d105a5" }, "renews_at": "2022-11-12T00:00:00.000000Z", "ends_at": null, "created_at": "2021-08-11T13:47:27.000000Z", "updated_at": "2021-08-11T13:54:19.000000Z", "test_mode": false }, "relationships": { "store": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/store", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/store" } }, "customer": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/customer", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/customer" }, "data": { "type": "customers", "id": "1" } }, "order": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/order", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/order" } }, "order-item": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/order-item", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/order-item" } }, "product": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/product", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/product" } }, "variant": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/variant", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/variant" } }, "subscription-items": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/subscription-items", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/subscription-items" } }, "subscription-invoices": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/subscription-invoices", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/subscription-invoices" } } }, "links": { "self": "https://api.lemonsqueezy.com/v1/subscriptions/1" } }, {...}, {...} ], "included": [ { "type": "customers", "id": "1", "attributes": { "store_id": 1, "name": "Luke Skywalker", "email": "[email protected]", "status": "subscribed", "city": null, "region": null, "country": "US", "total_revenue_currency": 84332, "mrr": 1999, "status_formatted": "Subscribed", "country_formatted": "United States", "total_revenue_currency_formatted": "$843.32", "mrr_formatted": "$19.99", "urls": { "customer_portal": "https://my-store.lemonsqueezy.com/billing?expires=1666869343&signature=82ae290ceac8edd4190c82825dd73a8743346d894a8ddbc4898b97eb96d105a5" }, "created_at": "2022-12-01T13:01:07.000000Z", "updated_at": "2022-12-09T09:05:21.000000Z", "test_mode": false }, "relationships": { "store": { "links": { "related": "https://api.lemonsqueezy.com/v1/customers/1/store", "self": "https://api.lemonsqueezy.com/v1/customers/1/relationships/store" } }, "orders": { "links": { "related": "https://api.lemonsqueezy.com/v1/customers/1/orders", "self": "https://api.lemonsqueezy.com/v1/customers/1/relationships/orders" } }, "subscriptions": { "links": { "related": "https://api.lemonsqueezy.com/v1/customers/1/subscriptions", "self": "https://api.lemonsqueezy.com/v1/customers/1/relationships/subscriptions" } }, "license-keys": { "links": { "related": "https://api.lemonsqueezy.com/v1/customers/1/license-keys", "self": "https://api.lemonsqueezy.com/v1/customers/1/relationships/license-keys" } } }, "links": { "self": "https://api.lemonsqueezy.com/v1/customers/1" } }, {...}, {...} ] }

A subscription and subscription invoices

This last example loads invoice data when querying a subscription.

GET https://api.lemonsqueezy.com/v1/subscription/1?include=subscription-invoices

In this response you'll get a single Subscription object in the data key, and a list of Subscription invoice objects in included.

{ "meta": { "page": { "currentPage": 1, "from": 1, "lastPage": 1, "perPage": 10, "to": 9, "total": 9 } }, "jsonapi": { "version": "1.0" }, "links": { "first": "https://api.lemonsqueezy.com/v1/subscriptions?include=subscription-invoices&page%5Bnumber%5D=1&page%5Bsize%5D=10&sort=-createdAt", "last": "https://api.lemonsqueezy.com/v1/subscriptions?include=subscription-invoices&page%5Bnumber%5D=1&page%5Bsize%5D=10&sort=-createdAt" }, "data": { "type": "subscriptions", "id": "1", "attributes": { "store_id": 1, "customer_id": 1, "order_id": 1, "order_item_id": 1, "product_id": 1, "variant_id": 1, "product_name": "Example Product", "variant_name": "Example Variant", "user_name": "Darlene Daugherty", "user_email": "[email protected]", "status": "active", "status_formatted": "Active", "card_brand": "visa", "card_last_four": "42424", "pause": null, "cancelled": false, "trial_ends_at": null, "billing_anchor": 12, "first_subscription_item": { "id": 1, "subscription_id": 1, "price_id": 1, "quantity": 5, "created_at": "2021-08-11T13:47:28.000000Z", "updated_at": "2021-08-11T13:47:28.000000Z" }, "urls": { "update_payment_method": "https://my-store.lemonsqueezy.com/subscription/1/payment-details?expires=1666869343&signature=9985e3bf9007840aeb3951412be475abc17439c449c1af3e56e08e45e1345413", "customer_portal": "https://my-store.lemonsqueezy.com/billing?expires=1666869343&signature=82ae290ceac8edd4190c82825dd73a8743346d894a8ddbc4898b97eb96d105a5" }, "renews_at": "2022-11-12T00:00:00.000000Z", "ends_at": null, "created_at": "2021-08-11T13:47:27.000000Z", "updated_at": "2021-08-11T13:54:19.000000Z", "test_mode": false }, "relationships": { "store": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/store", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/store" } }, "customer": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/customer", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/customer" } }, "order": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/order", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/order" } }, "order-item": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/order-item", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/order-item" } }, "product": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/product", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/product" } }, "variant": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/variant", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/variant" } }, "subscription-items": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/subscription-items", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/subscription-items" } }, "subscription-invoices": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscriptions/1/subscription-invoices", "self": "https://api.lemonsqueezy.com/v1/subscriptions/1/relationships/subscription-invoices" }, "data": [ { "type": "subscription-invoices", "id": "1" }, {...}, {...} ] } }, "links": { "self": "https://api.lemonsqueezy.com/v1/subscriptions/1" } }, "included": [ { "type": "subscription-invoices", "id": "1", "attributes": { "store_id": 1, "subscription_id": 1, "customer_id": 1, "user_name": "Darlene Daugherty", "user_email": "[email protected]", "billing_reason": "initial", "card_brand": "visa", "card_last_four": "4242", "currency": "USD", "currency_rate": "1.00000000", "status": "paid", "status_formatted": "Paid", "refunded": false, "refunded_at": null, "subtotal": 999, "discount_total": 0, "tax": 0, "total": 999, "subtotal_usd": 999, "discount_total_usd": 0, "tax_usd": 0, "total_usd": 999, "subtotal_formatted": "$9.99", "discount_total_formatted": "$0.00", "tax_formatted": "$0.00", "total_formatted": "$9.99", "urls": { "invoice_url": "https://app.lemonsqueezy.com/my-orders/.../subscription-invoice/..." }, "created_at": "2023-01-18T12:16:24.000000Z", "updated_at": "2023-01-18T12:16:24.000000Z", "test_mode": false }, "relationships": { "store": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscription-invoices/1/store", "self": "https://api.lemonsqueezy.com/v1/subscription-invoices/1/relationships/store" } }, "subscription": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscription-invoices/1/subscription", "self": "https://api.lemonsqueezy.com/v1/subscription-invoices/1/relationships/subscription" } }, "customer": { "links": { "related": "https://api.lemonsqueezy.com/v1/subscription-invoices/1/customer", "self": "https://api.lemonsqueezy.com/v1/subscription-invoices/1/relationships/customer" } } }, "links": { "self": "https://api.lemonsqueezy.com/v1/subscription-invoices/1" } }, {...}, {...} ] }
Previous
Free trials for SaaS