{{ brand.companyName }}
{{ brand.tagline || 'PCI Compliance Attestation' }}
{{ brand.companyName }}
{{ brand.tagline }}
Trust & Legal API Docs
{{ apiKey.startsWith('cat_live_') ? 'API Key' : 'Session Token' }}
{{ apiKey.slice(0, 16) }}…
CONNECTED
Embed missing valid API key. Append ?apiKey=cat_live_… or postMessage cat:configure.
{{ signInError }}
Live Demo · Bank of CAT

Three integration paths. One compliance engine.

Bank of CAT integrated the CAT compliance platform three ways: a REST API for their internal CRM, an embeddable iframe for their merchant portal, and an MCP server for their AI support chatbot. Every tab below hits real production endpoints — click 🚀 Use demo configuration to start.

{{ t.icon }}
{{ t.label }}
{{ t.blurb }}
📊 What you're seeing

Bank of CAT internal CRM — backed by the REST API

Bank of CAT staff log in here to see their merchants' PCI compliance posture. Every row is fetched live with GET /v1/merchants.

📈 Portfolio compliance overview

How much of your book is compliant, and what's expiring

{{ Math.round((portfolio.complianceRate || 0) * 100) }}%
compliant & current
Compliant
{{ portfolio.totals.compliant }}
Expiring soon
{{ portfolio.totals.expiringSoon }}
Expired
{{ portfolio.totals.expired }}
In progress
{{ portfolio.totals.inProgress }}
Not started
{{ portfolio.totals.notStarted }}
📉 Merchant funnel — where your book is on the path to compliance
🗂 SAQ-type breakdown
{{ saqType }} · {{ count }}
⏳ Expiring soon — worth a check-in before these lapse
{{ e.name }}
{{ e.saqType }}
expires in {{ e.daysUntilExpiry }} day{{ e.daysUntilExpiry === 1 ? '' : 's' }}
as of {{ fmtDate(portfolio.generatedAt) }}
⏳ Loading portfolio overview…
Total merchants
{{ stats.total }}
Compliant
{{ stats.compliant }}
In progress
{{ stats.inProgress }}
Not started
{{ stats.notStarted }}

Merchants under Bank of CAT

MerchantExternal IDStatus
{{ m.name }}
{{ m.email }}
{{ m.externalMerchantId || '—' }} {{ (m.effectiveStatus || m.complianceStatus || '').replace(/_/g, ' ') }}
{{ expiryNote(m) }}
Loading…
REST traffic
// HTTP traffic appears here
{{ e.t }} {{ e.statusCode }}
{{ e.dir === 'out' ? '→ ' + e.method + ' ' + e.path : '← response' }}
{{ e.body }}

{{ drill.merchant.name }}

{{ drill.merchant.email || 'no email on file' }} · {{ drill.merchant.externalMerchantId || 'no external ID' }}
Compliance lifecycle
{{ (drill.merchant.effectiveStatus || drill.merchant.complianceStatus || '').replace(/_/g,' ') }}
{{ expiryNote(drill.merchant) }}
Last SAQ: {{ drill.merchant.lastSaqType }}
Compliant since {{ fmtDate(drill.merchant.compliantAt) }}
Invite
Sent {{ fmtDate(drill.merchant.invite.sentAt) }} · {{ drill.merchant.invite.count }} time{{ drill.merchant.invite.count === 1 ? '' : 's' }}
Link expires {{ fmtDate(drill.merchant.invite.linkExpiresAt) }}
No invite sent yet.
{{ drill.inviteMsg }}
SAQ attempts
Loading…
No SAQ attempts yet.
{{ att.saqType }} {{ (att.status || '').replace(/_/g,' ') }} renewable
{{ att.documentKeys && att.documentKeys.sealedAt ? 'sealed ' + fmtDate(att.documentKeys.sealedAt) : 'opened ' + fmtDate(att.createdAt) }}
Loading answers…
No answers recorded.
{{ q.controlId }} {{ q.status }} {{ q.answer || '—' }} carried forward
Recent audit events
Loading…
No audit events for this merchant.
{{ ev.eventType }} {{ ev.actor }}
{{ fmtDate(ev.timestamp) }}
👤 What you're seeing

