{"envelope":{"id":"string (uuid), stable across retries and replays of the same event","type":"string, one of the event types below","livemode":"boolean, false when the event was produced by test-mode (crd_test_) activity, true otherwise (Stripe convention). Additive: treat a missing field as true.","createdAt":"string (ISO 8601)","data":"object, event-specific, shown per event below"},"signing":"Each delivery carries an HMAC-SHA256 signature over `${timestamp}.${rawBody}`. Verify it with the SDK (constructWebhookEvent / verifyWebhookSignature) using your endpoint's signing secret; verification is constant-time and replay-tolerant.","advisory":"Webhooks are advisory. No event, and no webhook consumer, can change anyone's score.","events":[{"type":"score.updated","description":"A user's Reliability Score changed, or was computed for the first time. Fires whenever the score value moves. Advisory only; receiving this never affects any score.","example":{"user":{"externalId":"seller_88"},"score":72,"band":"Good","previousScore":64,"previousBand":"Fair","confidence":0.9,"totalEvents":18,"verifiedEvents":14,"behavioralQuality":0.86,"formulaVersion":"5.3","computedAt":"2026-07-21T12:00:00.000Z","reason":null}},{"type":"score.band_changed","description":"A user crossed a score-band boundary (e.g. Fair → Good). Same payload as score.updated, but fires only when the band label actually changes.","example":{"user":{"externalId":"seller_88"},"score":72,"band":"Good","previousScore":64,"previousBand":"Fair","confidence":0.9,"totalEvents":18,"verifiedEvents":14,"behavioralQuality":0.86,"formulaVersion":"5.3","computedAt":"2026-07-21T12:00:00.000Z","reason":null}},{"type":"dispute.resolved","description":"A dispute on one of your events reached a terminal outcome, decided deterministically from the record, or resolved in the user's favour after the response window lapsed. Advisory only.","example":{"disputeId":"dsp_5f3a…","eventId":"evt_9c21…","user":{"externalId":"seller_88"},"outcome":"FOR_USER","status":"RESOLVED_FOR_USER","lapsed":false,"resolvedAt":"2026-07-21T12:00:00.000Z"}},{"type":"monitor.triggered","description":"One of your score monitors fired: the user's score crossed a threshold you registered (edge-triggered: down through belowScore, up through aboveScore) or the score band changed. condition tells you which; threshold is null for band_change. Monitors are notification config only; a monitor never reads into or changes a score.","example":{"monitorId":"mon_7a2c…","userId":"seller_88","previousScore":68,"newScore":61,"previousBand":"Good","newBand":"Fair","condition":"below_score","threshold":65,"formulaVersion":"5.3"}},{"type":"policy.threshold_crossed","description":"One of your threshold policies fired: a subject crossed the line you registered (edge-triggered: a score/component/verified-event-count crossing in a direction, or entering/leaving a band). Credda supplies EVIDENCE that the line was crossed: the deterministic score context and a machine-readable decision_input block, for your OWN policy engine. It is never a decision, a rating, or an instruction to act; the decision and the loss belong to you. Notification config only; a policy never reads into or changes a score.","example":{"policyId":"pol_3d1e…","policyName":"deposit-waiver-good-band","subject":{"externalId":"seller_88"},"metric":"band","condition":{"metric":"band","direction":"enter","threshold":null,"component":null,"band":"Good"},"observed":{"previous":"Fair","current":"Good"},"score":72,"previousScore":64,"band":"Good","previousBand":"Fair","reason":{"scoreBefore":64,"scoreAfter":72,"scoreDelta":8,"direction":"up","topDriver":{"factor":"OTR","delta":0.12}},"decision_input":{"subject_external_id":"seller_88","metric":"band","direction":"enter","threshold":null,"component":null,"band":"Good","observed_previous":"Fair","observed_current":"Good","score":72,"previous_score":64,"score_band":"Good","previous_band":"Fair","components":{"reliability":78,"timeliness":71,"trustworthiness":96,"verification":60,"consistency":82,"momentum":55},"verified_events":14,"confidence":0.9,"formula_version":"5.3","computed_at":"2026-07-23T12:00:00.000Z","crossed_at":"2026-07-23T12:00:00.000Z"},"note":"Credda supplies deterministic evidence that a threshold was crossed. It is not an assessment, a rating, or an instruction to act. The decision, and the loss, belong to you.","formulaVersion":"5.3","computedAt":"2026-07-23T12:00:00.000Z"}},{"type":"usage.quota_warning","description":"Your platform's month-to-date API usage crossed the warning share of its monthly quota (default 80%), a heads-up before requests start returning 429 QUOTA_EXCEEDED. Sent at most once per quota period. Only ever fires when a monthly quota cap is configured for your tier.","example":{"used":80000,"cap":100000,"remaining":20000,"ratio":0.8,"threshold":80000,"periodEnd":"2026-08-01T00:00:00.000Z"}},{"type":"import.completed","description":"An async historical import job (POST /api/v1/imports) reached its terminal state: COMPLETED with per-row counts, or FAILED. Lets you stop busy-polling GET /api/v1/imports/{id} for status. Advisory only; an import records events through the normal ingestion path; this notification changes no score.","example":{"importJobId":"imp_4b8f…","status":"COMPLETED","createdCount":942,"skippedCount":12,"failedCount":3,"error":null,"completedAt":"2026-07-24T12:00:00.000Z"}},{"type":"screening.completed","description":"An async bulk screening job (POST /api/v1/screenings) reached its terminal state: COMPLETED with the found count, or FAILED. Lets you stop busy-polling GET /api/v1/screenings/{id} for status; fetch the full results from GET /api/v1/screenings/{id}/results. Advisory only; screening reads scores, it never writes one.","example":{"screeningJobId":"scr_9a1c…","status":"COMPLETED","total":500,"foundCount":473,"error":null,"completedAt":"2026-07-24T12:00:00.000Z"}},{"type":"confirmation.awaiting_response","description":"A confirmation request you created is still PENDING and has gone unanswered past the reminder threshold (CONFIRMATION_REMINDER_AFTER_HOURS, default 48h). Sent at most once per request. Credda delivers nothing to anyone; this tells YOU to re-send the link over the channel you already own, using the one-time token you received at create time (only its hash is stored here, so the payload carries a URL template, never a working link, and never the token). Notification only: a pending request has recorded no event, and none is recorded if it lapses.","example":{"confirmationId":"cnf_6b41a2c9d0e3","stage":"awaiting_response","subject":{"externalId":"tech_88"},"eventType":"CONTRACT_FULFILLED","stakeLevel":"MEDIUM","description":"Confirm the emergency boiler repair on 14 March was completed","counterpartyRef":"client-4471","counterpartyName":"Northgate Dental","campaignId":null,"status":"PENDING","createdAt":"2026-07-20T09:00:00.000Z","expiresAt":"2026-07-27T09:00:00.000Z","ageHours":48,"hoursUntilExpiry":120,"confirmUrlTemplate":"https://api.credda.io/confirm/cnf_6b41a2c9d0e3?token={confirmationToken}","previewUrlTemplate":"https://api.credda.io/api/v1/confirmations/cnf_6b41a2c9d0e3/preview?token={confirmationToken}","note":"Credda delivers nothing to anyone; you hold the channel, and the one-time token you received when this request was created. Only its hash is stored here, so this notification carries a URL template rather than a working link: substitute that token for {confirmationToken}. A request that is still pending has recorded no event, and a request that lapses records none either; an absent confirmation is not evidence of an outcome, in any direction."}},{"type":"confirmation.expiring_soon","description":"A PENDING confirmation request is approaching its expiry (within CONFIRMATION_EXPIRING_WITHIN_HOURS, default 24h), the last window in which the counterparty can still act. Sent at most once per request, independently of confirmation.awaiting_response, so you can subscribe to only this one. Same payload, same rules: no token, no counterparty contact detail, no score, and nothing is written either way.","example":{"confirmationId":"cnf_6b41a2c9d0e3","stage":"expiring_soon","subject":{"externalId":"tech_88"},"eventType":"CONTRACT_FULFILLED","stakeLevel":"MEDIUM","description":"Confirm the emergency boiler repair on 14 March was completed","counterpartyRef":"client-4471","counterpartyName":"Northgate Dental","campaignId":null,"status":"PENDING","createdAt":"2026-07-20T09:00:00.000Z","expiresAt":"2026-07-27T09:00:00.000Z","ageHours":156,"hoursUntilExpiry":12,"confirmUrlTemplate":"https://api.credda.io/confirm/cnf_6b41a2c9d0e3?token={confirmationToken}","previewUrlTemplate":"https://api.credda.io/api/v1/confirmations/cnf_6b41a2c9d0e3/preview?token={confirmationToken}","note":"Credda delivers nothing to anyone; you hold the channel, and the one-time token you received when this request was created. Only its hash is stored here, so this notification carries a URL template rather than a working link: substitute that token for {confirmationToken}. A request that is still pending has recorded no event, and a request that lapses records none either; an absent confirmation is not evidence of an outcome, in any direction."}}],"eventTypes":["score.updated","score.band_changed","dispute.resolved","monitor.triggered","policy.threshold_crossed","usage.quota_warning","import.completed","screening.completed","confirmation.awaiting_response","confirmation.expiring_soon"]}