Vol. I · No. 01 · May 2026
The Portfolio
Case Study · 12 min read
Three products · One question

What does an
API choice look like
when you can feel it?

A close reading of three products: a private bank, a workout platform, and a delivery service, and the deliberate, opinionated decision behind each one's integration layer.

Studies
Three
Patterns
SOAP · GraphQL · REST
Surfaces
iOS, Android, Web
Discipline
Product Engineering
A Note from
the Editor

The pattern in this portfolio is not "we shipped a mobile app and a web app." The pattern is that each product makes a different deliberate choice about how mobile and web share data — and that choice is legible in the experience itself.

Meridian's private bankers need an audit trail, so the gateway is SOAP. Heat's coaches and athletes need a live feed, so the gateway is GraphQL. Bramble's kitchens and couriers need cacheable resources, so the gateway is REST. Three problems, three answers, three honest stacks.

01.
MERIDIAN · PRIVATE BANKING

When a wire
needs a signature.

A private bank can't pick a protocol on taste. It picks one that survives audit, settles with correspondents, and signs every byte going out.

Protocol
SOAP 1.2
Security
WS-Security
Contract
WSDL + XSD
Signed by
X.509
SYSTEM ARCHITECTURE
SURFACE
iOS & Android
React Native · FaceID
SIGNED ENVELOPE
over HTTPS
GATEWAY
SOAP 1.2 Service
WSDL contract · XSD schema
SIGNED ENVELOPE
over HTTPS
SURFACE
Next.js Web
SSR · Hardware key

The 6:42 PM wire transfer.

A client initiates a $28,500 wire from her iPhone at dinner. Her relationship manager sees it on the web dashboard moments later and counter-signs from his laptop. Same envelope, two signatures, one audit log.

IOS · 6:42 PM
Alexandra signs the wire
FaceID → X.509 token →
signed SOAP envelope
→ $28,500.00
REQUIRES 2ND SIG
WEB · 6:43 PM
James receives an alert
Hardware key → second X.509
signature appended to envelope
✓ Released to settle
VALUE DATE: 16 MAY

The envelope both clients send.

Mobile or web — the wire is the same SOAP envelope with a WS-Security header. Two X.509 signatures must be present for any transfer above $25,000.

submitWireTransfer · v2
<soap:Envelope>
  <soap:Header>
    <wsse:Security>
      <!-- Signature #1: Alexandra's iPhone -->
      <wsse:BinarySecurityToken Id="X509-iOS"/>
      <ds:Signature>...</ds:Signature>

      <!-- Signature #2: James's hardware key -->
      <wsse:BinarySecurityToken Id="X509-RM"/>
      <ds:Signature>...</ds:Signature>
    </wsse:Security>
  </soap:Header>
  <soap:Body>
    <mer:SubmitWireTransferRequest>
      <mer:Amount currency="USD">28500.00</mer:Amount>
      <mer:Beneficiary>Le Bernardin Holdings</mer:Beneficiary>
      <mer:ValueDate>2026-05-16</mer:ValueDate>
    </mer:SubmitWireTransferRequest>
  </soap:Body>
</soap:Envelope>
Mobile balance card
IOS · ANDROID
— SAME ENVELOPE →
Web portfolio dashboard
NEXT.JS
mer:Settled
$284,392.18 (hero balance)
$284,392.18 (with cents emphasis)
mer:Available
$271,892.18
$271,892.18 (with pending breakdown)
mer:Pending
— (collapsed)
$12,500.00 (inline detail)
mer:Currency
USD
USD (multi-currency selector)
mer:AsOf
"Live"
"As of 2026-05-15 · 18:42 UTC"
"We didn't choose SOAP because we love angle brackets.
We chose it because the auditor does."
— CTO, Hypothetical Private Bank
02.
HEAT · WELLNESS

When you need
just the BPM.

A workout app surfaces deeply-related data — sessions, exercises, sets, reps, heart rate samples. Each screen needs a different slice. Each slice is one query away.

Protocol
GraphQL
Transport
HTTP + WSS
Schema
SDL typed
Live data
~1Hz
SYSTEM ARCHITECTURE
SURFACE
iOS & Android
React Native · Apollo
QUERY · MUT · SUB
HTTP / WSS
GATEWAY
GraphQL Server
One schema · One URL
QUERY · MUT · SUB
HTTP / WSS
SURFACE
Next.js Web
SSR · Apollo

The 5:30 PM burpee circuit.

Maya starts a Primal Force session on her phone, paired to her chest strap. Her coach watches the BPM live from a laptop in Lagos. Same subscription, same socket, same numbers — both renders update in lockstep.

PHONE · LIVE
158BPM
Zone 4 · hold the pain
SET 3 / 50:42 LEFT
COACH · WEB
158BPM
Maya · in the green
AVG 142PEAK 168

The subscription both clients open.

Mobile or web — the live HR feed is the same GraphQL subscription over a WebSocket. The server fans out one event to every subscriber.

liveHeartRate · subscription
# Both clients open the same subscription
subscription LiveHeartRate($sessionId: ID!) {
  liveHeartRate(sessionId: $sessionId) {
    bpm
    zone           # 1 (recovery) → 5 (max)
    timestamp
    deltaFromAvg
  }
}