Customer-facing portal — backed by the REST API

A merchant of Bank of CAT (e.g., City of CAT) walks through completing one SAQ per payment method. Every interaction is a real REST call — watch the log on the right.

Continuing your PCI compliance attestation for {{ handoff.partnerName || handoff.returnHost }} — we'll send you back when you're done.
  1. {{ i + 1 }}. {{ s }}

{{ heroMerchantName }} Annual payment-security check for {{ brand.companyName || 'your bank' }}

Let's get you compliant. First, tell us how your business takes card payments — in your own words. It takes about 15 minutes.

✓ {{ assessmentsDone }} of {{ assessmentsTotal }} assessment{{ assessmentsTotal === 1 ? '' : 's' }} complete
🎉 You're all set — every payment method is covered.

Your bank has your signed documents. Nothing else is needed until your next annual review, due {{ nextReviewDate }}.

We'll email you before anything expires.

What is this?

Businesses that accept cards complete a short annual security self-assessment (called PCI DSS) confirming they handle card details safely.

You complete one assessment for each way you take payments — in person, online, over the phone, and so on. Your answers generate the official documents your bank keeps on file.

We never ask for card numbers.

Your ways of taking payments

{{ pm.name }}
{{ pm.description }}
{{ pmSaqType(pm) }}
Not started
In progress
✓ Complete {{ pmSealedDate(pm) }}

{{ showAddForm ? 'Add another way you take payments' : 'Tell us how you take card payments' }}

Describe it in plain language — the vendor, the device or website, and how a customer's card details flow. We never ask for card numbers.

Step 1 — Identify the merchant

Loading your assessment…

Step 3 — AI determines your SAQ type

The AI reads your payment method description, grounds itself in PCI DSS v4.1 documentation, and tells you which SAQ applies — plus the qualifications you'll need to meet.

Your payment method description:
{{ flow.pmDescription }}
⏳ Reviewing your answers to find the right assessment for your business… usually under two minutes.
🤖 AI needs more info
{{ flow.determination.followUpQuestion }}
✓ {{ flow.determination.saqType }} determined by AI
{{ flow.determination.reason }}
Qualifications you must meet:
  • {{ q.question }} ({{ q.pciReference }})
Helpful references:
or pick manually

Step 4 — {{ flow.saqType }} · Section {{ flow.sectionIdx + 1 }} of {{ flow.sectionList.length }}

{{ flow.attemptId.slice(0,16) }}…

Answer one combined question per requirement; the AI distributes your answer across all controls in that requirement.

All sections answered. .
Refining flagged control
Control {{ flow.refineChildId }}
PCI DSS Requirement {{ currentSection.topLevel }}
{{ currentSection.title }}
Covers {{ currentSection.children.length }} sub-control{{ currentSection.children.length === 1 ? '' : 's' }}
🤖 Combined question (covers all sub-controls in this requirement)
{{ currentSection.combinedQuestion }}
⏳ Generating combined question…
Click Generate combined question below to start.
Show all {{ currentSection.children.length }} sub-controls in this section
  • {{ c.controlId }} {{ c.status }} — {{ (c.requirement || c.title || '').slice(0, 140) }}
✓ Section answered — AI distributed across {{ currentSection.children.length }} sub-controls Advancing to next section in {{ flow.autoAdvanceCountdown }}s ·
Your combined answer: {{ currentSection.parentAnswer }}
{{ c.controlId }} {{ c.status || 'pending' }}
{{ c.reason.slice(0, 120) }}
🤖 Refined question for {{ flow.refineChildId }}
{{ refineQuestion?.combinedQuestion || refineQuestion?.requirement || 'Loading…' }}
AI-suggested combined answers:

Step 5 — Attestation of Compliance review

A few consolidated questions to fill the AoC cover sheet. Each maps to the same field your bank's auditor would expect: company info, address, acquirer/processor, locations that touch card data, and a brief business description. Any "Not In Place" controls flagged earlier will also need a remediation plan.

