@baseUrl = http://localhost:4000/api/v1
@apiRoot = http://localhost:4000/api
# Production:
# @baseUrl = https://api.gatewise.ng/v1
# @apiRoot = https://api.gatewise.ng
@accessToken = replace-after-auth
@estateId = 00000000-0000-4000-8000-000000000001
@userId = replace-with-sales-admin-user-id
@paymentReference = FLU-1778881112222-a1b2c3d4
@customerEmail = estate.admin@example.com

### Login with seeded super admin
POST {{baseUrl}}/auth/login
Content-Type: application/json

{
  "phone": "+2348000000001"
}

### Verify OTP
POST {{baseUrl}}/auth/verify-otp
Content-Type: application/json

{
  "phone": "+2348000000001",
  "otp": "123456"
}

### Login with seeded sales admin
POST {{baseUrl}}/auth/login
Content-Type: application/json

{
  "phone": "+2348000000005"
}

### Open Swagger docs (super admin bearer token or browser console cookie required)
GET {{apiRoot}}/docs
Authorization: Bearer {{accessToken}}

### Request super admin console OTP
POST {{baseUrl}}/console/request-otp
Content-Type: application/json

{
  "phone": "+2348000000001",
  "returnTo": "/api/docs"
}

### Open browser sandbox (super admin bearer token or browser console cookie required)
GET {{baseUrl}}/sandbox
Authorization: Bearer {{accessToken}}

### Signup resident
POST {{baseUrl}}/auth/signup
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "estateId": "{{estateId}}",
  "name": "New Resident",
  "phone": "+2348000000100",
  "role": "RESIDENT",
  "unit": "B14"
}

### List public subscription plans
GET {{baseUrl}}/onboarding/subscription-plans

### List public payment providers
GET {{baseUrl}}/onboarding/payment-providers?estateId={{estateId}}

### Estate admin lead signup
POST {{baseUrl}}/onboarding/estate-admin-signup
Content-Type: application/json

{
  "estateName": "GreenPark Estate",
  "location": "Lagos, Nigeria",
  "unitCount": 120,
  "estateType": "Residential gated community",
  "adminName": "Estate Admin",
  "adminPhone": "+2348000000990",
  "adminEmail": "{{customerEmail}}",
  "metadata": {
    "source": "api.http"
  }
}

### Estate admin selects plan after approval
POST {{baseUrl}}/onboarding/estates/{{estateId}}/select-plan
Content-Type: application/json

{
  "adminPhone": "+2348000000990",
  "planCode": "GROWTH",
  "paymentProvider": "FLUTTERWAVE"
}

### Estate admin initializes hosted sandbox checkout
POST {{baseUrl}}/onboarding/estates/{{estateId}}/payments/initialize
Content-Type: application/json

{
  "adminPhone": "+2348000000990",
  "customerEmail": "{{customerEmail}}",
  "customerName": "Estate Admin",
  "planCode": "GROWTH",
  "paymentProvider": "FLUTTERWAVE",
  "metadata": {
    "channel": "card"
  }
}

### Hosted payment redirect callback example
GET {{baseUrl}}/onboarding/payments/callback?provider=FLUTTERWAVE&reference={{paymentReference}}&transaction_id=123456789

### Estate admin records payment reference
POST {{baseUrl}}/onboarding/estates/{{estateId}}/payments
Content-Type: application/json

{
  "adminPhone": "+2348000000990",
  "reference": "{{paymentReference}}",
  "metadata": {
    "channel": "manual"
  }
}

### List estates
GET {{baseUrl}}/estates
Authorization: Bearer {{accessToken}}

### Feature catalog
GET {{baseUrl}}/features/catalog
Authorization: Bearer {{accessToken}}

### My effective features
GET {{baseUrl}}/features/me
Authorization: Bearer {{accessToken}}

### Super admin views sales admin feature settings
GET {{baseUrl}}/features/role-settings?role=SALES_ADMIN
Authorization: Bearer {{accessToken}}

### Super admin enables sales admin payment visibility
PATCH {{baseUrl}}/features/role-settings/SALES_ADMIN
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "settings": [
    {
      "feature": "PAYMENTS_VIEW",
      "enabled": true
    },
    {
      "feature": "PAYMENT_PROVIDERS_VIEW",
      "enabled": true
    }
  ]
}

### Super admin enables sales partner earnings and admin contact
PATCH {{baseUrl}}/features/role-settings/SALES_ADMIN
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "settings": [
    {
      "feature": "SALES_PARTNER_EARNINGS_VIEW",
      "enabled": true
    },
    {
      "feature": "SALES_PARTNER_ADMIN_CONTACT",
      "enabled": true
    }
  ]
}

### Estate admin disables guard manual check-in for own estate
PATCH {{baseUrl}}/features/role-settings/GUARD
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "estateId": "{{estateId}}",
  "settings": [
    {
      "feature": "CHECKIN_MANUAL",
      "enabled": false
    }
  ]
}

### Create visitor
POST {{baseUrl}}/visitors
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "estateId": "{{estateId}}",
  "name": "John Doe",
  "phone": "+2348111111111",
  "vehiclePlate": "LND-123-AB"
}

### Create visitor pass
POST {{baseUrl}}/visitors/passes
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "estateId": "{{estateId}}",
  "hostResidentId": "replace-with-resident-id",
  "visitorId": "replace-with-visitor-id",
  "validFrom": "2026-05-15T08:00:00.000Z",
  "validUntil": "2026-05-15T18:00:00.000Z",
  "passType": "SINGLE_USE"
}

