Solved

Using APIs from a different origin/domain

Knewb
Visitor
2 0 1

Any method I've attempted to request information from a Shopify store from a different domain results in the familiar CORS error:

 

"Access to fetch at 'https://x.myshopify.com/admin/api/2019-04/graphql.json' from origin 'https://x.ngrok.io' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled."

 

I'm trying to create a customer-facing site which is very simple and is just for managing (creating and logging in) customer accounts, and doing specific things with those accounts like setting tags and sending emails to store staff to update details on those accounts once they're created. Using GraphQL or the REST API, is there a way to get the Shopify store to allow API requests from my separate domain without triggering the CORS error? Any way at all to add the appropriate "Access-Control-Allow-Origin" header in the response from the API endpoint?

 

(The security implications are not my concern here, as I believe API credentials can be obfuscated using backend middleware on the site doing the requests)

 

Or am I going about it the wrong way and there's another recommended way to do this besides those two APIs?

 

Or is what I'm trying to do only possible on the same domain as the store, by design, no exceptions?

Accepted Solution (1)

Alex
Shopify Staff
1561 81 341

This is an accepted solution.

If you want to make an API request to the admin API, you have to do it from a back end. Front end requests, as you observed, will be blocked by the CORS policy on our end. What you can do is from your front end, delegate to your backend to make the request, and return the response data from that request to your front end.

Alex | Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit the Shopify Help Center or the Shopify Blog

View solution in original post

Replies 44 (44)

Alex
Shopify Staff
1561 81 341

This is an accepted solution.

If you want to make an API request to the admin API, you have to do it from a back end. Front end requests, as you observed, will be blocked by the CORS policy on our end. What you can do is from your front end, delegate to your backend to make the request, and return the response data from that request to your front end.

Alex | Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit the Shopify Help Center or the Shopify Blog

I_KNOW_NOTHING
Shopify Partner
45 0 11

Hi,

Can you please explain more how to achieve this delegation from Frontend to Backend?

regards

Jason
Shopify Expert
11190 225 2282

@I_KNOW_NOTHING wrote:

Hi,

Can you please explain more how to achieve this delegation from Frontend to Backend?

regards


The flow is fairly simple but refer to the docs for extra info on authentication. You should never be trying to access the Admin API from the front end as it's not secure. You will be passing auth details that anyone could steal so this is just a crazy idea.

 

General delegation (high level):

  1. You'd send info to your app/middlware instead of directly to the API. Perhaps in the ajax call like you're doing now.
  2. The middleware will handle the secure authentication to the Admin API - and any other security/rate buffering/etc. Also possible the middleware has cached data and skips calling the Admin API entirely. You have to consider API call rates in your approach regardless.
  3. the middleware passes info back via the response to the ajax call. With that data you do whatever you need to on a front end perspective.

 

What are you trying to do that needs a call to the Admin API in the first place?

★ I jump on these forums in my free time to help and share some insights. Not looking to be hired, and not looking for work. http://freakdesign.com.au ★
I_KNOW_NOTHING
Shopify Partner
45 0 11

Hi Jason,

Thank you for quick reply,

what I am using is an GraphQL Admin API. This is my sample query