⏳ Loading review groups…
{{ g.groupId.replace(/_/g, ' ') }}{{ g.required ? '' : ' (optional)' }}
{{ g.question }}
{{ g.hint }}
✓ saved

Step 6 — Sign & finalize

Type your full legal name and title. We'll render this in cursive on the AoC attestation page along with today's UTC timestamp.

⏳ Preparing your official documents ({{ flow.finalizeElapsedSec }}s elapsed). This usually takes 3–5 minutes — please keep this window open.
{{ flow.finalizeError }}
If you received the SAQ + AoC PDFs by email, the seal succeeded and only the response back to this page failed. Click "Check status" to verify and pull the download links.
🎉 {{ flow.finalizeResult.saqType }} finalized and submitted to the bank.
Findings: {{ flow.finalizeResult.breakdown.inPlace }} In Place · {{ flow.finalizeResult.breakdown.notInPlace }} Not In Place · {{ flow.finalizeResult.breakdown.notApplicable }} N/A{{ flow.finalizeResult.breakdown.compensating ? ' · ' + flow.finalizeResult.breakdown.compensating + ' Compensating' : '' }}
These stay available on your home page too — your bank automatically receives a copy.
REST traffic
// HTTP traffic appears here as you click around.
{{ e.t }} {{ e.statusCode }}
{{ e.dir === 'out' ? '→ ' + e.method + ' ' + e.path : '← response' }}
{{ e.body.length > 600 ? e.body.slice(0,600) + '\n…' : e.body }}
🤖 What you're seeing

Bank of CAT support chatbot — driven by the MCP server

A simulated AI assistant that walks the merchant through their entire PCI SAQ. Every step the bot takes is a real POST /mcp tool call — see the JSON-RPC traffic on the right. This is what you build when you embed the MCP server in your bank's existing chat copilot.

🤖
Bank of CAT Compliance Assistant
Powered by MCP · {{ chat.toolsCalled }} tools called
💬

Start a conversation with the AI assistant.
It'll walk you through the entire SAQ via MCP tool calls.

{{ m.tool }}
{{ f.controlId }} {{ f.status }}
{{ chat.botStatus }}
Live MCP traffic
// JSON-RPC requests appear here as the bot makes them.
{{ e.t }}
{{ e.dir === 'out' ? '→ POST /mcp' : '← response' }} {{ e.method }}
{{ e.body.length > 700 ? e.body.slice(0,700) + '\n…' : e.body }}
🖼️ What you're seeing

Bank of CAT merchant portal — with the iframe embedded

Below is a mockup of bankofcat.com/merchants/compliance. The grey area inside the page is a live <iframe src="https://api.complianceassessmenttool.com/portal/embed?…"> rendered fresh from production. Watch the postMessage events below as the customer clicks through.

🔒 bankofcat.com/merchants/compliance
Bank of CAT
↓ This is the live iframe — same code that any of our partners would embed:
Embed code (4 lines)
{{ embedSnippet }}
postMessage events
// Events from the iframe appear here:
cat:ready · cat:payment-method-added
cat:saq-submitted · cat:all-complete
{{ e.t }}
{{ e.type }}
{{ JSON.stringify(e.payload, null, 2).slice(0, 400) }}
💡 Why this matters

Your partners can drop the iframe into their existing merchant portal in 4 lines of HTML. No customer-facing rebuilds. No data leaving CAT's tenant boundary. Their merchant sees your bank's chrome but completes a real PCI SAQ behind the scenes.

👑 Founder / Super-Admin View

Partner onboarding & cross-partner monitoring

Logged in as {{ admin.me?.name || admin.me?.id }} · {{ admin.me?.id }} · key prefix {{ admin.me?.apiKeyPrefix }}. {{ admin.me?.webhookSecretConfigured ? '✓' : '✗' }} webhookSecret configured.

1. Review the application

When a bank or ISO submits at /signup, it shows up below as pending. Read the contact + use case, then click Approve. (For offline deals: have them submit the form themselves with "notes: closed via sales call" so the audit trail is intact.)

2. Issue + deliver credentials

