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