var query = `{
  productVariants(first:1, query:"barcode:${sku}") {
    edges {
      node {
        inventoryQuantity
        legacyResourceId
        barcode
        price
        compareAtPrice
        availableForSale
      }
    }
  }
method: 'POST',
data: JSON.stringify({query}),
headers: {"X-Shopify-Access-Token""PRIVATEAPPTOKEN"},
         crossDomain: true,
         successfunction(response){
              console.log(response);
         }
})
 
I am using a Private APP token.
sunildeshkar
Tourist
5 0 1

Hello,

Does have any example code or steps to do this?

Because I am new in it and don't have much idea.

 

Thank you

 

 

 

Ross_Angus
Shopify Partner
15 0 4

@sunildeshkar: Here's what I put together, for the purposes of demonstration. You should be able to replace the Storefront access token and store name with your own, to pull through some data. Is this what you were after?

sunildeshkar
Tourist
5 0 1

@ Thank you for replying. Actually I don't want call SHOPIFY API to get product and all. I need to call third party API which is created my self and It means, end point must be "https://devdemo.pro/outreachbee2/API/index.php" . I wrote code to call on product details template page, https://sbd-ds.myshopify.com/products/chikan-food this is the page where I need to call API via ajax code. Here is ajax code:

 
  $.ajax({
   method: "POST",      // The HTTP method to use for the request
   dataType: "json",   // The type of data that you're exerciseecting back 
    headers: {"X-Shopify-Access-Token": "7a914f63fda68e2af725acd6bbfcaf51"},
   crossDomain: true,
   error: function() {   
  // A function to be called if the request fails.
   },
   beforeSend: function() {      
      // A function to be called if before the request is made.
   },
   success: function(response) {
      console.log(response)     
      // A function to be called if the request succeeds.
   }
});
 
 
but getting error.. you can see on consol :  https://sbd-ds.myshopify.com/products/chikan-food
 
Error : 
Access to XMLHttpRequest at 'https://devdemo.pro/outreachbee2/API/index.php' from origin 'https://sbd-ds.myshopify.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
jquery-3.3.1.min.js:2 POST https://devdemo.pro/outreachbee2/API/index.php net::ERR_FAILED
 
 
HunkyBill
Shopify Expert
4845 60 547

This is dead simple to fix. Tell your server to allow incoming calls from sbd-ds.myshopify.com

Nothing else to it. It is your server causing the CORS issue. You are not allowed to call domain A from domain B without a CORS issue for the most part.The Internet has 1000 pages dedicated to explaining how to mitigate CORS issues, you should be able to solve this in < 5 minutes yourself.

 

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
globalxmart
Visitor
3 0 0

we are currently facing this issue in our store, can you show us how to implement it ???

 

stefanH
Shopify Partner
3 0 0

Can you show me your code?

PS: don't show the real api password or any private details

lawwantsin
Tourist
9 0 32

This is not solved.  What about the Storefront API.  Does that require a backend too?  I literally can't get a straight answer out of this forum because every question is about a different kind of API.  Public, private, custom.  Dudes.  Make better docs.

Nesters
Shopify Partner
19 1 19

Think of it this way:

 

Storefront API is a public API and the token for it is meant to be used on the client side.

 

Admin API is a private API and the token is not meant to be shared publicly. If you share this token to everyone by making requests from the browser, they can potentially access private information about your store, financial information, CUSTOMER information etc. 

This could lead to both inconvenience to your customers as they would be subject to fraud as well as you could run into legal issues if someone decides to sue you because of it.

 

Hence, Shopify throws a CORS error when detecting that you use a browser to send a request to a private API. While the CORS error might not be the most appropriate response here, it is valid for them to deny your request.

 

Hope that clarifies the issue for others encountering this error.

Contact me: mail@nesters.me
Technical solutions / integration / headless ecommerce.
Latest post: Benefits of JAMstack ecommerce
lawwantsin
Tourist
9 0 32

It doesn't clear up the issue because it doesn't answer my question.  It only reitterates other docs.

The question is Does Storefront API actually work Client-Side or are there unavoidable CORS issues that require a server-side proxy?

I'm not talking about the difference between Storefront and Admin.

You sound like a bot.

Nesters
Shopify Partner
19 1 19

Hence, Shopify throws a CORS error when detecting that you use a browser to send a request to a private API.

This is the answer to your question based on my comment. Storefront API is a public API and Admin API is a private one.

That's exactly why the difference between the APIs was pointed out.

 

Of course, you do not need a backend for Storefront API.

It takes very little time to verify that by sending a simple fetch request from Chrome dev tools console.

 

Aside from that, there is also a library (jsbuysdk) made by Shopify that utilizes Storefront API and is meant for the browser.

You can find more here: https://shopify.github.io/js-buy-sdk/

 

Contact me: mail@nesters.me
Technical solutions / integration / headless ecommerce.
Latest post: Benefits of JAMstack ecommerce
heinschulie
Visitor
1 0 1

Hi Nester,

 

My questions are very related to the topic at hand and, although I'm pretty sure it's a few very tiny things that I'm missing, I too am struggling for answers. 

 

My situation is simple: I have an Express server (Node) that can authenticate and call the Shopify admin API without problems when the process is initiated from a client app sitting on the same domain. When I initiate the oAuth flow from a client app sitting on a different domain (i.e. this client calls my secure server and this server attempts to establish contact with Shopify) then I end up with the CORS error described above.

 

I believe this is a reasonable (and possibly even popular) architecture and so it must be something simple I'm missing on my end. 

 

Can you confirm if this is possible and - if so - if an example exists that I can study to see where I'm going wrong? 

 

Hein 

 

AhmadH
Shopify Partner
2 0 1

Did you manage to find any solution? In 2023, I am struggling with the same issue - Angular as SPA and Express as backend. CORS error 😞

JoeLum
Visitor
2 0 1

 I am using Storefront API using apollo and get CORS, how to handle that?

sravans
Shopify Partner
23 1 6

Surprised that no one yet addressed how people managed work around the CORS issue.

lawwantsin
Tourist
9 0 32

 

 

The actual answer is despite what the docs say, you have to use a middleman server to use Storefront API as well.  You cannot just do it from the frontend like Stripe allows.  So spin up a whole server that just passes messages, folks.  Worry about it silently falling over at checkout, folks.  That's the only way to use this "serverless solution" of a scam product. 

Bottom line, after 2 integrations and endless trouble and even more monthly fees, I can attest, Shopify is a garbage fire built on a garbage framework, run by people who are just swimming in their money bin, don't care and don't answer questions on the forum.  Good F'ing luck.

HunkyBill
Shopify Expert
4845 60 547

You're doing it wrong. If you use Storefront API as intended, there is no CORS issue.

Shopify is fundamentally built with the exact same HTTP protocols as all other Internet properties. Shopify is not pushing any unique technology, so comparing it to Stripe as if Stripe is somehow doing Internet computing different or more correct, is plain silly. Once you can do one pattern with one service, you can repeat with any other. oAuth is oAuth, for example. 

It's ok to just say you don't understand, and ask for help. Mostly, you have to learn to help yourself. Like anything worth doing.

 

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
lawwantsin
Tourist
9 0 32

 

 

Using it as intended?  I've used it on 2 projects and you need a middle man server to use Storefront API and the docs suck.  Period.

and Stripe.JS allows for client side calls to the stripe.com api, so does google analytics script tag. that's how CORS works, dick. 

You are the expert of a pile of shit.

Nesters
Shopify Partner
19 1 19

You sure you are not mixing up Storefront API with the GraphQL Admin API?

Storefront API even has a simple library - JS Buy SDK that can be used on any website to implement product catalog / cart functionality with your Shopify store.
You can see an example here: https://jamstack-ecommerce.nesters.me/ 

That's a static Nuxt.js storefront outside of Shopify that is utilizing Storefront API.

GraphQL Admin API rightfully will have CORS issues due to sensitive data that can be exposed if you leave your credentials available to everyone on the internet.

 

Contact me: mail@nesters.me
Technical solutions / integration / headless ecommerce.
Latest post: Benefits of JAMstack ecommerce
fallen-domino
Shopify Partner
68 0 13

Since my question is closely related to the way the convo has shifted, I'm using the Storefront API and am getting a CORS error from a Gatsby development server on localhost.  

Been reading for a few days now and can't figure it out why this is happening.  Does CORS behave differently for localhost?

Thanks

HunkyBill
Shopify Expert
4845 60 547

When you setup a token to do Storefront API calls, do you not pin it to a domain? I pin my to https://mystore.test for example, as the .test domain is perfect for localhost work. So I get no CORS problems. But if you pinned your token to a different domain from your calls, CORS is indeed your problem. Without more details, it is hard to help you out.

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
fallen-domino
Shopify Partner
68 0 13

Thanks for the quick reply.  I did a little more investigating and realized that my environment variable isn't suppose to include ".myshopify.com" so it was appended twice and I'd been staring for so long I was blind to it.  I didn't consider that because Gatsby's Shopify source plugin was doing static graphql queries successfully using the same source plugin with the same credentials, but not queries in the browser.  Not sure why.

Appreciate the help

HunkyBill
Shopify Expert
4845 60 547

Puberty is hitting you hard! I get it though, I had kids, so your 'tude is like water off a ducks back. One day you'll be out of your mom's basement, and perhaps less bitter about things you should be enjoying more.

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
lawwantsin
Tourist
9 0 32

 

That's a lot of assumptions Hunky Bill.  It's okay to admit this platform is garbage and ruining e-commerce for developers.

andrewscott
Shopify Partner
4 0 0

Hey Alex,

I can't figure out how to delegate this to the backend. Is there any documentation?

I'm trying to GET /admin/api/themes/{theme_id}/assets.json from the index.js of a custom app that's embedded in the Shopify Admin.

It is similar to registering a webhook?

I've looked everywhere but I can find a concrete example of how to do this.

 

Cheers!

Andrew

HunkyBill
Shopify Expert
4845 60 547

A theme asset is not pinned to a "custom App" embedded in the Admin. Assets belong to a theme, and hence are available to any App with API permission to read theme assets. If you are having trouble making API GET requests for theme assets, ensure your App has permission to do so. After that, it remains a simple GET.

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
andrewscott
Shopify Partner
4 0 0

I was trying that at first. I'm using ngrok to develop the app and tried a few different get combinations:

fetch("/admin/api/themes/{theme_id}/assets.json", {method: "GET"}) - this fetched https://no234oiasd.ngrok.io/admin/api/..etc and returned 404.

fetch("{hardcoded_store_name}//admin/api/themes/{theme_id}/assets.json", {method: "GET"}) - cors policy, and an opaque response.

 

I do have the app set up for theme permissions as well. 

 

HunkyBill
Shopify Expert
4845 60 547

1. the correct endpoint is /admin/api/2020-10/themes/{theme_id}/assets.json

2. If you are getting CORS errors you are doing your API calls all wrong. That would be an indication you are calling from some domain other than your App, which is clearly a violation of CORS

 

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
andrewscott
Shopify Partner
4 0 0

Yeah, sorry the endpoint I'm using is that one (I can paste it into the URL of the store I'm developing for and receive the output I'm expecting).

So, I followed the Shopify React/Node.js custom app tutorial and got to the end with all the steps working. So, now I have a custom app that's embedded in the Shopify Admin Panel. 

I'm just looking to start with a button (on the index.js page) that returns the /admin/api/../assets.json data to the console.

I can't find any documentation that shows how to simply query that endpoint from the index.js page. Is there documentation that you can point me towards? 

 

I am using ngrok so my domain is different than my store but I do have the /auth/callback set to the ngrok url I'm using. I've seen that I might have to set up a route in server.js that index.js calls but I just can't find the right docs. 

 

Thanks for the help btw

Gregarican
Shopify Partner
1033 86 285

The easiest way to avoid all the pitfalls you are running into would be to implement this functionality via an app proxy --> https://shopify.dev/tutorials/display-data-on-an-online-store-with-an-application-proxy-app-extensio.... Once this app proxy is configured and installed in the Shopify store then you just reference your URL with the DNS name of the Shopify store. The path equates to the app proxy call, and Shopify does the rest. Your external resource can then validate the API request via HMAC signature verification to ensure the call is legit. Once you get whatever data you need then you pass values back to the request caller. 

mehmettekn
Shopify Partner
1 0 0

Thank you, sir! I'd been looking for this for the past 3 hrs!

HunkyBill
Shopify Expert
4845 60 547

So you speak of index.js being the home page of your own custom embedded App in the Admin. And you don't know where to start. OK. Well, to make a GET request to your App, you can use fetch() or even better, try the axios library. It is simple, and works well with all the bells and whistles. It is likely you can code up your GET request within a minute and see your results. So hook your button click event listener to an axios (or fetch) GET and you will see in the response, what you asked for.

 

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
andrewscott
Shopify Partner
4 0 0

Thanks Greg and Bill! 

I think Bill was right about that it should be easy. 

const res = await fetch(
`https://${SHOPIFY_API_KEY}:${accessToken}@${shop}/admin/api/2020-10/themes/116224032917/assets.json`
)

 