### Guard QR check-in
POST {{baseUrl}}/checkin/scan
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "estateId": "{{estateId}}",
  "qrToken": "replace-with-qr-token",
  "guardId": "replace-with-guard-id",
  "deviceId": "gate-tablet-001",
  "entryGate": "Main Gate"
}

### Guard manual check-in
POST {{baseUrl}}/checkin/manual
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "estateId": "{{estateId}}",
  "visitorCode": "replace-with-visitor-code",
  "guardId": "replace-with-guard-id",
  "deviceId": "gate-tablet-001",
  "entryGate": "Main Gate"
}

### Offline bootstrap payload
GET {{baseUrl}}/offline/bootstrap?estateId={{estateId}}
Authorization: Bearer {{accessToken}}

### Super admin dashboard
GET {{baseUrl}}/admin/dashboard
Authorization: Bearer {{accessToken}}

### Super admin views OTP provider configuration
GET {{baseUrl}}/admin/otp/config
Authorization: Bearer {{accessToken}}

### Super admin switches OTP provider to DEV
PATCH {{baseUrl}}/admin/otp/config
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "provider": "DEV",
  "enabledProviders": ["DEV"],
  "providerPriority": ["DEV", "TERMII", "AFRICAS_TALKING", "CUSTOM_HTTP"],
  "ttlSeconds": 300,
  "codeLength": 6,
  "maxAttempts": 5,
  "exposeDevCode": true
}

### Super admin configures Termii OTP
PATCH {{baseUrl}}/admin/otp/config
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "provider": "TERMII",
  "enabledProviders": ["TERMII", "AFRICAS_TALKING"],
  "providerPriority": ["TERMII", "AFRICAS_TALKING", "CUSTOM_HTTP"],
  "ttlSeconds": 300,
  "codeLength": 6,
  "maxAttempts": 5,
  "exposeDevCode": false,
  "termiiBaseUrl": "https://api.ng.termii.com",
  "termiiApiKey": "TERMII_API_KEY",
  "termiiSenderId": "SmartEstate",
  "termiiChannel": "dnd"
}

### Super admin configures custom SMS OTP endpoint
PATCH {{baseUrl}}/admin/otp/config
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "provider": "CUSTOM_HTTP",
  "enabledProviders": ["CUSTOM_HTTP"],
  "providerPriority": ["CUSTOM_HTTP", "TERMII", "AFRICAS_TALKING"],
  "customHttpUrl": "https://sms.example.com/send",
  "customHttpMethod": "POST",
  "customHttpHeadersJson": "{\"Authorization\":\"Bearer sms_api_key\"}",
  "customHttpBodyTemplate": "{\"to\":\"{{phone}}\",\"message\":\"{{message}}\",\"code\":\"{{otp}}\"}"
}

### Super admin reviews estate signup
PATCH {{baseUrl}}/admin/estate-signups/{{estateId}}/review
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "status": "APPROVED",
  "reviewNotes": "Approved for subscription plan selection."
}

### Super admin confirms estate payment
PATCH {{baseUrl}}/admin/estate-signups/{{estateId}}/confirm-payment
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "paymentReference": "{{paymentReference}}"
}

### Super admin creates custom plan with feature list
POST {{baseUrl}}/admin/subscription-plans
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "code": "CUSTOM_LUXURY",
  "name": "Luxury Custom",
  "minResidents": 301,
  "maxResidents": null,
  "monthlyPriceKobo": 150000000,
  "currency": "NGN",
  "customPricing": true,
  "description": "Custom plan controlled by super admin.",
  "isActive": true,
  "features": ["RESIDENTS_VIEW", "GUARDS_VIEW", "VISITORS_VIEW", "VISITOR_PASSES_CREATE", "CHECKIN_SCAN"]
}

### Super admin updates plan features
PATCH {{baseUrl}}/admin/subscription-plans/STARTER
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "monthlyPriceKobo": 25000000,
  "isActive": true,
  "features": ["RESIDENTS_VIEW", "VISITORS_VIEW", "VISITOR_PASSES_CREATE", "CHECKIN_SCAN"]
}

### Super admin lists sales partners
GET {{baseUrl}}/admin/sales-partners
Authorization: Bearer {{accessToken}}

### Sales admin views own partner profile
GET {{baseUrl}}/admin/sales-partners/me
Authorization: Bearer {{accessToken}}

### Sales admin views own earnings
GET {{baseUrl}}/admin/sales-partners/me/earnings
Authorization: Bearer {{accessToken}}

### Super admin enables partner earnings
PATCH {{baseUrl}}/admin/sales-partners/{{userId}}
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "enabled": true,
  "commissionPercent": 7.5,
  "notes": "Partner status enabled after super-admin review."
}

### Super admin assigns estate to sales partner
PATCH {{baseUrl}}/admin/estates/{{estateId}}/sales-partner
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "salesAdminId": "{{userId}}"
}

### Sales partner contacts assigned estate admins
POST {{baseUrl}}/admin/estates/{{estateId}}/admin-contact
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "channel": "SMS",
  "message": "Please complete your subscription payment so we can activate your estate.",
  "metadata": {
    "reason": "PAYMENT_PENDING"
  }
}

### Super admin toggles global payment provider
PATCH {{baseUrl}}/admin/payment-providers/FLUTTERWAVE
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "enabled": true
}

### Super admin toggles estate payment provider override
PATCH {{baseUrl}}/admin/estates/{{estateId}}/payment-providers/PAYSTACK
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "enabled": true
}
