Skip to main content

Webhooks

IdCanopy sends real-time updates about customer journeys to your webhook endpoint. This page covers how delivery works (configuration, security, retries) and the payload schema you’ll receive.

Configure

  • Webhook URL — Your HTTPS endpoint that accepts POST.
  • Events — Choose which journey events you want (e.g., journey completed, fraud alert).
  • Secret — We sign each request body with a shared secret so you can verify integrity.

Endpoint requirements

  • TLS: 1.2+
  • HTTP: POST
  • Body: application/json (default) or text/plain when an encrypted payload is used
  • Timeout/Response: Return HTTP 2xx within 10 seconds

Delivery & retries

If we don’t receive 2xx (or your endpoint times out), we retry for ~24 hours:
  • Up to 6 additional attempts
  • Increasing backoff (≈10s, 100s, 1000s, 10000s)

Security

We add a Signature header containing an HMAC-SHA256 of the raw request body, keyed with your Webhook Secret.
User-Agent: signteq.io API.
Use a constant-time comparison to prevent timing attacks.

Verify (PHP example)

<?php
$raw = file_get_contents('php://input');
$signature = $_SERVER['HTTP_SIGNATURE'] ?? '';
$secret = 'YOUR_WEBHOOK_SECRET';

$expected = hash_hmac('sha256', $raw, $secret);

if (!hash_equals($expected, $signature)) {
  http_response_code(401);
  exit('invalid signature');
}

http_response_code(200);

Testing

  • Use webhook.site to inspect incoming requests.
  • Use ngrok (or similar) to forward callbacks to a local environment.

Example payload

{
  "transactionId": "e5c81c78-272b-4307-9197-3ace19109fd3",
  "customerId": "g5481c79-ag2b-5313-9z95-3ape19779fuc",
  "timestamp": "2024-06-13T16:49:00+02:00",
  "status": "complete",
  "success": "PASS",
  "generalTransactionData": {
    "timestamp": "2022-02-14T10:04:32+01:00",
    "status": "complete",
    "success": "PASS"
  },
  "journeySummary": {
    "journeyStats": {
      "completedSteps": "2",
      "startTime": "2022-02-14T10:04:32+01:00",
      "endTime": "2022-02-14T10:06:38+01:00"
    },
    "identitySubject": {
      "type": "person",
      "fullName": "John Doe",
      "nameStructure": { "firstName": "John", "lastName": "Doe" },
      "gender": "M",
      "nationality": "AT",
      "dob": "1981/12/24",
      "mobileNumber": "+4312345678"
    },
    "authoritativeData": [
      {
        "type": "driversLicense",
        "idNumber": "1234567",
        "issuingDate": "2015/06/18",
        "expirationDate": "2030/06/17",
        "expeditor": "LPD Wien/VA",
        "issuingCountry": "AT"
      }
    ],
    "proofOfWork": [
      { "type": "image", "title": "selfie", "contentOfProof": "https://...", "timestampOfProof": "2024-06-13T16:49:00+02:00", "workstepVerificationSource": "camera" },
      { "type": "image", "title": "document_front", "contentOfProof": "https://...", "timestampOfProof": "2024-06-13T16:49:00+02:00", "workstepVerificationSource": "camera" }
    ],
    "steps": [ /* ... */ ],
    "fraudAlerts": [ /* ... */ ],
    "auditTrail": [ /* ... */ ],
    "journeyDocumentation": { /* ... */ }
  },
  "passThroughData": { /* ... */ }
}

Payload reference

FieldTypeDescription
transactionIdstringJourney identifier (treat as sensitive; use for correlation).
customerIdstringYour customer identifier.
timestampstring (ISO 8601)Event timestamp.
statusstringTechnical state, e.g. complete, processing, aborted, closed, error.
successstringBusiness outcome, e.g. PASS, DECLINE, REVIEW, FLAG.
generalTransactionDataobjectSummary block for the overall journey.
generalTransactionData.timestampstring (ISO 8601)Journey timestamp in the summary.
generalTransactionData.statusstringTechnical state in the summary.
generalTransactionData.successstringBusiness outcome in the summary.
journeySummaryobjectAggregated results and artifacts for the journey.
journeySummary.journeyStatsobjectHigh-level timings and counts.
journeyStats.completedStepsinteger *Number of completed steps (sample shows string "2"; recommended as integer).
journeyStats.startTimestring (ISO 8601)Journey start time.
journeyStats.endTimestring (ISO 8601)Journey end time.
journeySummary.identitySubjectobjectSubject details (person/company/government).
identitySubject.typestringSubject type, e.g. person.
identitySubject.fullNamestringFull name.
identitySubject.nameStructureobjectStructured name breakdown.
nameStructure.firstNamestringGiven name.
nameStructure.lastNamestringFamily name.
identitySubject.genderstringM, F, D (as applicable).
identitySubject.nationalitystringISO 3166-1 alpha-2 nationality (e.g., AT).
identitySubject.dobstring (date)Date of birth (format YYYY/MM/DD).
identitySubject.mobileNumberstringPhone number (e.g., E.164 format).
journeySummary.authoritativeDataarrayIdentity document data extracted/verified.
authoritativeData[].typestringDocument type (e.g., drivers_license, passport).
authoritativeData[].idNumberstringDocument number.
authoritativeData[].issuingDatestring (date)Issue date (e.g., YYYY/MM/DD).
authoritativeData[].expirationDatestring (date)Expiry date (e.g., YYYY/MM/DD).
authoritativeData[].expeditorstringIssuing authority.
authoritativeData[].issuingCountrystringISO country code of issuance (e.g., AT).
journeySummary.proofOfWorkarrayCaptured artifacts (images, excerpts, etc.).
proofOfWork[].typestringArtifact type (e.g., image).
proofOfWork[].titlestringArtifact label (e.g., selfie, documentFront).
proofOfWork[].contentOfProofstring (URL/handle)Secure link or opaque handle to the artifact.
proofOfWork[].workstepVerificationSourcestringSource (e.g., camera).
journeySummary.stepsarrayPer-step breakdown (work status, scores, data).
journeySummary.fraudAlertsarrayFraud events, details, evidence, and scores.
journeySummary.auditTrailarrayChronological work records (start/end/status/result).
journeySummary.journeyDocumentationobjectAdditional documentation for the journey.
passThroughDataobjectYour metadata echoed back (keys/values as provided).
Tips
  • Treat “transactionId” and “artifact” links as sensitive; avoid logging them on the client.
  • Consider adding your own idempotency handling on receipt to avoid double-processing retries.
  • If you consume payloads in multiple systems, keep a small payload changelog in this page to track field additions.