In case anyone else is wondering the full set up:

https://community.shopify.com/c/Shopify-APIs-SDKs/I-want-to-call-rest-api-in-the-shopify-embedded-ap...

agmiguelcalo
Visitor
3 0 0

So about using the api directly on browser, you take note of the ff:

  • create a private app on your store and tick what you need on the store front api scopes
  • an access token will be generated, add that in your request header as "X-Shopify-Storefront-Access-Token"
  • your endpoint will have a '.js' suffix, ex "https://your-shop.myshopify.com/api/graphql.js"

Got to admit though, the gql documentation is not very friendly. 🙂

Here's a sample query you can try

query {
  products(first:3) {
    edges {
      node {
        id
        handle
        variants(first:3) {
          edges {
            node {
              id
            }
          }
        }
      }
    }
  }
}
Ross_Angus
Shopify Partner
15 0 4

What baffles me about this issue is that I have no idea how this CodePen example works. Perhaps the later API has stricter CORS rules.

HunkyBill
Shopify Expert
4845 60 547

There are no CORS issues when you make calls with the Storefront API token. So this simple Codepen does a request that gets product tags. The result is returned and appended to DOM. Can you describe what baffles you about that? Perhaps we can help then.

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
Ross_Angus
Shopify Partner
15 0 4

I was getting CORS errors when I tried to connect. The CodePen example gave me enough of a working example to get over this hump. No idea why it was happening the Storefront access.

