How to call external API from POS UI Extension

Hi all,

i’m hoping someone can advise me, I’ve been going round in circles with this problem. Feels like it should be straight forward but I can’t get it to work…

I have an AWS lambda that returns a health status end point:
https://mg33cv2cbucg35psjackwv5ucu0muisw.lambda-url.eu-west-1.on.aws/health

I have tried both with the app proxy approach and with the CORS approach to access this API from within my POS UI Extension:

My latest cut down POS extension test is a simple boilerplate extension that has a tile, clicking the tile opens a modal:

Opening the modal tries to access the health endpoint, which errors:

The app toml has the proxy set up and the write proxy permission:

[access_scopes]

# Learn more at https://shopify.dev/docs/apps/tools/cli/configuration#access_scopes

scopes = "write_app_proxy"

[app_proxy]

url = "https://mg33cv2cbucg35psjackwv5ucu0muisw.lambda-url.eu-west-1.on.aws"

subpath = "proxy"

prefix = "apps"

I have uninstalled and reinstalled the app and I can see the proxy is there:

No matter what I try, I get a load error when trying to access the API through the proxy in the POS UI extension, however accessing the page directly works:

Here is the Modal component:

import React, { useEffect, useState } from 'react';
import { Text, Screen, ScrollView, Navigator, reactExtension, useApi } from '@shopify/ui-extensions-react/point-of-sale';

const Modal = () => {
  const api = useApi();
  const [data, setData] = useState<any>(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const baseUrl = 'https://teststore1-20240105.myshopify.com';
        const healthUrl = `${baseUrl}/apps/proxy/health`;

        const response = await fetch(healthUrl);
        const healthData = await response.json();
        
        setData({
          success: true,
          data: {
            message: healthData.message,
            status: healthData.status,
            timestamp: new Date().toISOString(),
            note: "Lambda connection successful!"
          }
        });
      } catch (error) {
        // Fail silently, just don't set data
      }
    };

    fetchData();
  }, [api]);

  return (
    <Navigator>
      <Screen name="HelloWorld" title="App Proxy Demo">
        <ScrollView>
          <Text>Hello World</Text>
          {data && (
            <>
              <Text>Status: {data.success ? 'Success' : 'Failed'}</Text>
              <Text>Message: {data.data?.message}</Text>
              <Text>Status: {data.data?.status}</Text>
              <Text>Timestamp: {data.data?.timestamp}</Text>
              <Text>Note: {data.data?.note}</Text>
            </>
          )}
        </ScrollView>
      </Screen>
    </Navigator>
  );
};

export default reactExtension('pos.home.modal.render', () => <Modal />);

(Screenshot above still had some debug logic, i’ve simplified the code for this snippet, this version just shows the “Hello World” fallback content)

Can someone please give me some pointers on where I’m going wrong?

Many thanks in advance! This is driving me crazy

Hey Daniel,

Would you be able to share the CORS headers you are returning with your request? If possible please.

Have you seen the docs here? Communicate with a server

Also if you attach the debugger, it will show you the real error which is causing the problem :slight_smile: Debugging

Hi Jordan, thanks for your reply. The shopify dev docs and ai assistant says to not use CORS headers with app proxy requests or it could cause problems. I’m happy to recreate this with CORS approach if you think that will work better

Have you seen the docs here? Communicate with a server

Yes I have followed the instructions there

Update: When I do a CORS version, instead of using app proxy, and paste the Modal component into the Shopify AI assistant, it says:

our current modal is making a direct fetch request from the POS UI extension to your AWS Lambda URL using CORS. While this can work in some environments, it is **not the recommended or most reliable approach for Shopify POS UI extensions**.

### Why?

* Shopify POS UI extensions run in a sandboxed environment and may block or restrict direct calls to external APIs, even if CORS headers are set correctly.
* You may encounter intermittent failures or "TypeError: Load failed" due to network restrictions or CORS preflight issues.

---

## **Recommended Approach: Use an App Proxy**

Instead of calling your Lambda directly, you should route your request through a Shopify App Proxy. This ensures:

* No CORS issues (Shopify handles the cross-origin request).
* Consistent, secure access from the POS extension.

Hi,
I appreciate the AI input here, I know you can use app proxy for Online store. But I think the best approach would be to get API access direct to your system first, as then its easier for you to debug.
Once that is working you can then look at moving over to POS.

Once you’ve got CORS setup with your lambda, and the POS UI extension setup to communicate with it.
I would then open the app debugger and see if there is any error shown, if you can drop the error in here I can help debug this with you :slight_smile:

Ok thanks, i’ll try that and come back to you

Ace :slight_smile:

If you’d rather sort a quick call to debug when you’ve got the CORS setup, just let me know

Did you sort this out @Daniel_Morris ?