📄 Marketplace Integration Guide  ·  v1.0 — March 2026  ·  Verity Platform Team

The Opportunity

If you run a marketplace where customers find tradespeople, you have a trust problem you didn't build and a payments problem you don't want to own.

Customers ask: Is this worker reliable? Will they show up? Can I trust them with my home?

Workers ask: Will I actually get paid? Can a customer dispute work I've already done?

Verity solves both — and we can attach directly to your platform without you changing your product or owning any payment risk.

What Verity Is

Verity is a trust and payments layer for informal tradespeople, built on:

  • An append-only financial ledger — every quote, payment and dispute is permanently recorded and cannot be altered
  • A trust score built from real job history — not identity documents
  • A WhatsApp-native interface — workers manage everything from WhatsApp, no app download required
  • A cryptographic evidence chain — every financial event is hashed and anchored publicly

We currently operate in South Africa (ZAR), with workers communicating in English and Afrikaans.

What You Get

Your marketplace getsWorkers getCustomers get
A verified trust badge on worker profiles Inbound quote requests via WhatsApp A trusted, independently-verified score
Automated job lead delivery to workers A permanent record of their work history Evidence-backed payment protection
Payment tracking without owning payment rails Access to more customers Dispute resolution through Verity
A worker vetting signal you didn't have to build No app download required Transparent, explainable transaction history

Flow 1 — Trust Scores on Worker Profiles

When a customer browses your platform and views a worker's profile, display their Verity trust badge alongside your own data.

GET /api/marketplace/workers/{phone}/trust
// Request
GET /api/marketplace/workers/+27821234567/trust
X-Marketplace-Key: your-partner-key

// Response
{
  "verified":             true,
  "trust_tier":           "gold",
  "trust_score":          112,
  "badge":                "✅ Verity Verified — Gold",
  "completed_jobs":       34,
  "dispute_rate_pct":     0,
  "summary":              "Gold tier · 34 jobs · 0% dispute rate",
  "id_verified":          true,
  "business_verified":    false,
  "can_accept_large_jobs": true,
  "member_days":          142
}

Score range: 0–200 (identity score 0–100 + behaviour score 0–100). Phone verification is required before behaviour points count.

Trust Tiers

TierScoreWhat it signals
trusted_pro 150+ 10+ verified jobs, excellent payment record, very low dispute rate
gold 100–149 5+ verified jobs, strong payment record
silver 50–99 Some identity + behaviour history, phone confirmed
bronze 10–49 Phone verified, early history
unregistered — Worker not yet registered — returns trust_tier: "unregistered", trust_score: 0, badge: "Not yet on Verity"
💡
Display recommendation: Show the badge only for silver and above. For unregistered workers, show a "Not yet verified" prompt that links to Verity registration.

Flow 2 — Push Quote Requests to Workers

When a customer selects a worker and requests a quote, push that lead to Verity. The worker gets a WhatsApp notification immediately — whether or not they're currently registered on Verity.

POST /api/marketplace/lead
// Request
POST /api/marketplace/lead
X-Marketplace-Key: your-partner-key
Content-Type: application/json

{
  "worker_phone":        "+27821234567",
  "customer_name":       "Sipho Dlamini",
  "customer_phone":      "+27798765432",
  "job_title":           "Fix leaking geyser",
  "job_description":     "Kitchen geyser dripping — needs washer replacement",
  "marketplace_job_url": "https://yourplatform.co.za/jobs/abc123",
  "external_ref":        "abc123"
}

// Response
{
  "job_id":          "uuid...",
  "worker_notified": true,
  "message":         "Lead created. Worker has been notified via WhatsApp."
}

WhatsApp Message Sent to Worker

WhatsApp — worker notification
📋 New Quote Request via [Your Platform]

Sipho Dlamini is looking for a handyman:
🔧 Fix leaking geyser
"Kitchen geyser dripping — needs washer replacement"

🔗 View full request: https://yourplatform.co.za/jobs/abc123

Reply QUOTE to send them a quote through Verity.
Not registered yet? Reply START — takes 30 seconds.

Important Behaviour

  • If the worker is not registered, the message still delivers. The START prompt recruits them automatically — your leads become a registration funnel.
  • If the worker replies QUOTE, they enter the Verity quoting wizard with customer phone and job title pre-filled.
  • If your platform has a marketplace_job_url, the worker sees it as a tap-through link.
  • Duplicate prevention is automatic — Verity rejects a second lead with the same external_ref from the same partner.

Flow 3 — Daily Job Digest

Push a curated list of available jobs to workers matching a location or trade. Verity delivers a WhatsApp digest (up to 5 jobs) the worker can act on immediately.