L1f7dev
Visitor
2 0 0

Hi,

I'm having a similar CORS issue.

In my case, I have a custom frontend on a different domain with a third party app trying to pull some data from Shopify at {{shopify_domain}}/tools/{{some_endpoint}}
This fails because of CORS.

Since I can confirm that I'm not exposing any keys using this app.
I'm wondering if there's a way to add my new domain to a cors whitelist?

@HunkyBill @Ross_Angus any ideas please?

Ross_Angus
Shopify Partner
15 0 4

Shameful admission, but as I've not been in the guts of this subject for a while, it's mostly drifted out of my head.

My CodePen proof-of-concept was working towards a headless solution using the CMS TakeShape. Unfortunately, TakeShape makes it easy to import Shopify data and mix it up with custom data patterns created in TakeShape itself, so I'm not even sure I solved some of these problems myself.
My guess would be that getting your domain added to a whitelist by Shopify isn't going to happen. My proof-of-concept was about pulling publicly available Shopify data to a third party domain, which is thankfully possible without any CORS issues.
(just to reiterate, I don't actually understand what CORS is!)

MakinMine
Shopify Partner
7 0 0

Access to fetch at 'https://interiortonic-united-states.myshopify.com/admin/api/2024-01/draft_orders.json' from origin 'https://interiortonic.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the

I am create the darft order than show me this error please solve this

HunkyBill
Shopify Expert
4845 60 547

The standard way to call the Admin API from the front-end of your store is to use the App Proxy pattern. The proxy accepts a call from your store Interior Tonic, and secures it for your backend. Your backend makes the Draft Order, returns and URL if you want, and you redirect your customer to that URL so they can checkout and turn the draft into a real order.

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com