Build a mobile app
Kreezalid storefronts are responsive, but a marketplace can also have its own native app. This guide shows how to split the work between the app, a small back end of yours and the Kreezalid APIs so that the app never holds an administrator secret.
Architecture
Section titled “Architecture”| Part | Talks to | Does |
|---|---|---|
| The app (iOS, Android, React Native, Flutter…) | Front API directly, and your back end | Sign-up and login, account, cart, the member’s orders, wishlist, a vendor’s own listings. |
| Your back end | Admin API, with the credentials stored server-side | Serves the catalog to the app, receives webhooks and turns them into push notifications. |
| Kreezalid | — | The marketplace: data, rules, emails, checkout pages. |
1. Sign members up and in
Section titled “1. Sign members up and in”Create an account with POST /front_api/v1/account/create. Pass the group_id the member
joins, a customer group or a vendor group, taken from Settings → Users → Groups:
curl -X POST https://acme.mykreezalid.com/front_api/v1/account/create \ -H "Content-Type: application/json" \ -d '{ "email": "jane@example.com", "password": "correct horse battery staple", "first_name": "Jane", "last_name": "Doe", "group_id": 2 }'{ "code": 201, "success": true, "user": { "object": "User", "id": 5120, "email": "jane@example.com", "first_name": "Jane", "group": { "object": "Group", "id": 2, "name": "Customers", "alias": "customers" }, "can_post_listing": false }}The member receives the marketplace’s welcome email, or a confirmation email when the marketplace requires email validation. In that case the account stays inactive, and login fails, until the link in the email is clicked.
Then log in and keep the token:
const BASE = 'https://acme.mykreezalid.com/front_api/v1';
export async function login(email, password) { const res = await fetch(`${BASE}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, body: JSON.stringify({ email, password }), }); const body = await res.json(); if (res.status !== 200 || body.status !== 'success') { throw new Error(body.message || 'Login failed'); } return body.data.token; // store it in the Keychain / Keystore}
export async function api(path, token, init = {}) { const res = await fetch(`${BASE}${path}`, { ...init, headers: { ...init.headers, Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', Accept: 'application/json', }, }); if (res.status === 403) throw new Error('SESSION_EXPIRED'); // send the user back to login return res.json();}curl -X POST https://acme.mykreezalid.com/front_api/v1/auth/login \ -H "Content-Type: application/json" \ -d '{"email": "jane@example.com", "password": "correct horse battery staple"}'
curl https://acme.mykreezalid.com/front_api/v1/auth/me -H "Authorization: Bearer $TOKEN"The token lasts one year and cannot be refreshed: when a call answers 403, ask the member
to log in again. Logging out of the app means deleting the token from the device.
Forgotten passwords go through POST /front_api/v1/account/forgot-password, which emails a
reset link.
2. Show the catalog through your back end
Section titled “2. Show the catalog through your back end”The Front API does not browse the marketplace catalog. Give your back end an endpoint that reads it with the Admin API, keeps only what the app displays, and caches it:
const ADMIN = 'https://acme.mykreezalid.com/api/v1';const auth = Buffer.from(`${process.env.KREEZALID_API_KEY}:${process.env.KREEZALID_API_SECRET}`).toString('base64');
// GET /app/catalog?category=812&page=1 → what the app's list screen needsexport async function catalog({ category, page = 1 }) { const qs = new URLSearchParams({ status: 'published', admin_status: 'approved', page: String(page), limit: '24', fields: 'id,title,price,price_with_currency,cover,medias,owner,category', }); if (category) qs.set('category_id', String(category));
const res = await fetch(`${ADMIN}/listings?${qs}`, { headers: { Authorization: `Basic ${auth}` } }); const { listings, pagination } = await res.json();
return { items: listings.map((l) => ({ id: l.id, title: l.title, price: l.price_with_currency, image: l.cover ?? l.medias?.[0]?.src ?? null, vendor: l.owner?.public_name, })), hasMore: pagination.nextPage, };}Read categories for the navigation with GET /front_api/v1/categories, which needs no token,
and a vendor’s public profile with GET /front_api/v1/directories/{user_id}.
3. Cart and checkout
Section titled “3. Cart and checkout”The cart is fully available in the Front API:
-
Create a cart once per device or per member, with an empty body, and keep its
url_key:Terminal window curl -X POST https://acme.mykreezalid.com/front_api/v1/carts -H "Authorization: Bearer $TOKEN"{"status": "success","message": "Cart created successfully","cart": { "id": 7781, "object": "Cart", "customer_id": 5120, "tmp_customer_id": null, "url_key": "q8Zt3k…" }} -
Add listings:
Terminal window curl -X POST https://acme.mykreezalid.com/front_api/v1/carts/q8Zt3k… \-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \-d '{"listing_id": 645646, "quantity": 1}' -
Show it with
GET /front_api/v1/carts/{url_key}: it returns one order per vendor, the totals (subtotal_amount,shipping_amount,checkout_amount…) and each order’s items. -
For each order, list the delivery options with
GET /carts/{url_key}/orders/{order_id}/available-shipping-methodsand pick one withPATCH /carts/{url_key}/orders/{order_id}/shipping-method. -
Save the address with
POST /account/checkout-addresses, then attach it to the cart withPUT /carts/{url_key}/checkout-addresses/{checkout_address_id}.
Payment is not part of the Front API. Two options:
- open the marketplace’s checkout in an in-app browser, where the marketplace’s payment provider takes the payment;
- take the payment with your own provider in the app, then let your back end record it with the Admin API. See Record orders paid outside Kreezalid.
4. Orders and notifications
Section titled “4. Orders and notifications”The member’s orders, as a customer and, for vendors, as a seller, come from
GET /front_api/v1/orders; one order from GET /front_api/v1/orders/{id}.
For push notifications, subscribe your back end to the order webhooks it cares about, such as
order.status.accepted or order.status.shipped, look up the customer in data.customer.id,
and push to the devices you registered for that user.
5. Vendor features
Section titled “5. Vendor features”When the member’s group can post listings (can_post_listing: true in GET /auth/me), the
app can manage their catalog: GET /front_api/v1/listings lists their listings,
POST /listings/add creates one and PATCH /listings/{id}/edit updates one.
Checklist before release
Section titled “Checklist before release”- The app contains no Admin API credentials, in code or configuration.
- The base URL is the marketplace’s primary address, and is configurable without a new app release.
- A
403on any Front API call sends the member to the login screen. - Every response is checked for its
successorstatusfield, not only its HTTP code. See Errors. - Your back end verifies webhook signatures.