Quickstart

Four steps from zero to a filled grocery cart. About an hour for a React Native app.

1. Create an app and get keys

Sign in to the dashboard with your Mealio account, create a partner, then an app. You get two keys:

  • pk_test_... publishable key. Safe to ship inside your app.
  • sk_test_... secret key. Shown once. Keep it on your server only.

Sandbox keys start with _test_. Live keys start with _live_. Both fill real carts, so test with your own store account.

2. Add one endpoint to your server

Your app asks your server for a Mealio session for the signed-in user. Your server asks Mealio with its secret key and your own user id. Mealio creates its record of that user the first time it sees the id.

Node (Express)
app.post('/mealio/session', requireLogin, async (req, res) => {
  const r = await fetch('https://mealio.co/api/v1/sessions', {
    method: 'POST',
    headers: {
      authorization: `Bearer ${process.env.MEALIO_SECRET_KEY}`,
      'content-type': 'application/json',
    },
    body: JSON.stringify({ externalUserId: req.user.id }),
  });
  const { sessionToken } = await r.json();   // valid for 15 minutes
  res.json({ sessionToken });
});

3. Install the SDK

React Native
npm install @mealio/react-native-cart react-native-webview
# Expo: use a development build, not Expo Go
App.tsx
import { MealioProvider } from '@mealio/react-native-cart';

export default function App() {
  return (
    <MealioProvider
      publishableKey="pk_test_..."
      getSessionToken={async () => {
        const r = await fetch('https://your.api/mealio/session', { method: 'POST', headers: authHeaders() });
        return (await r.json()).sessionToken;
      }}
    >
      <Root />
    </MealioProvider>
  );
}

Using Swift, Kotlin or Flutter? See the iOS, Android and Flutter pages. The steps are the same.

4. Fill the cart

RecipeScreen.tsx
import { useMealio, MealioCartSheet } from '@mealio/react-native-cart';

function AddToCartButton({ recipe }) {
  const mealio = useMealio();
  const [cart, setCart] = useState(null);

  async function start() {
    // Signs the user in to H-E-B if needed, then searches every ingredient.
    setCart(await mealio.prepareCart({
      store: 'heb',
      zip: '78704',
      recipe: {
        id: recipe.id,
        title: recipe.title,
        ingredients: recipe.ingredients.map((i) => ({ name: i.name })),
      },
    }));
  }

  if (cart) return <MealioCartSheet cart={cart} onDone={(r) => alert(`Added ${r.added.length} items`)} />;
  return <Button title="Add to my grocery cart" onPress={start} />;
}

cart.ready holds items the user chose before for this recipe. cart.needsChoice holds up to 8 options per item for the user to pick. Build your own screen with cart.choose(key, productId) and cart.addToCart(), or drop in MealioCartSheet.

Mealio never picks a product the user did not choose. The options are only ranked: products the user picked in other recipes first, then what most Mealio users pick at that store.

Next