# Each event, ~once per second:
{
  "bpm": 158,
  "zone": 4,
  "timestamp": "2026-05-15T17:30:42Z",
  "deltaFromAvg": +16
}
Mobile home screen
QUERY: HomeScreen
— ONE SCHEMA →
Web dashboard
QUERY: DashboardScreen
me.today.caloriesBurned
847 KCAL (hero card)
847 (with weekly bar chart)
me.streak.days
23 day streak
23 (with calendar heatmap)
me.upNext(limit:N)
limit: 3 workouts
limit: 10 (weekly programmer)
me.leaderboardRank
— (not requested)
#01 (with 5-deep peer view)
me.today.zoneBreakdown
— (not requested)
Zones 1–5 time-in-zone detail
"REST gave us five round trips to render one home screen.
GraphQL gave us one."
— Lead Mobile Engineer, Hypothetical Fitness Co.
03.
BRAMBLE · FOOD DELIVERY

When a menu
should just be
a resource.

Food delivery is a system of resources with clear lifecycles. REST gives it three things for free: edge caching, idempotency, and a model that a thousand third-party kitchens already understand.

Protocol
REST JSON
Caching
CDN edge
Idempotency
UUID keys
Realtime
SSE stream
SYSTEM ARCHITECTURE
SURFACE
iOS & Android
React Native · TanStack
HTTP · CACHED
via CDN edge
GATEWAY
REST API · v1
Resourceful · cacheable
HTTP · CACHED
via CDN edge
SURFACE
Next.js Web
SSR · ISR · TanStack

The 6:42 PM order ticket.

A customer stages a cart from Ondo on the iPhone in line at a meeting, then opens her laptop at home to complete checkout. Same cart, one order, one idempotency key — the duplicate submit is silent.

MOBILE · 6:38 PM
Cart staged on the phone
POST /v1/carts
Idempotency-Key: a1b2c3d4
→ Miso Cod · Truffle Soba
SUBTOTAL · $58.00
WEB · 6:42 PM
Checkout on the laptop
POST /v1/orders
Idempotency-Key: a1b2c3d4
✓ ord_8KQ4ZJ2x · ETA 7:12
SAME KEY · ONE CHARGE

The endpoint both clients call.

Mobile or web — the order goes to the same endpoint with the same idempotency key. A duplicate request returns the original order instead of creating a second one.

POST /v1/orders
POST /v1/orders HTTP/1.1
Authorization:   Bearer brk_live_XXXX
Idempotency-Key: "a1b2c3d4-e5f6-..."
Content-Type:    application/json

{
  "restaurant_id": "rest_ondo_001",
  "items": [
    { "menu_item_id": "mi_miso_cod", "qty": 1 },
    { "menu_item_id": "mi_truffle_soba", "qty": 1 }
  ],
  "delivery_address": { "line1": "24 Bedford St" },
  "tip_cents": 800
}

# Response — 201 Created (or 200 OK on duplicate)
{
  "id": "ord_8KQ4ZJ2x",
  "status": "pending_confirmation",
  "total_cents": 7114,
  "estimated_delivery_at": "2026-05-15T19:12:00Z"
}
Mobile restaurant card
GET /v1/restaurants/:id
— SAME JSON →
Web hero card
GET /v1/restaurants/:id
restaurant.name
"Ondo" (single line, 22pt)
"Ondo" (display, 32pt + tag)
restaurant.rating
4.9 ★ (pill)
4.9 ★ + (2,841 reviews)
restaurant.prep_time_min
"20–30 min"
"20–30 min" + courier ETA
restaurant.hero_image_url
Full-width banner @ 2x
Letterboxed hero @ 3x
order.status (SSE)
Status badge + push
Full timeline view
"Our menu lives on a CDN.
Our orders live behind an idempotency key."
— VP Engineering, Hypothetical Delivery Co.
Three answers · Three reasons

The right answer is
the one your product asks for.

An API is not a technical detail. It's a posture. It's how a product tells its operators, its partners, and its future self what kind of problems it's trying to solve.

CASE 01 · MERIDIAN

SOAP, because the auditor matters.

Wires, custody, and discretionary mandates demand a contract you can hand to a regulator. SOAP gives every transaction a signed, replayable envelope — and a WSDL that a treasury system can already parse.

SOAP 1.2 WS-SECURITY
CASE 02 · HEAT

GraphQL, because screens differ.

A phone needs three workouts and a streak. A coach's dashboard needs the full leaderboard and zone-by-zone breakdowns. Same schema, same socket, different selections — and a live BPM feed that fans out in real time.

GRAPHQL WSS · APOLLO
CASE 03 · BRAMBLE

REST, because resources cache.

A menu read 10,000 times an hour belongs at the CDN edge. An order created from two devices belongs behind an idempotency key. REST gives us both for free — and a JSON shape that any third-party kitchen display already knows how to render.

REST · JSON CDN · SSE
Three products. Three answers. Designed in service of the problem.
VOL. I · NO. 01 · MMXXVI