Tenant Verification Quickstart#

Verify a tenant's identity, income, credit history, and cash flow. CasaPay connects to bank accounts, pulls credit bureau data, verifies employment, and detects document fraud — all through a single API.

Step 1: Create a Verification Session#

Create a session specifying which checks to run. The session returns a client_secret for the hosted widget, or you can redirect the applicant to the redirect_url.

curl https://api.casapay.com/v1/verification_sessions \
  -H "Authorization: Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc" \
  -H "Content-Type: application/json" \
  -d '{
    "applicant": {
      "first_name": "Jane",
      "last_name": "Doe",
      "email": "jane.doe@example.com",
      "date_of_birth": "1990-05-15"
    },
    "products": ["identity", "income", "credit", "cash_flow"],
    "redirect_url": "https://your-app.com/verification/complete",
    "metadata": {
      "property_id": "prop_456",
      "unit": "4B"
    }
  }'
{
  "id": "vs_1a2b3c4d5e6f",
  "object": "verification_session",
  "status": "created",
  "client_secret": "vs_secret_abc123...",
  "redirect_url": "https://verify.casapay.com/session/vs_1a2b3c4d5e6f",
  "applicant": {
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane.doe@example.com"
  },
  "products": ["identity", "income", "credit", "cash_flow"],
  "created": 1706140800
}

Step 2: Redirect the Applicant#

Send the applicant to the verification flow. They will connect bank accounts, verify their identity, and authorize data access.

// Client-side: embed the CasaPay verification widget
const session = await fetch('/api/create-verification', { method: 'POST' });
const { client_secret } = await session.json();

const casapayVerify = CasaPay.Verify(client_secret);
casapayVerify.open();

Step 3: Handle the Webhook#

When the verification completes, CasaPay sends a verification_session.completed webhook. Retrieve the full report:

curl https://api.casapay.com/v1/verification_reports/vr_9z8y7x6w5v \
  -H "Authorization: Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc"
{
  "id": "vr_9z8y7x6w5v",
  "object": "verification_report",
  "session": "vs_1a2b3c4d5e6f",
  "status": "completed",
  "identity": {
    "verified": true,
    "full_name": "Jane Marie Doe",
    "date_of_birth": "1990-05-15",
    "selfie_match": 0.98
  },
  "income": {
    "annual_gross": 7200000,
    "annual_net": 5400000,
    "pay_frequency": "monthly",
    "sources": [
      { "type": "employment", "employer": "Acme Corp", "amount": 600000 }
    ]
  },
  "credit_data": {
    "bureau_scores": [
      { "bureau": "experian", "score": 742, "date": "2025-01-10" }
    ]
  },
  "cash_flow": {
    "scores": [
      { "type": "cash_flow_score", "value": 78, "risk_indicator": "low_risk" }
    ]
  }
}

Step 4: Make a Decision#

Use the verification data to approve or decline the tenant:

app.post('/webhooks/casapay', async (req, res) => {
  const event = req.body;

  if (event.type === 'verification_session.completed') {
    const report = await casapay.verificationReports.retrieve(
      event.data.object.report
    );

    const approved =
      report.identity.verified &&
      report.income.annual_gross >= 3 * annualRent &&
      report.credit_data.bureau_scores[0].score >= 650;

    await updateApplicationStatus(report.session, approved);
  }

  res.status(200).send();
});

That's it!

You've created a complete tenant verification flow. Explore the full API reference to customize verification products, upload documents, and handle edge cases.