POST /api/marketplace/digest
// Request
POST /api/marketplace/digest
X-Marketplace-Key: your-partner-key
Content-Type: application/json

{
  "worker_phone": "+27821234567",
  "jobs": [
    {
      "title":               "Fix leaking tap",
      "location":            "Claremont",
      "estimated_value_zar": 350,
      "customer_name":       "Thabo N.",
      "marketplace_job_url": "https://yourplatform.co.za/jobs/j1"
    },
    {
      "title":               "Paint bedroom ceiling",
      "location":            "Rondebosch",
      "estimated_value_zar": 1200,
      "customer_name":       "Priya K.",
      "marketplace_job_url": "https://yourplatform.co.za/jobs/j2"
    }
  ]
}

WhatsApp Digest Sent to Worker

WhatsApp — job digest
🌅 2 Jobs Near You — [Your Platform]

1️⃣ Fix leaking tap – Claremont – ~R350
   Customer: Thabo N.

2️⃣ Paint bedroom ceiling – Rondebosch – ~R1,200
   Customer: Priya K.

Tap a link to request contact details, or reply QUOTE to send
a quote for any job. Reply LEADS anytime to see fresh opportunities.
🕐
Suggested schedule: 7am + 5pm — aligns with when workers plan their day and review end-of-day opportunities. You control the schedule on your side.

Outbound Webhooks

When a job progresses, Verity fires an event to your registered webhook URL so your platform stays in sync without polling.

Events

EventTriggered when
job.lead_notifiedWorker WhatsApp sent (immediately after POST /lead)
job.acceptedCustomer accepts the worker's Verity quote
job.completedPayment confirmed by both parties — job done and paid
payment.confirmedPayment confirmed and applied to ledger
ℹ️
job.completed and payment.confirmed fire together. They are separate event types so your platform can handle them with different business logic.

Payload Format

All events — shared envelope
POST https://yourplatform.co.za/webhooks/verity
Content-Type:      application/json
X-Verity-Event:    payment.confirmed
X-Verity-Signature: sha256=<hmac-hex>

{
  "event":        "payment.confirmed",
  "job_id":       "uuid...",
  "partner":      "your-slug",
  "timestamp":    "2026-03-28T14:23:00.000Z",
  "external_ref": "abc123"
}

Per-Event Extra Fields

EventExtra fields
job.lead_notifiedworker_phone, worker_notified (bool)
job.acceptednone beyond envelope
job.completedpayment_method — "cash" or "eft"
payment.confirmedpayment_method — "cash" or "eft"

Signature Verification

Every webhook is signed with HMAC-SHA256 using your webhook secret. Always verify before processing.

Node.js — verify signature
import crypto from 'crypto';

function verifyVerityWebhook(rawBody, signatureHeader, webhookSecret) {
  const expected = 'sha256=' +
    crypto.createHmac('sha256', webhookSecret)
          .update(rawBody)   // raw bytes — do NOT parse JSON first
          .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signatureHeader),
    Buffer.from(expected)
  );
}

