Walking in Their Footsteps
About
API Documentation

Native App Integration Guide

Complete API reference for integrating payment tiers, access control, and location data into iOS and Android apps

Base URL
https://walkingintheirfootsteps.com
Payment Integration Workflow

Step-by-Step Implementation:

  1. Call GET /getPasses to display available tiers
  2. User selects a pass → Call POST /createCheckout with deep link URLs
  3. Open checkout_url in webview or browser
  4. Stripe processes payment and redirects to success_url
  5. Call GET /getUserPasses to refresh user's active passes
  6. Cache passes locally for offline access checks
GET
/getPasses

Fetch all active pass tiers for purchase

Request:

GET https://walkingintheirfootsteps.com/getPasses

Response:

{
  "success": true,
  "data": [
    {
      "id": "pass_1",
      "name": "All Access Pass",
      "description": "Unlimited access to all locations",
      "type": "all_access",
      "price_eur": 29.99,
      "duration_days": 365,
      "features": ["All locations", "Offline downloads"],
      "is_featured": true
    },
    {
      "id": "pass_2",
      "name": "D-Day Campaign Pass",
      "type": "campaign",
      "price_eur": 9.99,
      "duration_days": 180,
      "included_campaigns": ["D-Day"]
    }
  ]
}
GET
/getUserPasses
Auth Required

Get authenticated user's purchased passes

Request:

GET https://walkingintheirfootsteps.com/getUserPasses
Authorization: Bearer <USER_JWT_TOKEN>

Response:

{
  "success": true,
  "has_active_pass": true,
  "data": [
    {
      "purchase_id": "pur_123",
      "pass_id": "pass_1",
      "pass_name": "All Access Pass",
      "pass_type": "all_access",
      "included_campaigns": [],
      "included_location_ids": [],
      "purchased_at": "2026-01-15T10:00:00Z",
      "expires_at": "2027-01-15T10:00:00Z",
      "is_lifetime": false,
      "is_expired": false
    }
  ]
}
POST
/createCheckout
Auth Required

Create Stripe checkout session for pass purchase

Request:

POST https://walkingintheirfootsteps.com/createCheckout
Content-Type: application/json
Authorization: Bearer <USER_JWT_TOKEN>

{
  "pass_id": "pass_1",
  "success_url": "yourapp://payment/success",
  "cancel_url": "yourapp://payment/cancel"
}

Response:

{
  "success": true,
  "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_...",
  "session_id": "cs_test_..."
}
Complete Integration Example (Swift/iOS)
// 1. Fetch available passes
let passes = await fetchPasses()
displayPassesInUI(passes)

// 2. User selects pass, create checkout
let checkoutData = await createCheckout(
  passId: selectedPass.id,
  successUrl: "yourapp://payment/success",
  cancelUrl: "yourapp://payment/cancel"
)

// 3. Open Stripe checkout
presentWebView(url: checkoutData.checkout_url)

// 4. Handle success callback (from deep link)
func handlePaymentSuccess() {
  let userPasses = await getUserPasses()
  cacheUserPasses(userPasses)
  showSuccessMessage()
}

// 5. Before showing location content
func canAccessLocation(locationId: String) -> Bool {
  let access = await checkLocationAccess(locationId: locationId)
  return access.has_access
}

// OR check locally from cached location data
let location = cachedLocations.first { $0.id == locationId }
if location.has_access {
  // Show content
} else if location.access_reason == nil {
  // Show paywall
}

// Access reasons:
// - "free" → Always show
// - "sponsored" → Always show (with sponsor credit)
// - "all_access_pass" → User has All Access
// - "campaign_pass" → User has campaign pass
// - "single_location_pass" → User has single location pass
// - nil/missing → Show paywall
Complete Integration Example (Kotlin/Android)
// 1. Fetch and display passes
val passes = apiService.getPasses()
recyclerView.adapter = PassesAdapter(passes)

// 2. Create checkout session
val checkout = apiService.createCheckout(
    passId = selectedPass.id,
    successUrl = "yourapp://payment/success",
    cancelUrl = "yourapp://payment/cancel"
)

// 3. Open checkout in Chrome Custom Tab
val intent = CustomTabsIntent.Builder()
    .build()
    .launchUrl(context, Uri.parse(checkout.checkoutUrl))

// 4. Handle success in deep link activity
override fun onNewIntent(intent: Intent) {
    if (intent.data?.toString()?.contains("payment/success") == true) {
        lifecycleScope.launch {
            val userPasses = apiService.getUserPasses()
            cacheUserPasses(userPasses)
            showSuccessDialog()
        }
    }
}

// 5. Access control before content display
suspend fun canAccessLocation(locationId: String): Boolean {
    val access = apiService.checkLocationAccess(locationId)
    return access.hasAccess
}

// OR use cached location data
val location = locationCache[locationId]
when (location?.accessReason) {
    "free", "sponsored" -> showContent()
    "all_access_pass", "campaign_pass", "single_location_pass" -> showContent()
    else -> showPaywall()
}
Important Notes

✅ All endpoints return JSON

✅ Location data includes has_access boolean

✅ Free and sponsored locations automatically have has_access = true

✅ Cache user passes locally for offline access checks

✅ Use deep links for Stripe redirect URLs

⚠️ Webhook handles purchase completion automatically

Access Reason Values

free
Location is not premium

sponsored
Active sponsorship