Approval mints a cat_live_… API key + webhook signing secret once. The yellow banner that appears has copy buttons — paste each into a one-time-view channel (1Password Send, Bitwarden Send) and email the link to the bank's contact. They are never recoverable after dismiss.

3. Configure billing + branding

Select the new partner from the list (left column). Set their per-merchant fee + billing cycle (this provisions a Stripe subscription) and set their brand color / logo / support email. Click Generate Stripe quote to send them a signable PDF before they're charged.

4. Wire up platform redirect (optional)

If the bank wants to redirect their merchants to our portal and get them back when done, enable Platform redirect and add their hostnames to the allowlist. They then call POST /v1/merchants/:m/portal-link with a returnUrl; we validate it against this list. The "What to tell the bank's integration team" block has copy-pasteable instructions.

Checklist after onboarding: credentials delivered ▸ billing active (card on file) ▸ branding set ▸ handoff enabled (if applicable) ▸ first webhook signature verified end-to-end ▸ welcome email sent. The partner detail panel will show which of these are still outstanding.

📖 Founder library

admin-only — never shared with partners

Your meeting prep, in one click. The pitch deck is intentionally shareable — present from it, then send the link as the leave-behind.

🖥 Pitch deck ↗ 🧮 ROI calculator ↗

{{ admin.library.title }}

Loading…

Partner applications

Self-serve signups from /signup awaiting your review.

Loading…
No {{ admin.appStatus || '' }} applications.
{{ a.legalName }} {{ a.status }} {{ a.entityType }}
{{ a.contactName }}{{ a.contactTitle ? ' · ' + a.contactTitle : '' }} · {{ a.contactEmail }} {{ a.contactPhone ? ' · ' + a.contactPhone : '' }}
{{ a.websiteUrl || '' }} {{ a.estimatedMerchants ? '· ~' + a.estimatedMerchants + ' merchants/yr' : '' }} · submitted {{ fmtDate(a.createdAt) }}
{{ a.primaryUseCase }}
✓ Partner record: {{ a.approvedPartnerId }} · approved by {{ a.reviewedBy }} on {{ fmtDate(a.reviewedAt) }}
✗ Denied: {{ a.denialReason }} ({{ fmtDate(a.reviewedAt) }})

Approve "{{ admin.approveDialog.application.legalName }}"

This will mint a new partner record, a one-time-view API key, and a webhook signing secret. The plaintext credentials are shown once — be ready to deliver them via a secure channel.

{{ admin.approveDialog.error }}

Deny "{{ admin.denyDialog.application.legalName }}"

A denial reason is recorded on the application row. Be specific — the applicant can request reconsideration with new information.

{{ admin.denyDialog.error }}

⚠ One-time credential view — {{ admin.approval.application?.legalName }}

These credentials are shown exactly once. The easiest delivery: send the bank the claim link below — it renders the credentials one time, then self-destructs. They are not recoverable server-side — only the SHA-256 hash of the API key is stored.

✉ One-time claim link — send THIS to the bank{{ admin.approval.welcomeEmailSent ? ' (already emailed to the applicant ✓)' : '' }}
{{ admin.approval.claimUrl }}
expires {{ fmtDate(admin.approval.claimExpiresAt) }}
Partner ID
{{ admin.approval.partnerId }}
API Key (X-API-Key)
{{ admin.approval.apiKey }}
Webhook signing secret
{{ admin.approval.webhookSecret }}
Old key remains valid until {{ fmtDate(admin.approval.previousKeyExpiresAt) }}, then dies (zero-downtime rollover window).
Billing: {{ admin.approval.billing.error ? ('⚠ setup failed — ' + admin.approval.billing.error) : (admin.approval.billing.status || 'not configured') }} ·

Partners

Loading…
Click "Load partners" to fetch.
{{ p.name }}
{{ p.id }}
{{ p.contactEmail || '—' }}
{{ p.active === false ? 'inactive' : 'active' }} {{ p.tier || 'standard' }} 🧪 sandbox
Select a partner from the left to view their merchants, audit events, and recent activity.

🔐 Admin verification

Enter the 6-digit code from your authenticator app to unlock admin actions for the next 12 hours.

{{ mfa.error }}