lcp-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3230 @@
1
+ {
2
+ "schemas/ack.json": {
3
+ "$id": "https://lcp.dev/schemas/ack.json",
4
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
5
+ "additionalProperties": false,
6
+ "description": "Response to any message. Uses errors[] array \u2014 a single message can fail multiple field validations. Created by Spear Systems (a Spear company). Open standard \u2014 Apache 2.0, free to implement.",
7
+ "properties": {
8
+ "errors": {
9
+ "description": "Zero or more error objects. Present when status = ERROR or REJECTED.",
10
+ "items": {
11
+ "$ref": "core.json#/$defs/error"
12
+ },
13
+ "type": "array"
14
+ },
15
+ "lead_id": {
16
+ "description": "Assigned lead ID, if applicable.",
17
+ "type": "string"
18
+ },
19
+ "original_message_id": {
20
+ "description": "ID of the message being acknowledged.",
21
+ "format": "uuid",
22
+ "type": "string"
23
+ },
24
+ "rejection_reason": {
25
+ "$comment": "Open enum \u2014 enables publisher automation (route invalid_phone to retry, duplicate to dedup, etc.)",
26
+ "description": "Structured rejection reason when status = REJECTED. Known values: invalid_phone, invalid_email, duplicate, out_of_geography, out_of_scope, credit_too_low, already_customer, data_quality_fail, compliance_fail, price_too_high, capacity_exceeded, consent_expired, litigator_flagged. Open enumeration.",
27
+ "type": "string"
28
+ },
29
+ "request_id": {
30
+ "description": "Server-side request ID for tracing.",
31
+ "type": "string"
32
+ },
33
+ "status": {
34
+ "enum": [
35
+ "RECEIVED",
36
+ "VALIDATED",
37
+ "ACCEPTED",
38
+ "REJECTED",
39
+ "DUPLICATE",
40
+ "ERROR"
41
+ ],
42
+ "type": "string"
43
+ }
44
+ },
45
+ "required": [
46
+ "original_message_id",
47
+ "status"
48
+ ],
49
+ "title": "LCP Ack Message",
50
+ "type": "object"
51
+ },
52
+ "schemas/bid.json": {
53
+ "$id": "https://lcp.dev/schemas/bid.json",
54
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
55
+ "additionalProperties": false,
56
+ "description": "Buyer's response to a ping. Contains the bid price, accept/reject decision, and estimated contact speed. The platform collects bids from all pinged buyers and selects the winner. Created by Spear Systems (a Spear company). Open standard \u2014 Apache 2.0, free to implement.",
57
+ "properties": {
58
+ "bid_price_cents": {
59
+ "description": "Buyer's bid price in cents. Required when decision = accept. Ignored when decision = reject or pass.",
60
+ "minimum": 0,
61
+ "type": "integer"
62
+ },
63
+ "buyer_reference": {
64
+ "description": "Buyer's internal reference for this bid (for tracking).",
65
+ "type": "string"
66
+ },
67
+ "capacity_remaining": {
68
+ "description": "Buyer's remaining capacity after this bid. Helps the platform route future pings. Optional.",
69
+ "minimum": 0,
70
+ "type": "integer"
71
+ },
72
+ "currency": {
73
+ "$ref": "core.json#/$defs/currency"
74
+ },
75
+ "decision": {
76
+ "description": "accept = buyer wants the lead at bid_price_cents; reject = buyer does not want this lead; pass = buyer declines to bid (no reason).",
77
+ "enum": [
78
+ "accept",
79
+ "reject",
80
+ "pass"
81
+ ],
82
+ "type": "string"
83
+ },
84
+ "estimated_contact_seconds": {
85
+ "description": "Buyer's estimated time-to-contact in seconds. Used by the platform for speed-to-contact routing. Optional.",
86
+ "minimum": 0,
87
+ "type": "integer"
88
+ },
89
+ "ping_id": {
90
+ "description": "ID of the ping being responded to.",
91
+ "type": "string"
92
+ },
93
+ "reject_reason": {
94
+ "description": "Why the buyer rejected (e.g. out_of_hours, capacity_full, vertical_mismatch, price_too_low). Open enumeration. Optional.",
95
+ "type": "string"
96
+ }
97
+ },
98
+ "required": [
99
+ "ping_id",
100
+ "decision",
101
+ "bid_price_cents",
102
+ "currency"
103
+ ],
104
+ "title": "LCP Bid Message",
105
+ "type": "object"
106
+ },
107
+ "schemas/call.json": {
108
+ "$id": "https://lcp.dev/schemas/call.json",
109
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
110
+ "additionalProperties": false,
111
+ "description": "Telephony lead message. Structurally distinct from form-based lead \u2014 carries call-specific blocks (IVR, durations, recording, disposition). Created by Spear Systems (a Spear company). Open standard \u2014 Apache 2.0, free to implement.",
112
+ "properties": {
113
+ "attachments": {
114
+ "$ref": "core.json#/$defs/attachments"
115
+ },
116
+ "attributes": {
117
+ "$ref": "core.json#/$defs/attributes"
118
+ },
119
+ "call": {
120
+ "additionalProperties": false,
121
+ "properties": {
122
+ "agent": {
123
+ "additionalProperties": false,
124
+ "properties": {
125
+ "id": {
126
+ "type": "string"
127
+ },
128
+ "name": {
129
+ "type": "string"
130
+ }
131
+ },
132
+ "type": "object"
133
+ },
134
+ "call_id": {
135
+ "description": "Unique call identifier.",
136
+ "type": "string"
137
+ },
138
+ "caller_phone_hash": {
139
+ "pattern": "^[a-f0-9]{64}$",
140
+ "type": "string"
141
+ },
142
+ "did": {
143
+ "description": "Dialed number (Direct Inward Dial) \u2014 the tracking number the consumer called.",
144
+ "type": "string"
145
+ },
146
+ "direction": {
147
+ "enum": [
148
+ "inbound",
149
+ "outbound"
150
+ ],
151
+ "type": "string"
152
+ },
153
+ "disposition": {
154
+ "type": "string"
155
+ },
156
+ "durations": {
157
+ "additionalProperties": false,
158
+ "properties": {
159
+ "agent_seconds": {
160
+ "minimum": 0,
161
+ "type": "integer"
162
+ },
163
+ "hold_seconds": {
164
+ "minimum": 0,
165
+ "type": "integer"
166
+ },
167
+ "ivr_seconds": {
168
+ "minimum": 0,
169
+ "type": "integer"
170
+ },
171
+ "total_seconds": {
172
+ "minimum": 0,
173
+ "type": "integer"
174
+ }
175
+ },
176
+ "type": "object"
177
+ },
178
+ "forwarded_to": {
179
+ "description": "Number the call was forwarded to (buyer's destination number). E.164.",
180
+ "type": "string"
181
+ },
182
+ "hangup_cause": {
183
+ "type": "string"
184
+ },
185
+ "ivr": {
186
+ "additionalProperties": true,
187
+ "description": "IVR menu interaction data. Core fields are universal; platform-specific IVR data goes in extensions.",
188
+ "properties": {
189
+ "abandoned": {
190
+ "description": "True if the caller dropped during IVR before reaching an agent.",
191
+ "type": "boolean"
192
+ },
193
+ "digits": {
194
+ "description": "DTMF digits pressed during IVR.",
195
+ "type": "string"
196
+ },
197
+ "language": {
198
+ "description": "IVR language selected (BCP-47 tag, e.g. 'en-AU', 'es-US').",
199
+ "type": "string"
200
+ },
201
+ "menu_options_selected": {
202
+ "description": "Ordered list of menu option labels selected.",
203
+ "items": {
204
+ "type": "string"
205
+ },
206
+ "type": "array"
207
+ },
208
+ "path": {
209
+ "description": "IVR menu path taken (e.g. 'sales > mortgage > refinance').",
210
+ "type": "string"
211
+ }
212
+ },
213
+ "type": "object"
214
+ },
215
+ "queue": {
216
+ "additionalProperties": false,
217
+ "description": "Call queue that handled this call.",
218
+ "properties": {
219
+ "id": {
220
+ "type": "string"
221
+ },
222
+ "name": {
223
+ "type": "string"
224
+ }
225
+ },
226
+ "type": "object"
227
+ },
228
+ "recording": {
229
+ "additionalProperties": false,
230
+ "properties": {
231
+ "storage_ref": {
232
+ "type": "string"
233
+ },
234
+ "transcript_url": {
235
+ "format": "uri",
236
+ "type": "string"
237
+ },
238
+ "url": {
239
+ "format": "uri",
240
+ "type": "string"
241
+ }
242
+ },
243
+ "type": "object"
244
+ },
245
+ "started_at": {
246
+ "format": "date-time",
247
+ "type": "string"
248
+ },
249
+ "status": {
250
+ "$comment": "Open enumeration per SPEC.md \u00a76.",
251
+ "description": "OPEN ENUMERATION \u2014 known values: answered, no_answer, busy, failed, voicemail. Unknown values MUST be stored and passed through.",
252
+ "type": "string"
253
+ },
254
+ "tracking_number": {
255
+ "description": "Tracking/marketing number assigned to this campaign (may differ from DID if call was routed through a tracking pool). E.164.",
256
+ "type": "string"
257
+ },
258
+ "transferred_from": {
259
+ "additionalProperties": false,
260
+ "description": "Present if this call was transferred from another call/queue.",
261
+ "properties": {
262
+ "original_call_id": {
263
+ "type": "string"
264
+ },
265
+ "transfer_reason": {
266
+ "type": "string"
267
+ }
268
+ },
269
+ "type": "object"
270
+ }
271
+ },
272
+ "required": [
273
+ "call_id",
274
+ "status",
275
+ "started_at"
276
+ ],
277
+ "title": "Call Detail Block",
278
+ "type": "object"
279
+ },
280
+ "channel": {
281
+ "const": "call",
282
+ "description": "Always 'call' for call messages.",
283
+ "type": "string"
284
+ },
285
+ "compliance": {
286
+ "$ref": "core.json#/$defs/compliance"
287
+ },
288
+ "consumer": {
289
+ "$ref": "core.json#/$defs/consumer"
290
+ },
291
+ "exclusivity": {
292
+ "$ref": "core.json#/$defs/exclusivity"
293
+ },
294
+ "expiry": {
295
+ "$ref": "core.json#/$defs/expiry"
296
+ },
297
+ "external_id": {
298
+ "type": "string"
299
+ },
300
+ "lead_id": {
301
+ "type": "string"
302
+ },
303
+ "location": {
304
+ "$ref": "core.json#/$defs/location"
305
+ },
306
+ "provenance": {
307
+ "$ref": "core.json#/$defs/provenance"
308
+ },
309
+ "status": {
310
+ "$ref": "core.json#/$defs/status"
311
+ },
312
+ "submitted_at": {
313
+ "description": "When the call was initiated (distinct from provenance.received_at).",
314
+ "format": "date-time",
315
+ "type": "string"
316
+ }
317
+ },
318
+ "required": [
319
+ "lead_id",
320
+ "status",
321
+ "channel",
322
+ "consumer",
323
+ "location",
324
+ "call"
325
+ ],
326
+ "title": "LCP Call Message",
327
+ "type": "object"
328
+ },
329
+ "schemas/core.json": {
330
+ "$defs": {
331
+ "attachments": {
332
+ "description": "Metadata for encrypted, out-of-band files. Binary content is never embedded in an LCP JSON envelope.",
333
+ "items": {
334
+ "additionalProperties": false,
335
+ "properties": {
336
+ "attachment_id": {
337
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$",
338
+ "type": "string"
339
+ },
340
+ "content_type": {
341
+ "pattern": "^[^;\\s]+/[^;\\s]+$",
342
+ "type": "string"
343
+ },
344
+ "created_at": {
345
+ "format": "date-time",
346
+ "type": "string"
347
+ },
348
+ "encryption": {
349
+ "enum": [
350
+ "application_encrypted",
351
+ "provider_encrypted"
352
+ ],
353
+ "type": "string"
354
+ },
355
+ "expires_at": {
356
+ "format": "date-time",
357
+ "type": "string"
358
+ },
359
+ "filename": {
360
+ "maxLength": 255,
361
+ "minLength": 1,
362
+ "pattern": "^[^/\\\\]+$",
363
+ "type": "string"
364
+ },
365
+ "malware_scan": {
366
+ "additionalProperties": false,
367
+ "description": "Non-sensitive malware scan evidence. A production attachment must have status clean before release.",
368
+ "properties": {
369
+ "engine": {
370
+ "maxLength": 100,
371
+ "minLength": 1,
372
+ "type": "string"
373
+ },
374
+ "scanned_at": {
375
+ "format": "date-time",
376
+ "type": "string"
377
+ },
378
+ "status": {
379
+ "enum": [
380
+ "clean",
381
+ "not_scanned"
382
+ ],
383
+ "type": "string"
384
+ }
385
+ },
386
+ "required": [
387
+ "status",
388
+ "engine",
389
+ "scanned_at"
390
+ ],
391
+ "type": "object"
392
+ },
393
+ "purpose": {
394
+ "maxLength": 100,
395
+ "minLength": 1,
396
+ "type": "string"
397
+ },
398
+ "residency": {
399
+ "description": "Country or deployment region where the attachment bytes are stored and scanned.",
400
+ "pattern": "^[A-Z0-9][A-Z0-9._-]{1,31}$",
401
+ "type": "string"
402
+ },
403
+ "sha256": {
404
+ "pattern": "^[a-f0-9]{64}$",
405
+ "type": "string"
406
+ },
407
+ "size_bytes": {
408
+ "maximum": 104857600,
409
+ "minimum": 1,
410
+ "type": "integer"
411
+ },
412
+ "storage_ref": {
413
+ "maxLength": 512,
414
+ "minLength": 1,
415
+ "type": "string"
416
+ }
417
+ },
418
+ "required": [
419
+ "attachment_id",
420
+ "purpose",
421
+ "filename",
422
+ "content_type",
423
+ "size_bytes",
424
+ "sha256",
425
+ "storage_ref",
426
+ "created_at"
427
+ ],
428
+ "type": "object"
429
+ },
430
+ "maxItems": 50,
431
+ "type": "array"
432
+ },
433
+ "attributes": {
434
+ "description": "Vertical-specific fields. Shape defined by per-vertical JSON Schema in verticals/.",
435
+ "properties": {
436
+ "schema_version": {
437
+ "type": "string"
438
+ },
439
+ "vertical": {
440
+ "type": "string"
441
+ }
442
+ },
443
+ "required": [
444
+ "vertical",
445
+ "schema_version"
446
+ ],
447
+ "title": "Attributes",
448
+ "type": "object"
449
+ },
450
+ "channel": {
451
+ "description": "Open enumeration of lead channels.",
452
+ "title": "Lead Channel",
453
+ "type": "string"
454
+ },
455
+ "compliance": {
456
+ "additionalProperties": false,
457
+ "description": "Consent and regulatory compliance evidence.",
458
+ "properties": {
459
+ "call_recording_id": {
460
+ "type": "string"
461
+ },
462
+ "consent_evidence": {
463
+ "items": {
464
+ "$ref": "core.json#/$defs/consent_evidence_entry"
465
+ },
466
+ "type": "array"
467
+ },
468
+ "consent_expires_at": {
469
+ "format": "date-time",
470
+ "type": "string"
471
+ },
472
+ "consent_purposes": {
473
+ "description": "What was consented to (e.g. calls, sms, email, share_with_partners).",
474
+ "items": {
475
+ "type": "string"
476
+ },
477
+ "type": "array"
478
+ },
479
+ "consent_source_url": {
480
+ "format": "uri",
481
+ "type": "string"
482
+ },
483
+ "consent_text_version": {
484
+ "type": "string"
485
+ },
486
+ "consent_timestamp": {
487
+ "format": "date-time",
488
+ "type": "string"
489
+ },
490
+ "dnc_checked": {
491
+ "type": "boolean"
492
+ },
493
+ "otp": {
494
+ "additionalProperties": false,
495
+ "description": "OTP verification details. The actual OTP code MUST NOT be included.",
496
+ "properties": {
497
+ "attempts": {
498
+ "minimum": 1,
499
+ "type": "integer"
500
+ },
501
+ "channel": {
502
+ "enum": [
503
+ "sms",
504
+ "email",
505
+ "voice"
506
+ ],
507
+ "type": "string"
508
+ },
509
+ "verified_at": {
510
+ "format": "date-time",
511
+ "type": "string"
512
+ },
513
+ "verified_value_hash": {
514
+ "type": "string"
515
+ }
516
+ },
517
+ "type": "object"
518
+ },
519
+ "otp_verified": {
520
+ "description": "One-time-passcode verified.",
521
+ "type": "boolean"
522
+ },
523
+ "scrubs": {
524
+ "items": {
525
+ "additionalProperties": false,
526
+ "properties": {
527
+ "checked_at": {
528
+ "format": "date-time",
529
+ "type": "string"
530
+ },
531
+ "details": {
532
+ "type": "string"
533
+ },
534
+ "provider": {
535
+ "type": "string"
536
+ },
537
+ "result": {
538
+ "enum": [
539
+ "clean",
540
+ "flagged",
541
+ "blocked",
542
+ "not_checked"
543
+ ],
544
+ "type": "string"
545
+ },
546
+ "type": {
547
+ "type": "string"
548
+ }
549
+ },
550
+ "required": [
551
+ "type",
552
+ "result"
553
+ ],
554
+ "type": "object"
555
+ },
556
+ "type": "array"
557
+ },
558
+ "session_capture_id": {
559
+ "type": "string"
560
+ }
561
+ },
562
+ "title": "Compliance",
563
+ "type": "object"
564
+ },
565
+ "consent_evidence_entry": {
566
+ "additionalProperties": false,
567
+ "description": "A single piece of consent or compliance evidence.",
568
+ "properties": {
569
+ "provider": {
570
+ "description": "Vendor or system (e.g. jornaya, trustedform, internal).",
571
+ "type": "string"
572
+ },
573
+ "token_or_url": {
574
+ "description": "Verification token, certificate URL, or reference.",
575
+ "type": "string"
576
+ },
577
+ "type": {
578
+ "description": "Consent framework or evidence type (e.g. tcpa_consent, gdpr_opt_in).",
579
+ "type": "string"
580
+ }
581
+ },
582
+ "required": [
583
+ "type",
584
+ "provider",
585
+ "token_or_url"
586
+ ],
587
+ "title": "Consent Evidence Entry",
588
+ "type": "object"
589
+ },
590
+ "consumer": {
591
+ "additionalProperties": false,
592
+ "anyOf": [
593
+ {
594
+ "required": [
595
+ "email"
596
+ ]
597
+ },
598
+ {
599
+ "required": [
600
+ "phone"
601
+ ]
602
+ },
603
+ {
604
+ "required": [
605
+ "first_name",
606
+ "last_name"
607
+ ]
608
+ },
609
+ {
610
+ "required": [
611
+ "full_name"
612
+ ]
613
+ }
614
+ ],
615
+ "description": "The person the lead is about.",
616
+ "properties": {
617
+ "dob": {
618
+ "description": "Sensitive.",
619
+ "format": "date",
620
+ "type": "string"
621
+ },
622
+ "email": {
623
+ "format": "email",
624
+ "type": "string"
625
+ },
626
+ "email_hash": {
627
+ "description": "HMAC-SHA256(shared_secret, normalized_email). For dedup in ping. Same per-pair model as phone_hash.",
628
+ "pattern": "^[a-f0-9]{64}$",
629
+ "type": "string"
630
+ },
631
+ "first_name": {
632
+ "type": "string"
633
+ },
634
+ "full_name": {
635
+ "description": "Unstructured name \u2014 use when Western given/family splitting does not apply.",
636
+ "type": "string"
637
+ },
638
+ "last_name": {
639
+ "type": "string"
640
+ },
641
+ "locale": {
642
+ "description": "BCP-47 language tag (e.g. en-AU, es-US).",
643
+ "pattern": "^[a-z]{2,3}(-[A-Z][a-zA-Z]{1,7})?$",
644
+ "type": "string"
645
+ },
646
+ "phone": {
647
+ "description": "E.164 format.",
648
+ "pattern": "^\\+[1-9]\\d{1,14}$",
649
+ "type": "string"
650
+ },
651
+ "phone_hash": {
652
+ "description": "HMAC-SHA256(shared_secret, e164). 64 hex chars.",
653
+ "pattern": "^[a-f0-9]{64}$",
654
+ "type": "string"
655
+ },
656
+ "preferred_contact_method": {
657
+ "description": "Consumer's preferred contact method. Affects contact strategy and compliance.",
658
+ "enum": [
659
+ "phone",
660
+ "email",
661
+ "sms",
662
+ "any"
663
+ ],
664
+ "type": "string"
665
+ },
666
+ "secondary_phone": {
667
+ "description": "Secondary phone (work, spouse, alternate). E.164. Optional.",
668
+ "pattern": "^\\+[1-9]\\d{1,14}$",
669
+ "type": "string"
670
+ }
671
+ },
672
+ "title": "Consumer",
673
+ "type": "object"
674
+ },
675
+ "currency": {
676
+ "pattern": "^[A-Z]{3}$",
677
+ "type": "string"
678
+ },
679
+ "error": {
680
+ "additionalProperties": false,
681
+ "properties": {
682
+ "code": {
683
+ "pattern": "^LCP-\\d{3}$",
684
+ "type": "string"
685
+ },
686
+ "details": {
687
+ "additionalProperties": true,
688
+ "type": "object"
689
+ },
690
+ "field": {
691
+ "type": "string"
692
+ },
693
+ "message": {
694
+ "type": "string"
695
+ },
696
+ "name": {
697
+ "type": "string"
698
+ }
699
+ },
700
+ "required": [
701
+ "code",
702
+ "message"
703
+ ],
704
+ "type": "object"
705
+ },
706
+ "errors_array": {
707
+ "additionalProperties": false,
708
+ "properties": {
709
+ "errors": {
710
+ "items": {
711
+ "$ref": "core.json#/$defs/error"
712
+ },
713
+ "minItems": 1,
714
+ "type": "array"
715
+ }
716
+ },
717
+ "required": [
718
+ "errors"
719
+ ],
720
+ "type": "object"
721
+ },
722
+ "exclusivity": {
723
+ "additionalProperties": false,
724
+ "properties": {
725
+ "exclusivity": {
726
+ "default": "shared",
727
+ "enum": [
728
+ "exclusive",
729
+ "shared"
730
+ ],
731
+ "type": "string"
732
+ },
733
+ "max_buyers": {
734
+ "minimum": 1,
735
+ "type": "integer"
736
+ }
737
+ },
738
+ "type": "object"
739
+ },
740
+ "expiry": {
741
+ "additionalProperties": false,
742
+ "anyOf": [
743
+ {
744
+ "required": [
745
+ "expires_at"
746
+ ]
747
+ },
748
+ {
749
+ "required": [
750
+ "ttl_seconds"
751
+ ]
752
+ }
753
+ ],
754
+ "properties": {
755
+ "expires_at": {
756
+ "format": "date-time",
757
+ "type": "string"
758
+ },
759
+ "ttl_seconds": {
760
+ "minimum": 1,
761
+ "type": "integer"
762
+ }
763
+ },
764
+ "type": "object"
765
+ },
766
+ "location": {
767
+ "additionalProperties": false,
768
+ "anyOf": [
769
+ {
770
+ "required": [
771
+ "state_region"
772
+ ]
773
+ },
774
+ {
775
+ "required": [
776
+ "postal_code"
777
+ ]
778
+ }
779
+ ],
780
+ "properties": {
781
+ "city": {
782
+ "type": "string"
783
+ },
784
+ "country_code": {
785
+ "description": "ISO 3166-1 alpha-2. Required.",
786
+ "pattern": "^[A-Z]{2}$",
787
+ "type": "string"
788
+ },
789
+ "postal_code": {
790
+ "description": "Per-country format.",
791
+ "type": "string"
792
+ },
793
+ "state_region": {
794
+ "description": "Per-country validation registry (state, province, region).",
795
+ "type": "string"
796
+ },
797
+ "timezone": {
798
+ "description": "IANA timezone (e.g. Australia/Sydney).",
799
+ "type": "string"
800
+ }
801
+ },
802
+ "required": [
803
+ "country_code"
804
+ ],
805
+ "title": "Location",
806
+ "type": "object"
807
+ },
808
+ "provenance": {
809
+ "additionalProperties": false,
810
+ "description": "Non-PII origin metadata.",
811
+ "properties": {
812
+ "acquisition_method": {
813
+ "description": "Open enumeration of acquisition methods.",
814
+ "type": "string"
815
+ },
816
+ "agent": {
817
+ "additionalProperties": false,
818
+ "properties": {
819
+ "acting_for": {
820
+ "type": "string"
821
+ },
822
+ "agent_id": {
823
+ "type": "string"
824
+ },
825
+ "attestation": {
826
+ "type": "string"
827
+ }
828
+ },
829
+ "required": [
830
+ "agent_id",
831
+ "acting_for",
832
+ "attestation"
833
+ ],
834
+ "type": "object"
835
+ },
836
+ "brand_id": {
837
+ "description": "Publisher-owned brand identifier.",
838
+ "type": "string"
839
+ },
840
+ "campaign_id": {
841
+ "type": "string"
842
+ },
843
+ "creative_id": {
844
+ "type": "string"
845
+ },
846
+ "flow_key": {
847
+ "type": "string"
848
+ },
849
+ "form_id": {
850
+ "description": "Stable form or flow identifier.",
851
+ "type": "string"
852
+ },
853
+ "funnel_key": {
854
+ "type": "string"
855
+ },
856
+ "incentive_type": {
857
+ "type": "string"
858
+ },
859
+ "ip_hash": {
860
+ "type": "string"
861
+ },
862
+ "is_incentivized": {
863
+ "type": "boolean"
864
+ },
865
+ "landing_page_url": {
866
+ "format": "uri",
867
+ "type": "string"
868
+ },
869
+ "platform_source": {
870
+ "type": "string"
871
+ },
872
+ "received_at": {
873
+ "format": "date-time",
874
+ "type": "string"
875
+ },
876
+ "source_id": {
877
+ "type": "string"
878
+ },
879
+ "source_type": {
880
+ "description": "Open enumeration of source types.",
881
+ "type": "string"
882
+ },
883
+ "source_url": {
884
+ "format": "uri",
885
+ "type": "string"
886
+ },
887
+ "user_agent_hash": {
888
+ "type": "string"
889
+ }
890
+ },
891
+ "title": "Provenance",
892
+ "type": "object"
893
+ },
894
+ "security": {
895
+ "additionalProperties": false,
896
+ "properties": {
897
+ "algorithm": {
898
+ "const": "HMAC-SHA256",
899
+ "type": "string"
900
+ },
901
+ "signature": {
902
+ "type": "string"
903
+ },
904
+ "timestamp": {
905
+ "format": "date-time",
906
+ "type": "string"
907
+ }
908
+ },
909
+ "required": [
910
+ "signature",
911
+ "timestamp",
912
+ "algorithm"
913
+ ],
914
+ "type": "object"
915
+ },
916
+ "status": {
917
+ "description": "Open enumeration of lifecycle statuses.",
918
+ "title": "Lead Status",
919
+ "type": "string"
920
+ }
921
+ },
922
+ "$id": "https://lcp.dev/schemas/core.json",
923
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
924
+ "description": "Shared definitions for the LCP canonical core. Referenced by message-type and vertical schemas via $ref. Created by Spear Systems (a Spear company). Open standard \u2014 Apache 2.0, free to implement.",
925
+ "title": "LCP Core Definitions",
926
+ "type": "object"
927
+ },
928
+ "schemas/envelope.json": {
929
+ "$id": "https://lcp.dev/schemas/envelope.json",
930
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
931
+ "additionalProperties": false,
932
+ "description": "Top-level LCP wrapper. Transport-agnostic. Payload shape is determined by message.type. Created by Spear Systems (a Spear company). Open standard \u2014 Apache 2.0, free to implement.",
933
+ "properties": {
934
+ "lcp": {
935
+ "additionalProperties": false,
936
+ "properties": {
937
+ "message": {
938
+ "additionalProperties": false,
939
+ "properties": {
940
+ "correlation_id": {
941
+ "description": "Correlates this message with a prior message (e.g. ping \u2192 bid response).",
942
+ "type": [
943
+ "string",
944
+ "null"
945
+ ]
946
+ },
947
+ "id": {
948
+ "description": "Unique message identifier (UUID v4).",
949
+ "format": "uuid",
950
+ "type": "string"
951
+ },
952
+ "idempotency_key": {
953
+ "description": "Idempotency key \u2014 duplicate submissions with the same key return the original result.",
954
+ "type": "string"
955
+ },
956
+ "receiver_id": {
957
+ "description": "Receiver identifier.",
958
+ "type": "string"
959
+ },
960
+ "security": {
961
+ "$ref": "core.json#/$defs/security",
962
+ "description": "Transport-neutral HMAC signature. Optional for HTTP (headers used instead); required for non-HTTP transports."
963
+ },
964
+ "sender_id": {
965
+ "description": "Sender identifier (publisher/platform/buyer).",
966
+ "type": "string"
967
+ },
968
+ "test": {
969
+ "default": false,
970
+ "description": "Test message. Mirrored as X-LCP-Test header in the HTTP binding.",
971
+ "type": "boolean"
972
+ },
973
+ "timestamp": {
974
+ "format": "date-time",
975
+ "type": "string"
976
+ },
977
+ "type": {
978
+ "description": "Message type. Closed enumeration \u2014 unknown types trigger LCP-006.",
979
+ "enum": [
980
+ "lead",
981
+ "call",
982
+ "ping",
983
+ "post",
984
+ "ack",
985
+ "event",
986
+ "bid"
987
+ ],
988
+ "type": "string"
989
+ }
990
+ },
991
+ "required": [
992
+ "id",
993
+ "type",
994
+ "timestamp",
995
+ "sender_id",
996
+ "receiver_id",
997
+ "idempotency_key"
998
+ ],
999
+ "title": "Message Header",
1000
+ "type": "object"
1001
+ },
1002
+ "payload": {
1003
+ "description": "Message payload. Shape determined by message.type \u2014 see message-type schemas (lead.json, call.json, ping.json, post.json, ack.json, event.json)."
1004
+ },
1005
+ "version": {
1006
+ "description": "Protocol semver (e.g. 1.0.0).",
1007
+ "pattern": "^\\d+\\.\\d+\\.\\d+$",
1008
+ "type": "string"
1009
+ }
1010
+ },
1011
+ "required": [
1012
+ "version",
1013
+ "message",
1014
+ "payload"
1015
+ ],
1016
+ "type": "object"
1017
+ }
1018
+ },
1019
+ "required": [
1020
+ "lcp"
1021
+ ],
1022
+ "title": "LCP Envelope",
1023
+ "type": "object"
1024
+ },
1025
+ "schemas/event.json": {
1026
+ "$id": "https://lcp.dev/schemas/event.json",
1027
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
1028
+ "additionalProperties": false,
1029
+ "description": "Lifecycle notification. Events are open enumeration \u2014 receivers must store/pass through unknown values. Created by Spear Systems (a Spear company). Open standard \u2014 Apache 2.0, free to implement.",
1030
+ "properties": {
1031
+ "details": {
1032
+ "additionalProperties": true,
1033
+ "type": "object"
1034
+ },
1035
+ "event": {
1036
+ "$comment": "No enum constraint \u2014 this is an open enumeration per SPEC.md \u00a76. Receivers must accept any string value.",
1037
+ "description": "Lifecycle event. OPEN ENUMERATION \u2014 known values: DELIVERED, ACCEPTED, REJECTED, DISPUTED, REFUNDED, EXPIRED, CONVERTED, ARCHIVED. Unknown values MUST be stored and passed through, not rejected. Adding new values is a MINOR version bump, not breaking.",
1038
+ "type": "string"
1039
+ },
1040
+ "external_reference": {
1041
+ "type": "string"
1042
+ },
1043
+ "lead_id": {
1044
+ "type": "string"
1045
+ },
1046
+ "timestamp": {
1047
+ "format": "date-time",
1048
+ "type": "string"
1049
+ }
1050
+ },
1051
+ "required": [
1052
+ "lead_id",
1053
+ "event",
1054
+ "timestamp"
1055
+ ],
1056
+ "title": "LCP Event Message",
1057
+ "type": "object"
1058
+ },
1059
+ "schemas/lead.json": {
1060
+ "$id": "https://lcp.dev/schemas/lead.json",
1061
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
1062
+ "additionalProperties": false,
1063
+ "description": "Intake message \u2014 form/chat/click/api/agent/referral channel. Created by Spear Systems (a Spear company). Open standard \u2014 Apache 2.0, free to implement.",
1064
+ "properties": {
1065
+ "attachments": {
1066
+ "$ref": "core.json#/$defs/attachments"
1067
+ },
1068
+ "attributes": {
1069
+ "$ref": "core.json#/$defs/attributes"
1070
+ },
1071
+ "channel": {
1072
+ "$ref": "core.json#/$defs/channel"
1073
+ },
1074
+ "compliance": {
1075
+ "$ref": "core.json#/$defs/compliance"
1076
+ },
1077
+ "consumer": {
1078
+ "$ref": "core.json#/$defs/consumer"
1079
+ },
1080
+ "contact_window": {
1081
+ "additionalProperties": false,
1082
+ "description": "Optional. Publisher hint for when the consumer is available to be contacted.",
1083
+ "properties": {
1084
+ "available_from": {
1085
+ "description": "Local time HH:MM format (24h).",
1086
+ "type": "string"
1087
+ },
1088
+ "available_to": {
1089
+ "description": "Local time HH:MM format (24h).",
1090
+ "type": "string"
1091
+ },
1092
+ "days": {
1093
+ "description": "Days of week the consumer is available.",
1094
+ "items": {
1095
+ "enum": [
1096
+ "mon",
1097
+ "tue",
1098
+ "wed",
1099
+ "thu",
1100
+ "fri",
1101
+ "sat",
1102
+ "sun"
1103
+ ],
1104
+ "type": "string"
1105
+ },
1106
+ "type": "array"
1107
+ },
1108
+ "timezone": {
1109
+ "description": "IANA timezone for the window times (e.g. Australia/Sydney).",
1110
+ "type": "string"
1111
+ }
1112
+ },
1113
+ "type": "object"
1114
+ },
1115
+ "exclusivity": {
1116
+ "$ref": "core.json#/$defs/exclusivity"
1117
+ },
1118
+ "expiry": {
1119
+ "$ref": "core.json#/$defs/expiry"
1120
+ },
1121
+ "external_id": {
1122
+ "description": "Publisher's internal lead ID.",
1123
+ "type": "string"
1124
+ },
1125
+ "lead_id": {
1126
+ "type": "string"
1127
+ },
1128
+ "lead_quality": {
1129
+ "additionalProperties": false,
1130
+ "description": "Optional. Publisher-provided quality signals. Buyers use these to filter/route. All fields are publisher-declared and not independently verified by LCP.",
1131
+ "properties": {
1132
+ "data_completeness": {
1133
+ "description": "How complete the lead data is. 'minimal' = name+phone only, 'standard' = core fields, 'rich' = core + vertical attributes fully populated.",
1134
+ "enum": [
1135
+ "minimal",
1136
+ "standard",
1137
+ "rich"
1138
+ ],
1139
+ "type": "string"
1140
+ },
1141
+ "duplicate_risk": {
1142
+ "description": "Publisher's assessment of duplicate risk based on their dedup window.",
1143
+ "enum": [
1144
+ "low",
1145
+ "medium",
1146
+ "high"
1147
+ ],
1148
+ "type": "string"
1149
+ },
1150
+ "spam_risk_score": {
1151
+ "description": "Publisher's spam risk score (0 = clean, 100 = likely spam). Scoring methodology is publisher-defined.",
1152
+ "maximum": 100,
1153
+ "minimum": 0,
1154
+ "type": "integer"
1155
+ },
1156
+ "verification": {
1157
+ "additionalProperties": false,
1158
+ "description": "Details on how phone/email were verified. Supports OTP, enrichment tools, carrier lookup, SMTP validation, etc.",
1159
+ "properties": {
1160
+ "email_method": {
1161
+ "$comment": "Open enum \u2014 new email verification services are additive.",
1162
+ "description": "How the email was verified. Known values: otp, smtp_check, bounce_check, briteverify, zerobounce, kickbox, none. Open enumeration.",
1163
+ "type": "string"
1164
+ },
1165
+ "email_verified_at": {
1166
+ "format": "date-time",
1167
+ "type": "string"
1168
+ },
1169
+ "email_verified_by": {
1170
+ "description": "Provider that performed the verification (e.g. briteverify, zerobounce, internal, publisher_otp).",
1171
+ "type": "string"
1172
+ },
1173
+ "phone_method": {
1174
+ "$comment": "Open enum \u2014 new verification methods (e.g. new enrichment providers) are additive.",
1175
+ "description": "How the phone was verified. Known values: otp, carrier_lookup, call_connect, twilio_lookup, manual_call, none. Open enumeration.",
1176
+ "type": "string"
1177
+ },
1178
+ "phone_verified_at": {
1179
+ "format": "date-time",
1180
+ "type": "string"
1181
+ },
1182
+ "phone_verified_by": {
1183
+ "description": "Provider that performed the verification (e.g. twilio, numverify, internal, publisher_otp).",
1184
+ "type": "string"
1185
+ }
1186
+ },
1187
+ "type": "object"
1188
+ },
1189
+ "verified_email": {
1190
+ "description": "Email was verified (OTP, bounce check, or SMTP validation).",
1191
+ "type": "boolean"
1192
+ },
1193
+ "verified_phone": {
1194
+ "description": "Phone number was verified (OTP, call connect, or carrier lookup).",
1195
+ "type": "boolean"
1196
+ }
1197
+ },
1198
+ "type": "object"
1199
+ },
1200
+ "location": {
1201
+ "$ref": "core.json#/$defs/location"
1202
+ },
1203
+ "provenance": {
1204
+ "$ref": "core.json#/$defs/provenance"
1205
+ },
1206
+ "status": {
1207
+ "$ref": "core.json#/$defs/status"
1208
+ },
1209
+ "submitted_at": {
1210
+ "description": "When the consumer submitted the lead (distinct from provenance.received_at which is when the platform received it).",
1211
+ "format": "date-time",
1212
+ "type": "string"
1213
+ }
1214
+ },
1215
+ "required": [
1216
+ "lead_id",
1217
+ "status",
1218
+ "channel",
1219
+ "consumer",
1220
+ "location",
1221
+ "attributes"
1222
+ ],
1223
+ "title": "LCP Lead Message",
1224
+ "type": "object"
1225
+ },
1226
+ "schemas/offer.json": {
1227
+ "$defs": {
1228
+ "delivery_window": {
1229
+ "additionalProperties": false,
1230
+ "properties": {
1231
+ "available_from": {
1232
+ "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
1233
+ "type": "string"
1234
+ },
1235
+ "available_to": {
1236
+ "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
1237
+ "type": "string"
1238
+ },
1239
+ "channels": {
1240
+ "items": {
1241
+ "type": "string"
1242
+ },
1243
+ "type": "array",
1244
+ "uniqueItems": true
1245
+ },
1246
+ "days": {
1247
+ "items": {
1248
+ "enum": [
1249
+ "mon",
1250
+ "tue",
1251
+ "wed",
1252
+ "thu",
1253
+ "fri",
1254
+ "sat",
1255
+ "sun"
1256
+ ],
1257
+ "type": "string"
1258
+ },
1259
+ "minItems": 1,
1260
+ "type": "array",
1261
+ "uniqueItems": true
1262
+ },
1263
+ "timezone": {
1264
+ "minLength": 1,
1265
+ "type": "string"
1266
+ },
1267
+ "verticals": {
1268
+ "items": {
1269
+ "type": "string"
1270
+ },
1271
+ "type": "array",
1272
+ "uniqueItems": true
1273
+ }
1274
+ },
1275
+ "required": [
1276
+ "timezone",
1277
+ "available_from",
1278
+ "available_to",
1279
+ "days"
1280
+ ],
1281
+ "type": "object"
1282
+ }
1283
+ },
1284
+ "$id": "https://lcp.dev/schemas/offer.json",
1285
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
1286
+ "additionalProperties": false,
1287
+ "description": "A buyer's published acceptance profile for lead routing. Offer administration is deployment-specific; this document is the interoperable discovery shape.",
1288
+ "properties": {
1289
+ "active": {
1290
+ "default": true,
1291
+ "type": "boolean"
1292
+ },
1293
+ "allowed_brand_ids": {
1294
+ "description": "Optional publisher brand allowlist evaluated against provenance.brand_id.",
1295
+ "items": {
1296
+ "minLength": 1,
1297
+ "type": "string"
1298
+ },
1299
+ "type": "array",
1300
+ "uniqueItems": true
1301
+ },
1302
+ "allowed_publisher_ids": {
1303
+ "description": "Optional publisher sender-ID allowlist. Matching fails closed when the incoming publisher is not listed.",
1304
+ "items": {
1305
+ "minLength": 1,
1306
+ "type": "string"
1307
+ },
1308
+ "type": "array",
1309
+ "uniqueItems": true
1310
+ },
1311
+ "attribute_equals": {
1312
+ "additionalProperties": true,
1313
+ "description": "Safe declarative equality predicates keyed by vertical attribute name. Values are data, never executable expressions.",
1314
+ "type": "object"
1315
+ },
1316
+ "attribute_in": {
1317
+ "additionalProperties": {
1318
+ "minItems": 1,
1319
+ "type": "array"
1320
+ },
1321
+ "description": "Safe declarative allowlists keyed by vertical attribute name.",
1322
+ "type": "object"
1323
+ },
1324
+ "buyer_id": {
1325
+ "minLength": 1,
1326
+ "type": "string"
1327
+ },
1328
+ "call_routing_mode": {
1329
+ "default": "post_call",
1330
+ "description": "post_call delivers recorded call metadata; realtime_transfer requires a separate telephony binding for the live bridge.",
1331
+ "enum": [
1332
+ "post_call",
1333
+ "realtime_transfer"
1334
+ ],
1335
+ "type": "string"
1336
+ },
1337
+ "channels": {
1338
+ "items": {
1339
+ "minLength": 1,
1340
+ "type": "string"
1341
+ },
1342
+ "type": "array",
1343
+ "uniqueItems": true
1344
+ },
1345
+ "connect_timeout_seconds": {
1346
+ "description": "Maximum time allowed for a real-time call transfer decision.",
1347
+ "maximum": 60,
1348
+ "minimum": 1,
1349
+ "type": "integer"
1350
+ },
1351
+ "countries": {
1352
+ "items": {
1353
+ "pattern": "^[A-Z]{2}$",
1354
+ "type": "string"
1355
+ },
1356
+ "minItems": 1,
1357
+ "type": "array",
1358
+ "uniqueItems": true
1359
+ },
1360
+ "currency": {
1361
+ "pattern": "^[A-Z]{3}$",
1362
+ "type": "string"
1363
+ },
1364
+ "daily_cap": {
1365
+ "minimum": 1,
1366
+ "type": "integer"
1367
+ },
1368
+ "delivery_windows": {
1369
+ "items": {
1370
+ "$ref": "#/$defs/delivery_window"
1371
+ },
1372
+ "type": "array"
1373
+ },
1374
+ "excluded_acquisition_methods": {
1375
+ "items": {
1376
+ "type": "string"
1377
+ },
1378
+ "type": "array",
1379
+ "uniqueItems": true
1380
+ },
1381
+ "excluded_claim_language": {
1382
+ "items": {
1383
+ "type": "string"
1384
+ },
1385
+ "type": "array",
1386
+ "uniqueItems": true
1387
+ },
1388
+ "excluded_incentive_types": {
1389
+ "items": {
1390
+ "type": "string"
1391
+ },
1392
+ "type": "array",
1393
+ "uniqueItems": true
1394
+ },
1395
+ "excluded_source_types": {
1396
+ "items": {
1397
+ "type": "string"
1398
+ },
1399
+ "type": "array",
1400
+ "uniqueItems": true
1401
+ },
1402
+ "extensions": {
1403
+ "additionalProperties": true,
1404
+ "description": "Namespaced deployment-specific criteria. Matching implementations must not execute arbitrary values as code.",
1405
+ "type": "object"
1406
+ },
1407
+ "floor_price_cents": {
1408
+ "minimum": 0,
1409
+ "type": "integer"
1410
+ },
1411
+ "hourly_cap": {
1412
+ "minimum": 1,
1413
+ "type": "integer"
1414
+ },
1415
+ "max_spam_risk_score": {
1416
+ "maximum": 100,
1417
+ "minimum": 0,
1418
+ "type": "integer"
1419
+ },
1420
+ "min_data_completeness": {
1421
+ "enum": [
1422
+ "minimal",
1423
+ "standard",
1424
+ "rich"
1425
+ ],
1426
+ "type": "string"
1427
+ },
1428
+ "monthly_maximum_payable": {
1429
+ "description": "Optional hard maximum for payable outcomes in a calendar month.",
1430
+ "minimum": 1,
1431
+ "type": "integer"
1432
+ },
1433
+ "monthly_minimum_payable": {
1434
+ "description": "Operational pacing target for payable outcomes in each calendar month. It is not a guarantee of available supply.",
1435
+ "minimum": 0,
1436
+ "type": "integer"
1437
+ },
1438
+ "monthly_quota_policy": {
1439
+ "default": "monitor",
1440
+ "description": "monitor reports progress, pace prioritizes under-target offers, hard_cap stops payable routing at the maximum.",
1441
+ "enum": [
1442
+ "monitor",
1443
+ "pace",
1444
+ "hard_cap"
1445
+ ],
1446
+ "type": "string"
1447
+ },
1448
+ "monthly_quota_timezone": {
1449
+ "description": "IANA timezone used to determine the monthly quota period.",
1450
+ "minLength": 1,
1451
+ "type": "string"
1452
+ },
1453
+ "offer_id": {
1454
+ "minLength": 1,
1455
+ "type": "string"
1456
+ },
1457
+ "payable_definition": {
1458
+ "type": "string"
1459
+ },
1460
+ "payable_rules": {
1461
+ "additionalProperties": false,
1462
+ "description": "Structured, explainable payable evaluation rules.",
1463
+ "properties": {
1464
+ "allowed_call_dispositions": {
1465
+ "items": {
1466
+ "type": "string"
1467
+ },
1468
+ "type": "array",
1469
+ "uniqueItems": true
1470
+ },
1471
+ "exclude_duplicate_resubmissions": {
1472
+ "default": true,
1473
+ "type": "boolean"
1474
+ },
1475
+ "minimum_call_seconds": {
1476
+ "minimum": 0,
1477
+ "type": "integer"
1478
+ },
1479
+ "mode": {
1480
+ "default": "post_delivery",
1481
+ "enum": [
1482
+ "post_delivery",
1483
+ "call_outcome"
1484
+ ],
1485
+ "type": "string"
1486
+ },
1487
+ "require_call_answered": {
1488
+ "type": "boolean"
1489
+ }
1490
+ },
1491
+ "type": "object"
1492
+ },
1493
+ "ping_timeout_seconds": {
1494
+ "default": 30,
1495
+ "minimum": 1,
1496
+ "type": "integer"
1497
+ },
1498
+ "postal_codes": {
1499
+ "items": {
1500
+ "minLength": 1,
1501
+ "type": "string"
1502
+ },
1503
+ "type": "array",
1504
+ "uniqueItems": true
1505
+ },
1506
+ "reject_blacklist_flagged": {
1507
+ "type": "boolean"
1508
+ },
1509
+ "reject_dnc_flagged": {
1510
+ "type": "boolean"
1511
+ },
1512
+ "reject_incentivized": {
1513
+ "type": "boolean"
1514
+ },
1515
+ "reject_litigator_flagged": {
1516
+ "type": "boolean"
1517
+ },
1518
+ "require_consent_evidence": {
1519
+ "type": "boolean"
1520
+ },
1521
+ "require_verified_email": {
1522
+ "type": "boolean"
1523
+ },
1524
+ "require_verified_phone": {
1525
+ "type": "boolean"
1526
+ },
1527
+ "routing_mode": {
1528
+ "default": "auction",
1529
+ "description": "Direct sends a post at the floor price; auction sends a ping and waits for bids.",
1530
+ "enum": [
1531
+ "auction",
1532
+ "direct"
1533
+ ],
1534
+ "type": "string"
1535
+ },
1536
+ "schema_version": {
1537
+ "type": "string"
1538
+ },
1539
+ "state_regions": {
1540
+ "items": {
1541
+ "minLength": 1,
1542
+ "type": "string"
1543
+ },
1544
+ "type": "array",
1545
+ "uniqueItems": true
1546
+ },
1547
+ "tenant_id": {
1548
+ "description": "Owning platform tenant. Deployment metadata; not necessarily exposed in public offer discovery.",
1549
+ "minLength": 1,
1550
+ "type": "string"
1551
+ },
1552
+ "vertical": {
1553
+ "minLength": 1,
1554
+ "type": "string"
1555
+ },
1556
+ "webhook_url": {
1557
+ "format": "uri",
1558
+ "type": "string"
1559
+ }
1560
+ },
1561
+ "required": [
1562
+ "offer_id",
1563
+ "buyer_id",
1564
+ "vertical",
1565
+ "countries",
1566
+ "floor_price_cents",
1567
+ "currency"
1568
+ ],
1569
+ "title": "LCP Buyer Offer",
1570
+ "type": "object"
1571
+ },
1572
+ "schemas/ping.json": {
1573
+ "$id": "https://lcp.dev/schemas/ping.json",
1574
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
1575
+ "additionalProperties": false,
1576
+ "description": "Non-PII offer to buyers. STRICT ALLOWLIST \u2014 additionalProperties: false. No PII fields are permitted. The conformance runner also validates that every field in attributes is tagged ping_safe: true in the vertical schema. Created by Spear Systems (a Spear company). Open standard \u2014 Apache 2.0, free to implement.",
1577
+ "properties": {
1578
+ "attributes": {
1579
+ "additionalProperties": true,
1580
+ "description": "Only fields tagged ping_safe: true in the vertical schema. Banded/aggregated only \u2014 never exact values.",
1581
+ "type": "object"
1582
+ },
1583
+ "compliance_flags": {
1584
+ "additionalProperties": true,
1585
+ "description": "Presence indicators only \u2014 never tokens or evidence.",
1586
+ "properties": {
1587
+ "consent": {
1588
+ "type": "boolean"
1589
+ },
1590
+ "consent_valid": {
1591
+ "description": "True if consent is still within its validity window (not expired).",
1592
+ "type": "boolean"
1593
+ },
1594
+ "dnc_checked": {
1595
+ "type": "boolean"
1596
+ },
1597
+ "otp_verified": {
1598
+ "type": "boolean"
1599
+ }
1600
+ },
1601
+ "type": "object"
1602
+ },
1603
+ "country_code": {
1604
+ "description": "ISO 3166-1 alpha-2.",
1605
+ "pattern": "^[A-Z]{2}$",
1606
+ "type": "string"
1607
+ },
1608
+ "currency": {
1609
+ "$ref": "core.json#/$defs/currency"
1610
+ },
1611
+ "dedup_window_hours": {
1612
+ "description": "Sender hint: how many hours to dedup against. Optional.",
1613
+ "minimum": 1,
1614
+ "type": "integer"
1615
+ },
1616
+ "email_hash": {
1617
+ "description": "HMAC-SHA256(shared_secret, normalized_email) \u2014 per-pair, optional. Optional, for email-based dedup.",
1618
+ "pattern": "^[a-f0-9]{64}$",
1619
+ "type": "string"
1620
+ },
1621
+ "exclusivity": {
1622
+ "description": "Hint to buyer: is this an exclusive or shared lead?",
1623
+ "enum": [
1624
+ "exclusive",
1625
+ "shared"
1626
+ ],
1627
+ "type": "string"
1628
+ },
1629
+ "expires_at": {
1630
+ "format": "date-time",
1631
+ "type": "string"
1632
+ },
1633
+ "floor_price_cents": {
1634
+ "minimum": 0,
1635
+ "type": "integer"
1636
+ },
1637
+ "lead_age_minutes": {
1638
+ "description": "How many minutes since the consumer submitted the lead. Freshness signal for buyer pricing. Non-PII.",
1639
+ "minimum": 0,
1640
+ "type": "integer"
1641
+ },
1642
+ "lead_reference": {
1643
+ "description": "Opaque reference to the lead (not the lead_id).",
1644
+ "type": "string"
1645
+ },
1646
+ "offer_id": {
1647
+ "description": "ID of the buyer offer this ping is being sent against. Enables audit trail for billing and disputes.",
1648
+ "type": "string"
1649
+ },
1650
+ "phone_hash": {
1651
+ "description": "HMAC-SHA256(shared_secret, e164) \u2014 per-pair. See SPEC.md \u00a79.",
1652
+ "pattern": "^[a-f0-9]{64}$",
1653
+ "type": "string"
1654
+ },
1655
+ "ping_id": {
1656
+ "description": "Unique ping identifier.",
1657
+ "type": "string"
1658
+ },
1659
+ "postal_code": {
1660
+ "type": "string"
1661
+ },
1662
+ "publisher_id": {
1663
+ "description": "ID of the publisher that generated the lead. Non-PII \u2014 buyers need this for quality tracking and routing.",
1664
+ "type": "string"
1665
+ },
1666
+ "quality_flags": {
1667
+ "additionalProperties": true,
1668
+ "description": "Non-PII quality signals for buyer filtering. All publisher-declared.",
1669
+ "properties": {
1670
+ "acquisition_method": {
1671
+ "description": "paid_ad, organic_search, marketplace, gmb, cold_outbound, scraped, unknown. Open enum.",
1672
+ "type": "string"
1673
+ },
1674
+ "blacklist_status": {
1675
+ "description": "Blacklist alliance scrub result.",
1676
+ "enum": [
1677
+ "clean",
1678
+ "flagged",
1679
+ "blocked",
1680
+ "not_checked"
1681
+ ],
1682
+ "type": "string"
1683
+ },
1684
+ "dnc_status": {
1685
+ "description": "DNC scrub result.",
1686
+ "enum": [
1687
+ "clean",
1688
+ "flagged",
1689
+ "blocked",
1690
+ "not_checked"
1691
+ ],
1692
+ "type": "string"
1693
+ },
1694
+ "duplicate_risk": {
1695
+ "enum": [
1696
+ "low",
1697
+ "medium",
1698
+ "high"
1699
+ ],
1700
+ "type": "string"
1701
+ },
1702
+ "incentive_type": {
1703
+ "description": "What incentive was offered (e.g. free_consultation, gift_card). Open enum.",
1704
+ "type": "string"
1705
+ },
1706
+ "is_incentivized": {
1707
+ "description": "True if consumer was offered an incentive (free consultation, gift card, etc.).",
1708
+ "type": "boolean"
1709
+ },
1710
+ "litigator_status": {
1711
+ "description": "Litigator scrub result.",
1712
+ "enum": [
1713
+ "clean",
1714
+ "flagged",
1715
+ "blocked",
1716
+ "not_checked"
1717
+ ],
1718
+ "type": "string"
1719
+ },
1720
+ "spam_risk_score": {
1721
+ "maximum": 100,
1722
+ "minimum": 0,
1723
+ "type": "integer"
1724
+ },
1725
+ "verified_email": {
1726
+ "type": "boolean"
1727
+ },
1728
+ "verified_phone": {
1729
+ "type": "boolean"
1730
+ }
1731
+ },
1732
+ "type": "object"
1733
+ },
1734
+ "state_region": {
1735
+ "type": "string"
1736
+ },
1737
+ "vertical": {
1738
+ "description": "Vertical identifier.",
1739
+ "type": "string"
1740
+ }
1741
+ },
1742
+ "required": [
1743
+ "ping_id",
1744
+ "lead_reference",
1745
+ "phone_hash",
1746
+ "country_code",
1747
+ "vertical",
1748
+ "floor_price_cents",
1749
+ "currency"
1750
+ ],
1751
+ "title": "LCP Ping Message",
1752
+ "type": "object"
1753
+ },
1754
+ "schemas/post.json": {
1755
+ "$id": "https://lcp.dev/schemas/post.json",
1756
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
1757
+ "additionalProperties": false,
1758
+ "description": "Full lead delivery to the winning buyer. Contains full PII. Created by Spear Systems (a Spear company). Open standard \u2014 Apache 2.0, free to implement.",
1759
+ "properties": {
1760
+ "attachments": {
1761
+ "$ref": "core.json#/$defs/attachments"
1762
+ },
1763
+ "attributes": {
1764
+ "$ref": "core.json#/$defs/attributes"
1765
+ },
1766
+ "buyer_id": {
1767
+ "type": "string"
1768
+ },
1769
+ "buyer_reference": {
1770
+ "description": "Buyer's internal reference.",
1771
+ "type": "string"
1772
+ },
1773
+ "call": {
1774
+ "additionalProperties": false,
1775
+ "description": "Call detail block copied from a call intake when the post represents a call.",
1776
+ "properties": {
1777
+ "agent": {
1778
+ "additionalProperties": false,
1779
+ "type": "object"
1780
+ },
1781
+ "call_id": {
1782
+ "type": "string"
1783
+ },
1784
+ "caller_phone_hash": {
1785
+ "pattern": "^[a-f0-9]{64}$",
1786
+ "type": "string"
1787
+ },
1788
+ "did": {
1789
+ "type": "string"
1790
+ },
1791
+ "direction": {
1792
+ "enum": [
1793
+ "inbound",
1794
+ "outbound"
1795
+ ],
1796
+ "type": "string"
1797
+ },
1798
+ "disposition": {
1799
+ "type": "string"
1800
+ },
1801
+ "durations": {
1802
+ "additionalProperties": false,
1803
+ "properties": {
1804
+ "agent_seconds": {
1805
+ "minimum": 0,
1806
+ "type": "integer"
1807
+ },
1808
+ "hold_seconds": {
1809
+ "minimum": 0,
1810
+ "type": "integer"
1811
+ },
1812
+ "ivr_seconds": {
1813
+ "minimum": 0,
1814
+ "type": "integer"
1815
+ },
1816
+ "total_seconds": {
1817
+ "minimum": 0,
1818
+ "type": "integer"
1819
+ }
1820
+ },
1821
+ "type": "object"
1822
+ },
1823
+ "forwarded_to": {
1824
+ "type": "string"
1825
+ },
1826
+ "hangup_cause": {
1827
+ "type": "string"
1828
+ },
1829
+ "ivr": {
1830
+ "additionalProperties": true,
1831
+ "type": "object"
1832
+ },
1833
+ "queue": {
1834
+ "additionalProperties": false,
1835
+ "type": "object"
1836
+ },
1837
+ "recording": {
1838
+ "additionalProperties": true,
1839
+ "type": "object"
1840
+ },
1841
+ "started_at": {
1842
+ "format": "date-time",
1843
+ "type": "string"
1844
+ },
1845
+ "status": {
1846
+ "type": "string"
1847
+ },
1848
+ "tracking_number": {
1849
+ "type": "string"
1850
+ },
1851
+ "transferred_from": {
1852
+ "additionalProperties": false,
1853
+ "type": "object"
1854
+ }
1855
+ },
1856
+ "required": [
1857
+ "call_id",
1858
+ "status",
1859
+ "started_at"
1860
+ ],
1861
+ "type": "object"
1862
+ },
1863
+ "compliance": {
1864
+ "$ref": "core.json#/$defs/compliance"
1865
+ },
1866
+ "consumer": {
1867
+ "$ref": "core.json#/$defs/consumer"
1868
+ },
1869
+ "currency": {
1870
+ "$ref": "core.json#/$defs/currency"
1871
+ },
1872
+ "delivered_at": {
1873
+ "format": "date-time",
1874
+ "type": "string"
1875
+ },
1876
+ "exclusivity": {
1877
+ "$ref": "core.json#/$defs/exclusivity"
1878
+ },
1879
+ "lead_id": {
1880
+ "type": "string"
1881
+ },
1882
+ "location": {
1883
+ "$ref": "core.json#/$defs/location"
1884
+ },
1885
+ "matched_preferences": {
1886
+ "additionalProperties": true,
1887
+ "description": "Buyer preferences that matched this lead.",
1888
+ "type": "object"
1889
+ },
1890
+ "offer_id": {
1891
+ "description": "ID of the buyer offer that matched. Audit trail for billing and disputes.",
1892
+ "type": "string"
1893
+ },
1894
+ "price_cents": {
1895
+ "minimum": 0,
1896
+ "type": "integer"
1897
+ },
1898
+ "pricing": {
1899
+ "additionalProperties": false,
1900
+ "properties": {
1901
+ "dispute_window_expires_at": {
1902
+ "description": "When the dispute window closes. Platforms mechanically reject disputes after this timestamp.",
1903
+ "format": "date-time",
1904
+ "type": "string"
1905
+ },
1906
+ "dispute_window_hours": {
1907
+ "description": "Contractually agreed return window in hours. Buyer can dispute within this window.",
1908
+ "minimum": 1,
1909
+ "type": "integer"
1910
+ },
1911
+ "final_price_cents": {
1912
+ "minimum": 0,
1913
+ "type": "integer"
1914
+ },
1915
+ "floor_price_cents": {
1916
+ "minimum": 0,
1917
+ "type": "integer"
1918
+ },
1919
+ "is_duplicate_resub": {
1920
+ "description": "True if this is an accidental resubmission of a previously delivered lead.",
1921
+ "type": "boolean"
1922
+ },
1923
+ "max_allowed_price_cents": {
1924
+ "minimum": 0,
1925
+ "type": "integer"
1926
+ },
1927
+ "payable_definition": {
1928
+ "$comment": "Payable definition is agreed bilaterally between publisher and buyer. This field records which definition applies to this delivery.",
1929
+ "description": "What makes this lead payable (e.g. 'form_lead_valid_phone', 'call_answered_30s', 'connected_transfer', 'exclusive_delivery'). Open enumeration.",
1930
+ "type": "string"
1931
+ },
1932
+ "payable_status": {
1933
+ "description": "Current payable status. 'pending' = within validation window, 'payable' = meets payable definition, 'not_payable' = failed validation, 'disputed' = under review.",
1934
+ "enum": [
1935
+ "pending",
1936
+ "payable",
1937
+ "not_payable",
1938
+ "disputed"
1939
+ ],
1940
+ "type": "string"
1941
+ },
1942
+ "premium_cents": {
1943
+ "minimum": 0,
1944
+ "type": "integer"
1945
+ },
1946
+ "price_guardrails": {
1947
+ "type": "boolean"
1948
+ },
1949
+ "uncapped_price_cents": {
1950
+ "minimum": 0,
1951
+ "type": "integer"
1952
+ }
1953
+ },
1954
+ "type": "object"
1955
+ },
1956
+ "provenance": {
1957
+ "$ref": "core.json#/$defs/provenance"
1958
+ },
1959
+ "submitted_at": {
1960
+ "description": "When the consumer originally submitted the lead. Lets buyer assess lead age.",
1961
+ "format": "date-time",
1962
+ "type": "string"
1963
+ }
1964
+ },
1965
+ "required": [
1966
+ "lead_id",
1967
+ "delivered_at",
1968
+ "price_cents",
1969
+ "currency",
1970
+ "buyer_id",
1971
+ "consumer",
1972
+ "location",
1973
+ "attributes"
1974
+ ],
1975
+ "title": "LCP Post Message",
1976
+ "type": "object"
1977
+ },
1978
+ "verticals/home_services.json": {
1979
+ "$id": "https://lcp.dev/verticals/home_services.json",
1980
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
1981
+ "additionalProperties": false,
1982
+ "description": "Home services lead attributes. Every field is tagged ping_safe: true|false. Publishers normalize brand-specific form questions into this controlled taxonomy; unsupported source questions remain in an approved post-only extension or source archive.",
1983
+ "properties": {
1984
+ "budget_band": {
1985
+ "enum": [
1986
+ "under_500",
1987
+ "500_1000",
1988
+ "1000_5000",
1989
+ "5000_10000",
1990
+ "10000_25000",
1991
+ "over_25000",
1992
+ "unknown"
1993
+ ],
1994
+ "ping_safe": true,
1995
+ "type": "string"
1996
+ },
1997
+ "damage_type": {
1998
+ "enum": [
1999
+ "water",
2000
+ "fire",
2001
+ "storm",
2002
+ "mold",
2003
+ "structural",
2004
+ "pest",
2005
+ "wear_tear",
2006
+ "other",
2007
+ "none"
2008
+ ],
2009
+ "ping_safe": true,
2010
+ "type": "string"
2011
+ },
2012
+ "exact_budget": {
2013
+ "description": "Exact budget is post-only; use budget_band in a ping.",
2014
+ "minimum": 0,
2015
+ "ping_safe": false,
2016
+ "type": "number"
2017
+ },
2018
+ "free_text": {
2019
+ "description": "Free text is post-only because it may contain names, addresses, or sensitive details.",
2020
+ "ping_safe": false,
2021
+ "type": "string"
2022
+ },
2023
+ "has_existing_damage": {
2024
+ "ping_safe": true,
2025
+ "type": "boolean"
2026
+ },
2027
+ "has_insurance_claim": {
2028
+ "ping_safe": true,
2029
+ "type": "boolean"
2030
+ },
2031
+ "material": {
2032
+ "enum": [
2033
+ "aluminum",
2034
+ "copper",
2035
+ "steel",
2036
+ "vinyl",
2037
+ "tile",
2038
+ "metal",
2039
+ "asphalt_shingle",
2040
+ "wood",
2041
+ "concrete",
2042
+ "other",
2043
+ "unknown"
2044
+ ],
2045
+ "ping_safe": true,
2046
+ "type": "string"
2047
+ },
2048
+ "number_of_rooms_band": {
2049
+ "enum": [
2050
+ "under_3",
2051
+ "3_5",
2052
+ "5_7",
2053
+ "7_10",
2054
+ "over_10",
2055
+ "unknown"
2056
+ ],
2057
+ "ping_safe": true,
2058
+ "type": "string"
2059
+ },
2060
+ "occupancy": {
2061
+ "enum": [
2062
+ "owner_occupied",
2063
+ "tenant_occupied",
2064
+ "vacant",
2065
+ "commercial",
2066
+ "unknown"
2067
+ ],
2068
+ "ping_safe": true,
2069
+ "type": "string"
2070
+ },
2071
+ "preferred_schedule": {
2072
+ "enum": [
2073
+ "asap",
2074
+ "within_week",
2075
+ "within_month",
2076
+ "flexible",
2077
+ "specific_date"
2078
+ ],
2079
+ "ping_safe": true,
2080
+ "type": "string"
2081
+ },
2082
+ "project_type": {
2083
+ "description": "Legacy-compatible project classification.",
2084
+ "enum": [
2085
+ "repair",
2086
+ "install",
2087
+ "maintenance",
2088
+ "replacement",
2089
+ "inspection",
2090
+ "cleaning",
2091
+ "removal",
2092
+ "other"
2093
+ ],
2094
+ "ping_safe": true,
2095
+ "type": "string"
2096
+ },
2097
+ "property_age_band": {
2098
+ "enum": [
2099
+ "under_5",
2100
+ "5_15",
2101
+ "15_30",
2102
+ "30_50",
2103
+ "over_50",
2104
+ "unknown"
2105
+ ],
2106
+ "ping_safe": true,
2107
+ "type": "string"
2108
+ },
2109
+ "property_type": {
2110
+ "enum": [
2111
+ "single_family",
2112
+ "condo",
2113
+ "townhouse",
2114
+ "multi_family",
2115
+ "commercial",
2116
+ "other"
2117
+ ],
2118
+ "ping_safe": true,
2119
+ "type": "string"
2120
+ },
2121
+ "roof_type": {
2122
+ "enum": [
2123
+ "asphalt_shingle",
2124
+ "metal",
2125
+ "tile",
2126
+ "flat",
2127
+ "slate",
2128
+ "wood",
2129
+ "unknown"
2130
+ ],
2131
+ "ping_safe": true,
2132
+ "type": "string"
2133
+ },
2134
+ "schema_version": {
2135
+ "const": "1.0.0",
2136
+ "type": "string"
2137
+ },
2138
+ "service_subtype": {
2139
+ "description": "Controlled service operation. A more specific taxonomy can be introduced by a future vertical schema version without changing the core.",
2140
+ "enum": [
2141
+ "inspection",
2142
+ "repair",
2143
+ "replacement",
2144
+ "new_installation",
2145
+ "cleaning",
2146
+ "maintenance",
2147
+ "installation_and_repair",
2148
+ "emergency_response",
2149
+ "quote_only",
2150
+ "other"
2151
+ ],
2152
+ "ping_safe": true,
2153
+ "type": "string"
2154
+ },
2155
+ "service_type": {
2156
+ "description": "Controlled top-level service category.",
2157
+ "enum": [
2158
+ "roofing",
2159
+ "gutters",
2160
+ "downspouts",
2161
+ "plumbing",
2162
+ "hvac",
2163
+ "electrical",
2164
+ "landscaping",
2165
+ "painting",
2166
+ "windows",
2167
+ "doors",
2168
+ "flooring",
2169
+ "fencing",
2170
+ "concrete",
2171
+ "tree_service",
2172
+ "pest_control",
2173
+ "water_damage",
2174
+ "solar",
2175
+ "pool",
2176
+ "general_repair",
2177
+ "other"
2178
+ ],
2179
+ "ping_safe": true,
2180
+ "type": "string"
2181
+ },
2182
+ "square_footage_band": {
2183
+ "enum": [
2184
+ "under_1000",
2185
+ "1000_1500",
2186
+ "1500_2000",
2187
+ "2000_3000",
2188
+ "3000_5000",
2189
+ "over_5000",
2190
+ "unknown"
2191
+ ],
2192
+ "ping_safe": true,
2193
+ "type": "string"
2194
+ },
2195
+ "stories_band": {
2196
+ "enum": [
2197
+ "one",
2198
+ "two",
2199
+ "three_or_more",
2200
+ "unknown"
2201
+ ],
2202
+ "ping_safe": true,
2203
+ "type": "string"
2204
+ },
2205
+ "urgency": {
2206
+ "enum": [
2207
+ "emergency",
2208
+ "within_week",
2209
+ "within_month",
2210
+ "flexible"
2211
+ ],
2212
+ "ping_safe": true,
2213
+ "type": "string"
2214
+ },
2215
+ "vertical": {
2216
+ "const": "home_services",
2217
+ "type": "string"
2218
+ }
2219
+ },
2220
+ "required": [
2221
+ "vertical",
2222
+ "schema_version"
2223
+ ],
2224
+ "title": "LCP Home Services Vertical Schema",
2225
+ "type": "object"
2226
+ },
2227
+ "verticals/insurance.json": {
2228
+ "$id": "https://lcp.dev/verticals/insurance.json",
2229
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
2230
+ "additionalProperties": false,
2231
+ "description": "Insurance lead attributes. Every field is tagged ping_safe: true|false \u2014 the conformance runner rejects any ping containing a non-ping_safe field. Created by Spear Systems (a Spear company). Open standard \u2014 Apache 2.0, free to implement.",
2232
+ "properties": {
2233
+ "claim_count_band": {
2234
+ "description": "Banded number of claims filed.",
2235
+ "enum": [
2236
+ "none",
2237
+ "one",
2238
+ "two",
2239
+ "three_or_more"
2240
+ ],
2241
+ "ping_safe": true,
2242
+ "type": "string"
2243
+ },
2244
+ "coverage_amount_band": {
2245
+ "description": "Banded coverage amount for ping use.",
2246
+ "enum": [
2247
+ "under_25k",
2248
+ "25k_50k",
2249
+ "50k_100k",
2250
+ "100k_250k",
2251
+ "250k_500k",
2252
+ "500k_1m",
2253
+ "over_1m"
2254
+ ],
2255
+ "ping_safe": true,
2256
+ "type": "string"
2257
+ },
2258
+ "coverage_type": {
2259
+ "description": "Type of coverage sought.",
2260
+ "enum": [
2261
+ "liability",
2262
+ "comprehensive",
2263
+ "collision",
2264
+ "full_coverage",
2265
+ "term_life",
2266
+ "whole_life",
2267
+ "health_basic",
2268
+ "health_major_medical",
2269
+ "business_general_liability",
2270
+ "business_property",
2271
+ "business_workers_comp",
2272
+ "other"
2273
+ ],
2274
+ "ping_safe": true,
2275
+ "type": "string"
2276
+ },
2277
+ "current_insurer": {
2278
+ "description": "Current insurance company name. Company name \u2014 not ping_safe.",
2279
+ "ping_safe": false,
2280
+ "type": "string"
2281
+ },
2282
+ "deductible_band": {
2283
+ "description": "Banded deductible amount for ping use.",
2284
+ "enum": [
2285
+ "under_250",
2286
+ "250_500",
2287
+ "500_1000",
2288
+ "1000_2500",
2289
+ "2500_5000",
2290
+ "over_5000"
2291
+ ],
2292
+ "ping_safe": true,
2293
+ "type": "string"
2294
+ },
2295
+ "driver_age_band": {
2296
+ "description": "Banded driver age. Ping_safe for auto insurance underwriting.",
2297
+ "enum": [
2298
+ "under_18",
2299
+ "18_21",
2300
+ "21_25",
2301
+ "25_35",
2302
+ "35_50",
2303
+ "50_65",
2304
+ "over_65"
2305
+ ],
2306
+ "ping_safe": true,
2307
+ "type": "string"
2308
+ },
2309
+ "gender": {
2310
+ "description": "Gender \u2014 insurance requires this for underwriting rate classification.",
2311
+ "enum": [
2312
+ "male",
2313
+ "female",
2314
+ "non_binary",
2315
+ "prefer_not_to_say"
2316
+ ],
2317
+ "ping_safe": true,
2318
+ "type": "string"
2319
+ },
2320
+ "has_claims_history": {
2321
+ "description": "Has the consumer filed any claims?",
2322
+ "ping_safe": true,
2323
+ "type": "boolean"
2324
+ },
2325
+ "health_condition_band": {
2326
+ "description": "Self-reported health condition band for health insurance.",
2327
+ "enum": [
2328
+ "excellent",
2329
+ "good",
2330
+ "fair",
2331
+ "poor",
2332
+ "unknown"
2333
+ ],
2334
+ "ping_safe": true,
2335
+ "type": "string"
2336
+ },
2337
+ "height_band": {
2338
+ "description": "Banded height for health/life insurance underwriting.",
2339
+ "enum": [
2340
+ "under_5ft",
2341
+ "5_5ft5",
2342
+ "5ft5_5ft9",
2343
+ "5ft9_6ft",
2344
+ "over_6ft"
2345
+ ],
2346
+ "ping_safe": true,
2347
+ "type": "string"
2348
+ },
2349
+ "insurance_type": {
2350
+ "enum": [
2351
+ "auto",
2352
+ "home",
2353
+ "life",
2354
+ "health",
2355
+ "business"
2356
+ ],
2357
+ "ping_safe": true,
2358
+ "type": "string"
2359
+ },
2360
+ "marital_status": {
2361
+ "enum": [
2362
+ "single",
2363
+ "married",
2364
+ "divorced",
2365
+ "widowed",
2366
+ "separated",
2367
+ "domestic_partnership"
2368
+ ],
2369
+ "ping_safe": true,
2370
+ "type": "string"
2371
+ },
2372
+ "occupation_class": {
2373
+ "description": "Occupation risk class for life/disability insurance underwriting.",
2374
+ "enum": [
2375
+ "professional",
2376
+ "clerical",
2377
+ "skilled_trade",
2378
+ "manual_labor",
2379
+ "heavy_labor",
2380
+ "self_employed",
2381
+ "other"
2382
+ ],
2383
+ "ping_safe": true,
2384
+ "type": "string"
2385
+ },
2386
+ "property_type": {
2387
+ "description": "Property type for home insurance.",
2388
+ "enum": [
2389
+ "single_family",
2390
+ "condo",
2391
+ "townhouse",
2392
+ "multi_family",
2393
+ "rental",
2394
+ "mobile_home",
2395
+ "other"
2396
+ ],
2397
+ "ping_safe": true,
2398
+ "type": "string"
2399
+ },
2400
+ "schema_version": {
2401
+ "const": "1.0.0",
2402
+ "type": "string"
2403
+ },
2404
+ "smoker": {
2405
+ "description": "Smoking status for health/life insurance underwriting.",
2406
+ "ping_safe": true,
2407
+ "type": "boolean"
2408
+ },
2409
+ "vehicle_type": {
2410
+ "description": "Vehicle type for auto insurance. Ping_safe for auto.",
2411
+ "enum": [
2412
+ "sedan",
2413
+ "coupe",
2414
+ "suv",
2415
+ "truck",
2416
+ "van",
2417
+ "motorcycle",
2418
+ "rv",
2419
+ "commercial",
2420
+ "other"
2421
+ ],
2422
+ "ping_safe": true,
2423
+ "type": "string"
2424
+ },
2425
+ "vertical": {
2426
+ "const": "insurance",
2427
+ "type": "string"
2428
+ },
2429
+ "weight_band": {
2430
+ "description": "Banded weight (lbs) for health/life insurance underwriting.",
2431
+ "enum": [
2432
+ "under_120",
2433
+ "120_150",
2434
+ "150_180",
2435
+ "180_210",
2436
+ "210_250",
2437
+ "over_250"
2438
+ ],
2439
+ "ping_safe": true,
2440
+ "type": "string"
2441
+ },
2442
+ "years_with_current_insurer_band": {
2443
+ "description": "Banded years with current insurer.",
2444
+ "enum": [
2445
+ "under_1",
2446
+ "1_2",
2447
+ "3_5",
2448
+ "6_10",
2449
+ "over_10"
2450
+ ],
2451
+ "ping_safe": true,
2452
+ "type": "string"
2453
+ }
2454
+ },
2455
+ "required": [
2456
+ "vertical",
2457
+ "schema_version"
2458
+ ],
2459
+ "title": "LCP Insurance Vertical Schema",
2460
+ "type": "object"
2461
+ },
2462
+ "verticals/legal.json": {
2463
+ "$id": "https://lcp.dev/verticals/legal.json",
2464
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
2465
+ "additionalProperties": false,
2466
+ "description": "Legal lead attributes. Every field is tagged ping_safe: true|false \u2014 the conformance runner rejects any ping containing a non-ping_safe field. Created by Spear Systems (a Spear company). Open standard \u2014 Apache 2.0, free to implement.",
2467
+ "properties": {
2468
+ "at_fault": {
2469
+ "description": "Was the consumer at fault? Ping_safe for auto-related cases.",
2470
+ "ping_safe": true,
2471
+ "type": "boolean"
2472
+ },
2473
+ "case_type": {
2474
+ "enum": [
2475
+ "personal_injury",
2476
+ "divorce",
2477
+ "criminal",
2478
+ "dui",
2479
+ "bankruptcy",
2480
+ "immigration",
2481
+ "workers_comp",
2482
+ "medical_malpractice"
2483
+ ],
2484
+ "ping_safe": true,
2485
+ "type": "string"
2486
+ },
2487
+ "claim_status": {
2488
+ "description": "Current status of the claim.",
2489
+ "enum": [
2490
+ "not_filed",
2491
+ "filed",
2492
+ "under_review",
2493
+ "denied",
2494
+ "settled",
2495
+ "in_litigation"
2496
+ ],
2497
+ "ping_safe": true,
2498
+ "type": "string"
2499
+ },
2500
+ "has_attorney": {
2501
+ "description": "Does the consumer already have an attorney?",
2502
+ "ping_safe": true,
2503
+ "type": "boolean"
2504
+ },
2505
+ "incident_date": {
2506
+ "description": "Date of incident. Not ping_safe \u2014 could narrow identity.",
2507
+ "format": "date",
2508
+ "ping_safe": false,
2509
+ "type": "string"
2510
+ },
2511
+ "incident_state": {
2512
+ "description": "US state where incident occurred.",
2513
+ "ping_safe": true,
2514
+ "type": "string"
2515
+ },
2516
+ "injury_severity": {
2517
+ "description": "Severity of injury sustained.",
2518
+ "enum": [
2519
+ "none",
2520
+ "minor",
2521
+ "moderate",
2522
+ "severe",
2523
+ "catastrophic",
2524
+ "fatal"
2525
+ ],
2526
+ "ping_safe": true,
2527
+ "type": "string"
2528
+ },
2529
+ "insurance_company": {
2530
+ "description": "Insurance company involved. Company name \u2014 not ping_safe.",
2531
+ "ping_safe": false,
2532
+ "type": "string"
2533
+ },
2534
+ "medical_treatment_received": {
2535
+ "description": "Has medical treatment been received?",
2536
+ "ping_safe": true,
2537
+ "type": "boolean"
2538
+ },
2539
+ "police_report_filed": {
2540
+ "description": "Was a police report filed?",
2541
+ "ping_safe": true,
2542
+ "type": "boolean"
2543
+ },
2544
+ "schema_version": {
2545
+ "const": "1.0.0",
2546
+ "type": "string"
2547
+ },
2548
+ "time_to_contact_deadline_days": {
2549
+ "description": "Days remaining to contact before statute of limitations or deadline.",
2550
+ "maximum": 3650,
2551
+ "minimum": 0,
2552
+ "ping_safe": true,
2553
+ "type": "integer"
2554
+ },
2555
+ "vertical": {
2556
+ "const": "legal",
2557
+ "type": "string"
2558
+ }
2559
+ },
2560
+ "required": [
2561
+ "vertical",
2562
+ "schema_version"
2563
+ ],
2564
+ "title": "LCP Legal Vertical Schema",
2565
+ "type": "object"
2566
+ },
2567
+ "verticals/mortgage.json": {
2568
+ "$id": "https://lcp.dev/verticals/mortgage.json",
2569
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
2570
+ "additionalProperties": false,
2571
+ "description": "Mortgage lead attributes. Every field is tagged ping_safe: true|false \u2014 the conformance runner rejects any ping containing a non-ping_safe field. Created by Spear Systems (a Spear company). Open standard \u2014 Apache 2.0, free to implement.",
2572
+ "properties": {
2573
+ "annual_income_band": {
2574
+ "enum": [
2575
+ "under_40k",
2576
+ "40k_60k",
2577
+ "60k_80k",
2578
+ "80k_100k",
2579
+ "100k_150k",
2580
+ "over_150k"
2581
+ ],
2582
+ "ping_safe": true,
2583
+ "type": "string"
2584
+ },
2585
+ "annual_income_cents": {
2586
+ "description": "Annual income. PII-adjacent \u2014 not ping_safe.",
2587
+ "minimum": 0,
2588
+ "ping_safe": false,
2589
+ "type": "integer"
2590
+ },
2591
+ "bankruptcy_history": {
2592
+ "description": "Has the consumer filed for bankruptcy? Disqualifier for many loan products.",
2593
+ "ping_safe": true,
2594
+ "type": "boolean"
2595
+ },
2596
+ "cash_out_amount_band": {
2597
+ "enum": [
2598
+ "none",
2599
+ "under_25k",
2600
+ "25k_50k",
2601
+ "50k_100k",
2602
+ "over_100k"
2603
+ ],
2604
+ "ping_safe": true,
2605
+ "type": "string"
2606
+ },
2607
+ "cash_out_amount_cents": {
2608
+ "description": "Cash-out amount for cash-out refinance. Not ping_safe.",
2609
+ "minimum": 0,
2610
+ "ping_safe": false,
2611
+ "type": "integer"
2612
+ },
2613
+ "credit_rating_band": {
2614
+ "enum": [
2615
+ "excellent",
2616
+ "good",
2617
+ "fair",
2618
+ "poor",
2619
+ "unknown"
2620
+ ],
2621
+ "ping_safe": true,
2622
+ "type": "string"
2623
+ },
2624
+ "current_lender": {
2625
+ "description": "Current mortgage lender (refinance context). Company name \u2014 not ping_safe.",
2626
+ "ping_safe": false,
2627
+ "type": "string"
2628
+ },
2629
+ "desired_rate_term": {
2630
+ "description": "Desired mortgage rate term.",
2631
+ "enum": [
2632
+ "15_year_fixed",
2633
+ "20_year_fixed",
2634
+ "30_year_fixed",
2635
+ "5_1_arm",
2636
+ "7_1_arm",
2637
+ "10_1_arm",
2638
+ "interest_only",
2639
+ "other"
2640
+ ],
2641
+ "ping_safe": true,
2642
+ "type": "string"
2643
+ },
2644
+ "employment_status": {
2645
+ "enum": [
2646
+ "employed",
2647
+ "self_employed",
2648
+ "retired",
2649
+ "unemployed",
2650
+ "student"
2651
+ ],
2652
+ "ping_safe": true,
2653
+ "type": "string"
2654
+ },
2655
+ "existing_rate_percent": {
2656
+ "description": "Current interest rate. Not ping_safe \u2014 can narrow identity.",
2657
+ "maximum": 30,
2658
+ "minimum": 0,
2659
+ "ping_safe": false,
2660
+ "type": "number"
2661
+ },
2662
+ "foreclosure_history": {
2663
+ "description": "Has the consumer had a foreclosure? Disqualifier for many loan products.",
2664
+ "ping_safe": true,
2665
+ "type": "boolean"
2666
+ },
2667
+ "has_existing_mortgage": {
2668
+ "ping_safe": true,
2669
+ "type": "boolean"
2670
+ },
2671
+ "is_first_home_buyer": {
2672
+ "ping_safe": true,
2673
+ "type": "boolean"
2674
+ },
2675
+ "loan_amount_band": {
2676
+ "description": "Banded loan amount for ping use.",
2677
+ "enum": [
2678
+ "under_100k",
2679
+ "100k_250k",
2680
+ "250k_500k",
2681
+ "500k_750k",
2682
+ "750k_1m",
2683
+ "over_1m"
2684
+ ],
2685
+ "ping_safe": true,
2686
+ "type": "string"
2687
+ },
2688
+ "loan_amount_cents": {
2689
+ "description": "Exact loan amount in cents. PII-adjacent \u2014 not ping_safe.",
2690
+ "minimum": 0,
2691
+ "ping_safe": false,
2692
+ "type": "integer"
2693
+ },
2694
+ "loan_term_band": {
2695
+ "description": "Banded loan term.",
2696
+ "enum": [
2697
+ "under_15",
2698
+ "15",
2699
+ "20",
2700
+ "30",
2701
+ "over_30"
2702
+ ],
2703
+ "ping_safe": true,
2704
+ "type": "string"
2705
+ },
2706
+ "loan_term_years": {
2707
+ "description": "Exact loan term in years. Not ping_safe.",
2708
+ "maximum": 40,
2709
+ "minimum": 1,
2710
+ "ping_safe": false,
2711
+ "type": "integer"
2712
+ },
2713
+ "loan_type": {
2714
+ "enum": [
2715
+ "purchase",
2716
+ "refinance",
2717
+ "cash_out_refinance",
2718
+ "debt_consolidation",
2719
+ "first_home_buyer",
2720
+ "investment"
2721
+ ],
2722
+ "ping_safe": true,
2723
+ "type": "string"
2724
+ },
2725
+ "ltv_ratio_band": {
2726
+ "description": "Loan-to-value ratio band.",
2727
+ "enum": [
2728
+ "under_60",
2729
+ "60_70",
2730
+ "70_80",
2731
+ "80_90",
2732
+ "90_95",
2733
+ "over_95"
2734
+ ],
2735
+ "ping_safe": true,
2736
+ "type": "string"
2737
+ },
2738
+ "mortgage_product": {
2739
+ "additionalProperties": false,
2740
+ "description": "Country-specific mortgage product. Include only fields relevant to your country; all others MAY be null or omitted. Follows the country-scoping rule in AGENTS.md \u00a77.",
2741
+ "ping_safe": true,
2742
+ "properties": {
2743
+ "au_product": {
2744
+ "description": "Australian mortgage product type. Null if not AU.",
2745
+ "enum": [
2746
+ "principal_and_interest",
2747
+ "interest_only",
2748
+ "offset",
2749
+ null
2750
+ ],
2751
+ "ping_safe": true,
2752
+ "type": [
2753
+ "string",
2754
+ "null"
2755
+ ]
2756
+ },
2757
+ "ca_product": {
2758
+ "description": "Canadian mortgage product type. Null if not CA.",
2759
+ "enum": [
2760
+ "insured",
2761
+ "insurable",
2762
+ "uninsured",
2763
+ null
2764
+ ],
2765
+ "ping_safe": true,
2766
+ "type": [
2767
+ "string",
2768
+ "null"
2769
+ ]
2770
+ },
2771
+ "country_code": {
2772
+ "description": "ISO 3166-1 alpha-2 country code (e.g. US, CA, GB, AU).",
2773
+ "ping_safe": true,
2774
+ "type": "string"
2775
+ },
2776
+ "gb_product": {
2777
+ "description": "UK mortgage product type. Null if not GB.",
2778
+ "enum": [
2779
+ "standard_variable",
2780
+ "discount",
2781
+ "tracker",
2782
+ "offset",
2783
+ null
2784
+ ],
2785
+ "ping_safe": true,
2786
+ "type": [
2787
+ "string",
2788
+ "null"
2789
+ ]
2790
+ },
2791
+ "us_product": {
2792
+ "description": "US mortgage product type. Null if not US.",
2793
+ "enum": [
2794
+ "conventional",
2795
+ "fha",
2796
+ "va",
2797
+ "heloc",
2798
+ "jumbo",
2799
+ "usda",
2800
+ null
2801
+ ],
2802
+ "ping_safe": true,
2803
+ "type": [
2804
+ "string",
2805
+ "null"
2806
+ ]
2807
+ }
2808
+ },
2809
+ "required": [
2810
+ "country_code"
2811
+ ],
2812
+ "type": "object"
2813
+ },
2814
+ "mortgage_purpose": {
2815
+ "enum": [
2816
+ "new_mortgage",
2817
+ "remortgage",
2818
+ "equity_release",
2819
+ "debt_consolidation"
2820
+ ],
2821
+ "ping_safe": true,
2822
+ "type": "string"
2823
+ },
2824
+ "property_address": {
2825
+ "description": "Full property address. PII \u2014 never in ping.",
2826
+ "ping_safe": false,
2827
+ "type": "string"
2828
+ },
2829
+ "property_type": {
2830
+ "enum": [
2831
+ "single_family",
2832
+ "condo",
2833
+ "townhouse",
2834
+ "multi_family",
2835
+ "investment_property",
2836
+ "land"
2837
+ ],
2838
+ "ping_safe": true,
2839
+ "type": "string"
2840
+ },
2841
+ "property_value_band": {
2842
+ "enum": [
2843
+ "under_200k",
2844
+ "200k_400k",
2845
+ "400k_600k",
2846
+ "600k_800k",
2847
+ "800k_1m",
2848
+ "over_1m"
2849
+ ],
2850
+ "ping_safe": true,
2851
+ "type": "string"
2852
+ },
2853
+ "property_value_cents": {
2854
+ "description": "Estimated property value. Not ping_safe \u2014 could narrow identity.",
2855
+ "minimum": 0,
2856
+ "ping_safe": false,
2857
+ "type": "integer"
2858
+ },
2859
+ "schema_version": {
2860
+ "const": "1.0.0",
2861
+ "type": "string"
2862
+ },
2863
+ "self_employed_income_verified": {
2864
+ "description": "For self-employed leads, whether income has been verified (bank statements, tax returns).",
2865
+ "ping_safe": true,
2866
+ "type": "boolean"
2867
+ },
2868
+ "vertical": {
2869
+ "const": "mortgage",
2870
+ "type": "string"
2871
+ },
2872
+ "veteran_status": {
2873
+ "enum": [
2874
+ "veteran",
2875
+ "active_duty",
2876
+ "reservist",
2877
+ "non_veteran"
2878
+ ],
2879
+ "ping_safe": true,
2880
+ "type": "string"
2881
+ }
2882
+ },
2883
+ "required": [
2884
+ "vertical",
2885
+ "schema_version"
2886
+ ],
2887
+ "title": "LCP Mortgage Vertical Schema",
2888
+ "type": "object"
2889
+ },
2890
+ "verticals/mva.json": {
2891
+ "$id": "https://lcp.dev/verticals/mva.json",
2892
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
2893
+ "additionalProperties": false,
2894
+ "description": "Motor-vehicle-accident lead attributes. Exact medical, contractual, and evidentiary documents stay in the post and authenticated attachment store; pings expose only controlled bands and qualification flags.",
2895
+ "properties": {
2896
+ "accident_date": {
2897
+ "description": "Exact accident date. Post-only; never include in a ping.",
2898
+ "format": "date",
2899
+ "ping_safe": false,
2900
+ "type": "string"
2901
+ },
2902
+ "accident_date_band": {
2903
+ "description": "Age band of the accident; never expose an exact date in a ping.",
2904
+ "enum": [
2905
+ "last_7_days",
2906
+ "8_30_days",
2907
+ "1_3_months",
2908
+ "3_12_months",
2909
+ "over_12_months"
2910
+ ],
2911
+ "ping_safe": true,
2912
+ "type": "string"
2913
+ },
2914
+ "accident_type": {
2915
+ "enum": [
2916
+ "car_collision",
2917
+ "motorcycle_collision",
2918
+ "truck_collision",
2919
+ "rideshare_collision",
2920
+ "pedestrian",
2921
+ "bicycle",
2922
+ "public_transport",
2923
+ "work_vehicle",
2924
+ "other"
2925
+ ],
2926
+ "ping_safe": true,
2927
+ "type": "string"
2928
+ },
2929
+ "additional_context": {
2930
+ "description": "Free text may contain sensitive information and is post-only.",
2931
+ "ping_safe": false,
2932
+ "type": "string"
2933
+ },
2934
+ "claim_filed": {
2935
+ "ping_safe": true,
2936
+ "type": "boolean"
2937
+ },
2938
+ "claim_stage": {
2939
+ "enum": [
2940
+ "initial_intake",
2941
+ "insurer_contacted",
2942
+ "claim_open",
2943
+ "claim_denied",
2944
+ "settlement_discussion",
2945
+ "unknown"
2946
+ ],
2947
+ "ping_safe": true,
2948
+ "type": "string"
2949
+ },
2950
+ "commercial_vehicle_involved": {
2951
+ "ping_safe": true,
2952
+ "type": "boolean"
2953
+ },
2954
+ "consumer_insured": {
2955
+ "enum": [
2956
+ "yes",
2957
+ "no",
2958
+ "unknown"
2959
+ ],
2960
+ "ping_safe": true,
2961
+ "type": "string"
2962
+ },
2963
+ "emergency_services_called": {
2964
+ "ping_safe": true,
2965
+ "type": "boolean"
2966
+ },
2967
+ "evidence_available": {
2968
+ "description": "Presence indicators only. The actual records are represented by encrypted attachments.",
2969
+ "items": {
2970
+ "enum": [
2971
+ "police_report",
2972
+ "medical_record",
2973
+ "insurance_policy",
2974
+ "photographs",
2975
+ "witness_details",
2976
+ "signed_contract",
2977
+ "other"
2978
+ ],
2979
+ "type": "string"
2980
+ },
2981
+ "ping_safe": true,
2982
+ "type": "array",
2983
+ "uniqueItems": true
2984
+ },
2985
+ "fault_position": {
2986
+ "enum": [
2987
+ "not_at_fault",
2988
+ "partially_at_fault",
2989
+ "at_fault",
2990
+ "unclear",
2991
+ "unknown"
2992
+ ],
2993
+ "ping_safe": true,
2994
+ "type": "string"
2995
+ },
2996
+ "injury_present": {
2997
+ "ping_safe": true,
2998
+ "type": "boolean"
2999
+ },
3000
+ "injury_severity_band": {
3001
+ "enum": [
3002
+ "none",
3003
+ "minor",
3004
+ "moderate",
3005
+ "serious",
3006
+ "fatality",
3007
+ "unknown"
3008
+ ],
3009
+ "ping_safe": true,
3010
+ "type": "string"
3011
+ },
3012
+ "jurisdiction": {
3013
+ "description": "State, province, or territory where the accident occurred. Prefer core location for the consumer's current location.",
3014
+ "ping_safe": true,
3015
+ "type": "string"
3016
+ },
3017
+ "medical_treatment": {
3018
+ "enum": [
3019
+ "none",
3020
+ "self_treated",
3021
+ "emergency_room",
3022
+ "hospitalized",
3023
+ "ongoing",
3024
+ "unknown"
3025
+ ],
3026
+ "ping_safe": true,
3027
+ "type": "string"
3028
+ },
3029
+ "other_driver_identified": {
3030
+ "ping_safe": true,
3031
+ "type": "boolean"
3032
+ },
3033
+ "other_driver_insured": {
3034
+ "enum": [
3035
+ "yes",
3036
+ "no",
3037
+ "unknown"
3038
+ ],
3039
+ "ping_safe": true,
3040
+ "type": "string"
3041
+ },
3042
+ "passenger_count_band": {
3043
+ "enum": [
3044
+ "none",
3045
+ "one",
3046
+ "two",
3047
+ "three_or_more",
3048
+ "unknown"
3049
+ ],
3050
+ "ping_safe": true,
3051
+ "type": "string"
3052
+ },
3053
+ "police_report_available": {
3054
+ "ping_safe": true,
3055
+ "type": "boolean"
3056
+ },
3057
+ "prior_attorney_consultation": {
3058
+ "ping_safe": true,
3059
+ "type": "boolean"
3060
+ },
3061
+ "represented_by_attorney": {
3062
+ "ping_safe": true,
3063
+ "type": "boolean"
3064
+ },
3065
+ "schema_version": {
3066
+ "const": "1.0.0",
3067
+ "type": "string"
3068
+ },
3069
+ "vehicle_count_band": {
3070
+ "enum": [
3071
+ "one",
3072
+ "two",
3073
+ "three_or_more",
3074
+ "unknown"
3075
+ ],
3076
+ "ping_safe": true,
3077
+ "type": "string"
3078
+ },
3079
+ "vertical": {
3080
+ "const": "mva",
3081
+ "type": "string"
3082
+ }
3083
+ },
3084
+ "required": [
3085
+ "vertical",
3086
+ "schema_version"
3087
+ ],
3088
+ "title": "LCP Motor Vehicle Accident Vertical Schema",
3089
+ "type": "object"
3090
+ },
3091
+ "verticals/solar.json": {
3092
+ "$id": "https://lcp.dev/verticals/solar.json",
3093
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3094
+ "additionalProperties": false,
3095
+ "description": "Solar lead attributes. Every field is tagged ping_safe: true|false \u2014 the conformance runner rejects any ping containing a non-ping_safe field. Created by Spear Systems (a Spear company). Open standard \u2014 Apache 2.0, free to implement.",
3096
+ "properties": {
3097
+ "battery_storage_interest": {
3098
+ "description": "Consumer interest in battery storage.",
3099
+ "ping_safe": true,
3100
+ "type": "boolean"
3101
+ },
3102
+ "current_energy_source": {
3103
+ "description": "Current energy source.",
3104
+ "enum": [
3105
+ "grid",
3106
+ "solar_existing",
3107
+ "wind",
3108
+ "generator",
3109
+ "hybrid",
3110
+ "other"
3111
+ ],
3112
+ "ping_safe": true,
3113
+ "type": "string"
3114
+ },
3115
+ "installation_timeline": {
3116
+ "description": "Desired installation timeline.",
3117
+ "enum": [
3118
+ "immediate",
3119
+ "1_3_months",
3120
+ "3_6_months",
3121
+ "6_12_months",
3122
+ "exploring"
3123
+ ],
3124
+ "ping_safe": true,
3125
+ "type": "string"
3126
+ },
3127
+ "monthly_electric_bill_band": {
3128
+ "description": "Banded monthly electric bill in dollars.",
3129
+ "enum": [
3130
+ "under_100",
3131
+ "100_150",
3132
+ "150_200",
3133
+ "200_300",
3134
+ "300_500",
3135
+ "over_500"
3136
+ ],
3137
+ "ping_safe": true,
3138
+ "type": "string"
3139
+ },
3140
+ "number_of_panels_band": {
3141
+ "description": "Banded number of solar panels.",
3142
+ "enum": [
3143
+ "under_10",
3144
+ "10_20",
3145
+ "20_30",
3146
+ "30_40",
3147
+ "over_40"
3148
+ ],
3149
+ "ping_safe": true,
3150
+ "type": "string"
3151
+ },
3152
+ "ownership": {
3153
+ "description": "Property ownership status.",
3154
+ "enum": [
3155
+ "own",
3156
+ "rent"
3157
+ ],
3158
+ "ping_safe": true,
3159
+ "type": "string"
3160
+ },
3161
+ "property_type": {
3162
+ "enum": [
3163
+ "single_family",
3164
+ "condo",
3165
+ "townhouse",
3166
+ "multi_family",
3167
+ "commercial",
3168
+ "other"
3169
+ ],
3170
+ "ping_safe": true,
3171
+ "type": "string"
3172
+ },
3173
+ "roof_type": {
3174
+ "description": "Roof material type.",
3175
+ "enum": [
3176
+ "asphalt_shingle",
3177
+ "metal",
3178
+ "tile",
3179
+ "flat",
3180
+ "wood_shake",
3181
+ "slate",
3182
+ "other"
3183
+ ],
3184
+ "ping_safe": true,
3185
+ "type": "string"
3186
+ },
3187
+ "schema_version": {
3188
+ "const": "1.0.0",
3189
+ "type": "string"
3190
+ },
3191
+ "shade_level": {
3192
+ "description": "Roof shade level affecting solar production.",
3193
+ "enum": [
3194
+ "none",
3195
+ "partial",
3196
+ "significant"
3197
+ ],
3198
+ "ping_safe": true,
3199
+ "type": "string"
3200
+ },
3201
+ "system_size_kw_band": {
3202
+ "description": "Banded solar system size in kilowatts.",
3203
+ "enum": [
3204
+ "under_5kw",
3205
+ "5_10kw",
3206
+ "10_15kw",
3207
+ "15_20kw",
3208
+ "over_20kw"
3209
+ ],
3210
+ "ping_safe": true,
3211
+ "type": "string"
3212
+ },
3213
+ "utility_provider": {
3214
+ "description": "Current utility provider name.",
3215
+ "ping_safe": true,
3216
+ "type": "string"
3217
+ },
3218
+ "vertical": {
3219
+ "const": "solar",
3220
+ "type": "string"
3221
+ }
3222
+ },
3223
+ "required": [
3224
+ "vertical",
3225
+ "schema_version"
3226
+ ],
3227
+ "title": "LCP Solar Vertical Schema",
3228
+ "type": "object"
3229
+ }
3230
+ }