Payment session lifecycle
Agent dashboard ──create──▶ LoopLoyal Payments API ──▶ session: created
│ │
│ SMS w/ one-time link (resend anytime)
│ ▶ link_sent
│ caller opens link, enters card (hosted fields)
│ → straight to merchant processor (tokenized)
│ ▶ in_progress ▶ processing
│ │
│ processor webhook (signed) ──▶ LoopLoyal Payments
│ ▶ succeeded | declined | failed
│ timer ▶ expired agent ▶ canceled
◀──── live status updates (safe fields only) ────┘Webhook events → status
| payment_session.created | Agent submits amount, ref, phone | Created |
| sms.delivered | SMS provider delivery receipt | Link sent |
| sms.resent | Agent re-sent the link (window refreshed) | Link sent |
| payment_session.capture_started | Caller opened link and started entering card | Caller entering card |
| processor.authorization_requested | Token submitted to merchant processor | Authorizing |
| processor.payment.succeeded | Processor webhook: approved | Paid |
| processor.payment.declined | Processor webhook: declined | Declined |
| processor.payment.failed | Network / processor error | Failed |
| payment_session.expired | 15 min TTL elapsed, link revoked | Expired |
| payment_session.canceled | Agent canceled | Canceled |
Agent can see
- Status + event timeline
- Amount, invoice reference
- Card brand + last 4
- Auth code, processor transaction ID
- Generic decline reason
- Masked phone (last 4)
Never stored or shown
- Full card number (PAN)
- CVV / CVC
- Expiry date
- Processor raw response codes
Production wiring (next steps)
- SMS via Twilio with a single-use, 15-minute link to processor hosted fields (Stripe / Authorize.net / Adyen on the merchant's account).
- Signed webhook endpoints for SMS and processor; verify HMAC before updating status.
- Replace the demo phone with a real SMS provider.