all_access_pass
User has All Access Pass

campaign_pass
User has Campaign Pass

single_location_pass
User has Single Location Pass

null/missing
No access - show paywall

Explore All Battlefield Locations

119 sites across Normandy and beyond

Sainte-Mère-Église Church·29th Infantry Division Monument·325th Glider Infantry Regiment Memorial·47 Royal Marine Commando Memorial·506th PIR Command Post·Abbaye d'Ardenne Memorial·Admiral Ramsay HQ - Ver sur Mer·Airborne Museum·Amfreville (Timmes Orchard)·Angoville-au-Plain Church·Ardenne Abbey (Abbaye d'Ardenne)·Arromanches 360 Circular Cinema·Arromanches les Bains·Azeville Battery·Batterie du Mont Canisy·Bayeux Memorial and Museum of the Battle of Normandy·Bayeux War Cemetery·Benouville War Cemetery·Bény-sur-Mer Canadian War Cemetery·Brécourt Manor·Brigadier General Theodore Roosevelt Jr. Monument·British Normandy Memorial·Brittany American Cemetery·C47 Memorial Garden Picauville·Caen British Garden of Peace·Café Gondrée·Cambes-en-Plaine War Cemetery·Canadian Military Cemetery Bretteville-Sur-Laize·Château de Colombières·Château de Creully·Chef-du-Pont Bridge·Churchill Mk IV AVRE ''One Charlie''·Company Sergeant Major Stanley Hollis VC Plaque·Cretteville A-14 Airfield Memorial·Crisbecq Battery·Croix de Guerre 5th Engineer Special Brigade·D-Day 70th Anniversary Memorial - Ouistreham·D-Day Experience·D-Day Landings Museum Arromanches·D-Day Omaha Museum·Dead Man's Corner (Saint-Côme-du-Mont)·Église Saint-Ferréol de Cauquigny·Falaise Memorial·Filthy Thirteen Memorial·Fontenay-le-Pesnel War Cemetery·Franceville Radar Station·German Tiger Tank - Vimoutiers·Gold Beach·Gold Beach, King Sector (La Rivière) where the 6th Green Howards came ashore at 07:32.·Graignes Memorial·Hermanville War Cemetery·Higgins Boat Memorial Utah Beach·Hill 112 Memorial - Normandy Battle·Hillman Fortress·Holdy Battery·Hottot-les-Bagues War Cemetery·Huisnes-sur-Mer German Cemetery·Iron Mike Memorial La Fiere·Jerusalem War Cemetery (Chouain)·Juno Beach·Juno Park·La Cambe German War Cemetery·La Maison des Canadiens (The Canada House)·Landing Ground A-16 Brucheville·Le Grand Bunker - Ouistreham·Les Braves Monument·Longues-sur-Mer battery·Maisy Battery·Major Richard Winters Memorial·Marmion’s Farm·Memorial 39-45 Saint Malo·Memorial of Eighth Air Force·Memorial Pegasus Bridge Museum·Memorial to the Barge Sunk by a Mine·Memorial to the Major of Saint-Lô·Merville Battery·Montormel Memorial·Monument Big Red One·Monument La Flamme - Ouistreham·Museum of Liberation Cherbourg·Museum of Underwater Wrecks·Normandy American Cemetery·Normandy French Resistance Monument·Normandy Victory Museum·Omaha Beach·Omaha Beach Memorial Museum·Orglandes German War Cemetery·Overlord Museum·Pegasus Bridge·Piper Bill Millin Memorial·Pointe du Hoc·Pont des Canadiens Le Mesnil-Villement·Porpoise Ammunition Sledge·Port-en-Bessin Harbour Commando Assault Site·Ranville War Cemetery·Royal Artillery Regiment Memorial - Ver sur Mer·Ryes-Bazenville War Cemetery·Saint-Aubin-sur-Mer 50mm Gun Casemate·Saint-Désir-de-Lisieux German War Cemetery·Saint-Lambert-sur-Dive (The Corridor of Death)·Sainte-Mère-Église·Secqueville-en-Bessin War Cemetery·Sexton 25 Pdr SP Gun - Ver sur Mer·Site de Panama - Fougerolles du Plessis·St. Charles de Percy War Cemetery·Stanley Hollis Hut D-Day Memorial·Sword Beach·The Canadian Memorial Garden Caen·The Sherman Tank at Courseulles-sur-Mer·Tilly-sur-Seulles Battle·Tilly-sur-Seulles War Cemetery·U.S. Navy Monument (Utah Beach)·Urville-Langannerie Polish Military Cemetery·Utah Beach·Utah Beach Museum·Ver-sur-Mer·Verrières Ridge·Villers-Bocage Battle Site·Wn 33a Graye-sur-Mer, La Brèche Le Bisson

Lest we forget — each name marks a place where history was made

Walking in Their Footsteps

Preserving history through immersive digital experiences

Quick Links

LocationsMapGPS Battlefield MapMini ToursTimelineTour PlannerWin PrizesCommunityBlogShopPassesAbout🚀 Kickstarter

Connect

Follow our journey on social media

© 2024 Walking in Their Footsteps. All rights reserved.

Privacy Policy

Built byDigital Battlefields (Worldwide) Ltd

🌍 Choose Language / Choisir la langue / Sprache wählen
Elegir idioma / Scegli la lingua / Kies taal / Escolher idioma / Wybierz język