POST /v1/capture-verbal
When a consumer gives verbal consent during a call, submit the audio segment and transcript to this endpoint. eConsent’s classifier analyzes the transcript for affirmative consent, coercion, and sentiment, then generates a signed consent record if the consent meets the TCPA standard.
This endpoint bills 1 verbal capture unit per request.
Request
Section titled “Request”POST https://voice.econsent.org/v1/capture-verbalAuthorization: Bearer ec_voice_YOUR_KEYContent-Type: application/json{ "call_id": "call_xyz789", "phone": "+15551234567", "calling_entity": "Acme Insurance LLC", "captured_at": "2026-04-10T15:42:33Z", "audio_segment_url": "https://storage.yourplatform.com/segments/consent.wav", "transcript": "Yes I authorize Acme Insurance to call and text me about insurance quotes using AI assistants", "agent_disclosure_text": "Do you authorize Acme Insurance to contact you using AI assistants for quote follow-ups?", "consent_scope": ["ai_voice", "ai_sms", "telemarketing"], "language": "en-US"}| Field | Type | Required | Description |
|---|---|---|---|
call_id | string | No | Your internal call identifier |
phone | string | Yes | Consumer phone in E.164 |
calling_entity | string | Yes | Legal entity name |
captured_at | string | No | ISO 8601 timestamp (defaults to now) |
audio_segment_url | string | Yes | URL to the audio segment (eConsent fetches and stores the SHA-256 hash) |
transcript | string | Yes | Text transcript of what the consumer said |
agent_disclosure_text | string | No | What the agent said before the consent prompt |
consent_scope | array | Yes | Scopes: ai_voice, ai_sms, telemarketing, transactional |
language | string | No | BCP 47 code, defaults to en-US |
Response: Valid
Section titled “Response: Valid”{ "consent_id": "cst_lx8ka1b2c3d4e5f6", "signature": "9c2f3a8b4d5e6f7a8b9c0d1e2f3a4b5c...", "evidence_url": "https://verify.econsent.org/c/cst_lx8ka1b2c3d4e5f6", "audio_attestation": { "stored": true, "sha256": "e3b0c44298fc1c149afbf4c8996fb924..." }, "valid": true, "classifier_result": { "verdict": "accept_consent", "affirmative_consent_score": 1.0, "coercion_score": 0.0, "sentiment": "positive", "backend": "rules" }, "warnings": []}Response: Rejected
Section titled “Response: Rejected”{ "consent_id": null, "valid": false, "rejected_reason": "consent_phrase_too_weak_or_coerced", "classifier_result": { "verdict": "no_signal", "affirmative_consent_score": 0.2, "coercion_score": 0.95, "sentiment": "negative", "backend": "rules" }, "warnings": [ "Classifier verdict: no_signal", "High coercion score detected", "Affirmative score: 0.20" ]}Classifier Verdicts
Section titled “Classifier Verdicts”| Verdict | Meaning | Action |
|---|---|---|
accept_consent | Strong, genuine affirmative consent | Consent record created and signed |
review_consent | Affirmative phrase detected but flagged (coercion, negative sentiment) | Consent NOT created. Re-prompt the consumer with clearer language. |
accept_revocation | Consumer expressed an opt-out | Consent NOT created. Call POST /v1/revoke instead. |
no_signal | No consent or opt-out phrase detected | Consent NOT created. The transcript did not contain a recognizable consent phrase. |
ambiguous | Conflicting signals | Consent NOT created. Needs human review. |
Code Examples
Section titled “Code Examples”const result = await voice.captureVerbal({ callId: 'call_xyz', phone: '+15551234567', callingEntity: 'Acme Insurance LLC', audioSegmentUrl: 's3://bucket/segment.wav', transcript: 'Yes I authorize Acme to call me about insurance', agentDisclosureText: 'Do you authorize Acme to contact you?', consentScope: ['ai_voice'],});
if (result.valid) { console.log(`Consent captured: ${result.evidenceUrl}`);} else { console.log(`Rejected: ${result.rejectedReason}`);}result = voice.capture_verbal( phone="+15551234567", calling_entity="Acme Insurance LLC", audio_segment_url="s3://bucket/segment.wav", transcript="Yes I authorize Acme to call me about insurance", agent_disclosure_text="Do you authorize Acme to contact you?", consent_scope=["ai_voice"],)
if result.valid: print(f"Consent captured: {result.evidence_url}")else: print(f"Rejected: {result.rejected_reason}")