// Express
app.post('/webhooks/verity', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-verity-signature'];
  if (!verifyVerityWebhook(req.body, sig, process.env.VERITY_WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  const event = JSON.parse(req.body);
  // handle event...
  res.sendStatus(200);
});
⚠️
Single delivery — no retries. Respond with HTTP 2xx within 10 seconds or the delivery is logged as failed. Build idempotency around job_id + event if you need replay.

How the Trust Score Is Built

Unlike identity-only verification (ID document, selfie), the Verity trust score is built from real transaction history. A worker earns score by doing jobs and getting paid — not by uploading documents.

Two Components — 100 Points Each (Total 0–200)

Identity component (0–100): Phone verification, ID document, business registration, and account age. Unlocks the behaviour component — behaviour points don't count until a phone is verified.

Behaviour component (0–100): Earned from real job history:

Behaviour signalPointsWhat it measures
Completion Reliability40Jobs completed vs started
Payment Integrity25Payments confirmed without dispute
Consistency & Volume20Regularity of work activity
Dispute Behaviour15Dispute rate across all payments
🔒
Cannot be faked. A GOLD worker with 30 completed jobs and 0% dispute rate is a signal your star-rating system cannot produce with confidence. The Verity score is derived from an append-only ledger that no one — including Verity — can edit.

Authentication

All API calls use a per-partner API key in the X-Marketplace-Key header. Keys are stored as SHA-256 hashes — the raw key is shown once at registration and never again. To rotate a key, contact the Verity team.

⚠️
Server-side only. The API key must never appear in browser-side JavaScript or be exposed to end users. Make all Verity API calls from your backend. The API does not support CORS.

Rate Limits

All endpoints are limited to 100 requests per minute per partner key. Exceeding this returns 429 Too Many Requests with a Retry-After header.

Response headerMeaning
X-RateLimit-LimitMaximum requests allowed in the window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets
429 error response
{
  "error":      "rate_limit_exceeded",
  "message":    "Too many requests. Limit: 100 per 1m",
  "statusCode": 429
}

Phone Number Format

All phone numbers must be in E.164 format with the + prefix. Numbers without + are rejected. South African numbers use +27 — drop the leading 0:

Format
// Incorrect  082 123 4567   or   0821234567
// Correct    +27821234567

Error Responses

HTTPerror valueMeaning
401unauthorizedMissing or invalid X-Marketplace-Key
400validation_errorRequest body failed schema validation — see details field
409duplicate_external_refA lead with this external_ref already exists for your account
404—Not used for trust score. Unknown phone returns 200 with trust_tier: "unregistered"
429rate_limit_exceededToo many requests — see Retry-After header

Base URLs & Testing

Environments
Production:  https://handyman-ledger.fly.dev
Pilot:        https://handyman-ledger-pilot.fly.dev

Verity will issue a separate test API key pointing to the pilot environment. Note that test leads send real WhatsApp messages — use a phone number you control.

Verify Your Key

GET /api/marketplace/partner
GET /api/marketplace/partner
X-Marketplace-Key: your-test-key

// Expected response
{
  "partner": {
    "id":                  "uuid...",
    "name":                "Your Platform Name",
    "slug":                "your-slug",
    "webhook_configured":  true
  }
}

Endpoints

MethodPathPurpose
GET /api/marketplace/partner Verify your key — returns your partner identity
GET /api/marketplace/workers/{phone}/trust Worker trust score and badge
POST /api/marketplace/lead Push a quote request to a worker
POST /api/marketplace/digest Send a job digest to a worker

Partner Portal

Once approved, log in to the partner portal to monitor your integration. The dashboard shows:

  • Total leads sent and worker notification rate
  • Jobs accepted and completed
  • Webhook delivery success rate
  • A feed of your 20 most recent leads
  • Your API key prefix and webhook configuration status

Your API key prefix (first 8 characters) is visible so you can identify which key is active. The full key is never displayed again after initial provisioning.

🔑
Webhook URLs are set at registration. To update your URL after provisioning, contact the Verity team.

What You Don't Have to Build or Own

ConcernVerity owns itYou own it
Payment processing✅
Dispute resolution✅
Worker identity verification✅
Evidence and audit trail✅
WhatsApp communication with workers✅
Trust score calculation✅
Customer experience on your platform→
Worker discovery and matching→
Job categories and geographic coverage→

Getting Started

1
Apply via the partner portal

Complete the application at verityledger.co.za/marketplace/signup

2
Verity reviews your application

You receive your API key and webhook secret by email within 1 business day.

3
Verify your credentials

GET /api/marketplace/partner should return your partner name.

4
Pilot with 10–20 workers

Test lead delivery, trust badge display, and webhook delivery end-to-end.

5
Review digest results

Tune timing and job selection criteria based on quote conversion rates.

6
Full rollout

Typical time from application to first live lead: 1–3 days. All integration work is on your side — Verity is ready now.

FAQ

Does the worker need to be on Verity before we send a lead?

+

No. Verity delivers the WhatsApp regardless. If they're not registered, the message includes a START prompt. Your leads become a natural registration funnel.

What happens if the worker ignores the lead?

+

The job stays in lead status. You receive the job.lead_notified webhook immediately. If there's no further activity, close it on your side after your own timeout. Verity doesn't chase the worker — that's your product decision.

Can we send leads to multiple workers for the same job?

+

Yes — call POST /api/marketplace/lead once per worker with the same job_title but a different worker_phone. Use your own external_ref format to distinguish them (e.g. job-abc123-worker-1, job-abc123-worker-2).

Do customers interact with Verity directly?

+

Only when confirming payment. When a worker records a payment through Verity, the customer receives a confirmation link handled entirely by Verity. Everything else — browsing, booking, reviewing — stays on your platform.

Is the trust score real-time?

+

Yes. GET /api/marketplace/workers/:phone/trust queries the live ledger every time. There is no cache to invalidate.

What if a worker disputes their trust score?

+

The score is derived from an immutable ledger. Every component is explainable: "you have 3 disputed payments out of 30 — that gives you a 10% dispute rate." There is no hidden logic.

Ready to integrate?

Apply for access and get your API key within 1 business day.

Apply for integration access →