39 KiB
HybridmailPingenSpecification.md
1. Document Status
Document: HybridmailPingenSpecification.md Project: hybridmail-connect Provider Flavor: Pingen Parent Specification: HybridmailAdapterSpecification.md Target Integration: coordination-engine Adapter Contract: AdapterInterfaceSpecification.md v1.0 Status: Draft v1.0 Primary Scope: Pingen-specific hybrid-mail provider flavor for letter upload, letter creation, validation, auto-send/manual-send control, Track & Trace, webhooks, return mail, delivered/undeliverable status mapping, and idempotent API usage.
2. Purpose
This document specifies the Pingen provider flavor for hybridmail-connect.
The Pingen flavor implements the generic hybrid-mail adapter model for the Pingen Letter API. It maps Pingen’s API concepts into the provider-neutral hybrid-mail model used by coordination-engine.
The purpose of this document is to capture:
- Pingen-specific provider capabilities.
- Pingen-specific workflow stages.
- Pingen letter, file, address, validation, send, status, Track & Trace, and webhook concepts.
- Pingen return-mail and undeliverable processing.
- Pingen delivery-confirmation semantics.
- Pingen idempotency and rate-limit behavior.
- Pingen evidence event mapping.
- Pingen-specific limitations and assumptions.
- Pingen-specific MVP boundaries.
The Pingen flavor MUST remain compatible with HybridmailAdapterSpecification.md and MUST NOT leak Pingen-specific terminology into the core coordination model except through mapped provider metadata.
3. Grounding Summary
The public Pingen material indicates the following relevant features:
- Pingen provides a Letter API for automated postal-letter sending.
- Pingen offers SDKs, including PHP, Python, Go, .NET, and code examples.
- API authentication uses OAuth-style client credentials in common tooling/examples.
- Pingen supports Idempotency-Key headers.
- Pingen supports rate limiting and configurable send limits.
- Pingen offers staging/sandbox or full-feature simulation.
- Pingen supports document validation.
- Pingen supports configurable address position.
- Pingen supports auto-send control.
- Pingen offers Track & Trace for real-time progress transparency.
- Pingen provides webhooks for status changes.
- Public webhook categories include letter issues, sent letters, undeliverable letters, and delivered letters.
- Pingen automates return-mail processing and can provide return details via email and webhook.
- Pingen distinguishes ordinary postal dispatch from actual delivery-confirmation products. Ordinary letters may not receive final post-office delivery confirmation.
These facts define the baseline for this provider flavor.
4. Provider Flavor Identity
HybridmailProviderFlavorDescriptor:
provider_name: pingen
provider_label: Pingen Letter API
provider_family: hybridmail
adapter_contract_version: "1.0"
parent_specification: HybridmailAdapterSpecification.md
deployment_mode: external
5. Pingen Capability Descriptor
The Pingen flavor MUST expose a capability descriptor.
HybridmailProviderFlavorDescriptor:
provider_name: pingen
provider_version: provider_specific
supported_file_types:
- pdf
supported_attachment_file_types:
- provider_specific
supports_single_letter: true
supports_bulk: true
supports_serial_letters: true
supports_attachments: provider_specific
supports_preview: true
supports_webhooks: true
supports_polling: true
supports_track_and_trace: true
supports_registered_mail: true
supports_delivery_confirmation: product_dependent
supports_return_mail: true
supports_address_correction: provider_specific
supports_international_mail: true
supports_cancellation: provider_specific
supports_staging: true
supports_full_feature_simulation: true
supports_idempotency: true
supports_rate_limits: true
supports_configurable_send_limits: true
supports_auto_send: true
supports_address_position_configuration: true
supports_document_validation: true
supported_print_options:
color_mode: provider_specific
simplex_duplex: provider_specific
envelope_selection: provider_specific
address_position: true
supported_postal_products:
- standard
- registered
- delivery_confirmation
- international
- provider_specific
limitations:
- Ordinary postal letters usually do not provide final post-office delivery confirmation.
- Delivered-letter webhook semantics must be interpreted according to selected product and Pingen status details.
- Return-mail information may arrive late.
- Public documentation confirms webhook categories, but exact event payload fields must be implemented against the live Pingen API documentation.
- Provider-native status names must be preserved in metadata and mapped conservatively.
6. Pingen-Specific Conceptual Workflow
The Pingen flavor uses a file/letter-centric workflow.
authenticate
→ upload file / create letter
→ configure address position and sending options
→ validate letter
→ optionally auto-send or manually trigger send
→ Track & Trace status changes
→ webhook or polling status ingestion
→ sent-letter evidence
→ undeliverable/return-mail evidence where applicable
→ delivered-letter evidence where product/status supports it
The adapter MUST preserve this distinction:
Letter creation is not sending.
Validation success is not postal dispatch.
Sent status is not necessarily final delivery.
Ordinary postal dispatch is not proof of human awareness.
Return-mail events may arrive late and can change the delivery assessment.
7. Pingen Object Mapping
7.1 Generic to Pingen Mapping
| Generic hybrid-mail concept | Pingen flavor concept |
|---|---|
HybridmailLetter |
Pingen letter |
HybridmailDocumentRef |
Uploaded file / letter document |
HybridmailAttempt |
Pingen letter creation/send operation |
HybridmailBatch |
Bulk or serial letter group where used |
PostalRecipient |
Address extracted from document or configured via address position / metadata where supported |
HybridmailOptions |
Pingen send, print, address, and delivery options |
HybridmailPreview |
Pingen preview or validation representation where supported |
HybridmailTimeline |
Pingen Track & Trace and webhook timeline |
7.2 PingenLetter
PingenLetter:
pingen_letter_id: string
hybridmail_letter_id: string?
coordination_case_id: string?
participant_id: string?
provider_status: string?
normalized_status: string
file_ref: ResourceRef
page_count: integer?
sheet_count: integer?
address_position: PingenAddressPosition?
options: PingenLetterOptions?
validation_result: PingenValidationResult?
track_and_trace_ref: string?
webhook_event_refs:
- string
created_at: timestamp
updated_at: timestamp?
metadata: object?
7.3 PingenFile
PingenFile:
pingen_file_id: string?
hybridmail_letter_id: string?
original_file_ref: ResourceRef
file_type: pdf | unknown
file_size_bytes: integer?
integrity_hash: string?
upload_state: pending | uploaded | rejected | failed | unknown
created_at: timestamp
metadata: object?
7.4 PingenAttempt
PingenAttempt:
pingen_attempt_id: string
hybridmail_letter_id: string
pingen_letter_id: string?
provider_operation_id: string?
idempotency_key: string
operation_type: create_letter | validate_letter | send_letter | cancel_letter | status_poll | webhook_ingest
state: pending | accepted | rejected | failed | completed | duplicate | unknown
created_at: timestamp
updated_at: timestamp?
raw_provider_response_ref: string?
7.5 PingenBatch
PingenBatch:
pingen_batch_id: string?
hybridmail_batch_id: string
coordination_case_id: string?
batch_type: bulk | serial | campaign | mixed | unknown
letters:
- hybridmail_letter_id
state: pending | partial | completed | failed | unknown
created_at: timestamp
updated_at: timestamp?
Batch-level events MUST NOT be treated as success for every child letter unless Pingen provides per-letter status or policy explicitly accepts batch-level evidence.
8. Pingen Address Model
Pingen supports configurable address position. The Pingen flavor MUST model address positioning explicitly.
PingenAddressPosition:
source: configured | detected | provider_default | unknown
position: left | right | provider_specific | unknown
page_number: integer?
bounding_box: object?
confidence: low | medium | high
Generic postal recipient mapping:
PostalRecipient:
recipient_id: string?
name_lines:
- string
organization: string?
street: string?
house_number: string?
address_addition: string?
postal_code: string?
city: string?
region: string?
country_code: string?
country_name: string?
address_source: extracted_from_document | provided_metadata | provider_detected | manual | unknown
address_quality: PostalAddressQuality?
If Pingen validation detects address issues, they MUST be mapped into PingenValidationIssue and then into generic HybridmailValidationIssue.
9. Pingen Validation Model
Pingen validation results MUST be mapped into generic HybridmailValidationResult.
PingenValidationResult:
pingen_letter_id: string
provider_validation_state: string?
validation_state: pending | passed | action_required | failed | unknown
issues:
- PingenValidationIssue
validated_at: timestamp?
raw_provider_response_ref: string?
PingenValidationIssue:
provider_issue_code: string?
issue_code: string
severity: info | warning | action_required | fatal
category: format | page_size | pdf | address | address_position | restricted_area | margins | file_size | page_count | postage | country | provider_policy | unknown
message: string
page_number: integer?
bounding_box: object?
fixable: boolean?
10. Pingen Validation Issue Mapping
| Pingen validation concern | Generic validation category | Normalized issue code |
|---|---|---|
| Invalid PDF | pdf / format |
invalid_pdf |
| Unsupported file type | format |
unsupported_file_type |
| Address not found or unreadable | address |
address_not_detected |
| Address position invalid | address_position |
address_position_invalid |
| Address format invalid | address |
address_format_invalid |
| Unsupported destination country | country |
unsupported_country |
| Page or file constraints violated | page_count / file_size |
document_constraint_violation |
| Postal product invalid | postage |
unsupported_product |
| Provider policy rejection | provider_policy |
provider_policy_rejected |
| Unknown validation issue | unknown |
unknown_validation_issue |
Validation failure MUST emit:
payload.validation_failed
Validation success MUST emit:
payload.validation_passed
If Pingen classifies an issue as fixable/action-required, the adapter SHOULD include severity action_required rather than immediately treating the coordination case as permanently failed.
11. Pingen Letter Options
The Pingen flavor MUST map Pingen options into the generic HybridmailOptions.
PingenLetterOptions:
color_mode: color | grayscale | provider_default | unknown
print_sides: simplex | duplex | provider_default | unknown
address_position: left | right | provider_default | unknown
postage_product: standard | registered | delivery_confirmation | international | provider_specific
country_scope: domestic | international | unknown
auto_send: boolean?
dispatch_mode: manual_review | auto_send | submit_later | scheduled
desired_dispatch_date: date?
return_mail_handling: none | provider_processed | scan_return | digital_return_info | physical_return | unknown
delivery_confirmation_requested: boolean?
metadata: object?
Provider-native option names MUST be preserved in metadata.
The adapter MUST NOT assume support for a postal product unless the Pingen capability descriptor confirms it.
12. Pingen Auto-Send Handling
Pingen supports auto-send behavior according to public API materials.
The adapter MUST explicitly model auto-send, because it affects the transition from creation/validation to physical dispatch.
PingenAutoSendPolicy:
auto_send: boolean
send_after_validation: boolean?
require_adapter_approval: boolean?
require_coordination_policy_approval: boolean?
Recommended safety rule:
For high-assurance or expensive physical-mail scenarios,
auto_send SHOULD default to false unless explicitly enabled by policy.
If auto_send=true, the adapter MUST make duplicate-send prevention especially strict.
13. Pingen Track & Trace Model
Pingen provides Track & Trace progress updates. The adapter MUST represent those as a timeline.
PingenTrackAndTraceEvent:
event_id: string
pingen_letter_id: string
provider_status: string
normalized_status: string
event_category: letter_issue | sent_letter | undeliverable_letter | delivered_letter | return_mail | processing | unknown
occurred_at: timestamp?
observed_at: timestamp
raw_provider_response_ref: string?
metadata: object?
Track & Trace events should map to the strongest safe generic event.
If the event only indicates process progress, it MUST NOT be mapped to postal delivery confirmation.
14. Pingen Webhook Model
Pingen public help identifies webhook categories:
Letter issues
Sent letters
Undeliverable letters
Delivered letters
The adapter MUST support these categories where available.
PingenWebhookEvent:
pingen_webhook_event_id: string
webhook_category: letter_issue | sent_letter | undeliverable_letter | delivered_letter | unknown
pingen_letter_id: string?
provider_event_id: string?
occurred_at: timestamp?
observed_at: timestamp
raw_payload_ref: string?
normalized_events:
- EvidenceEvent
15. Pingen Webhook Category Mapping
| Pingen webhook category | Generic event | Evidence interpretation |
|---|---|---|
| Letter issues | payload.validation_failed or delivery.payload.rejected |
Strong issue/failure/action-required evidence depending payload |
| Sent letters | delivery.postal.handed_over or delivery.payload.submitted |
Strong dispatch evidence only if semantics confirm physical send/handover |
| Undeliverable letters | delivery.postal.undeliverable or delivery.postal.return_received |
Strong negative delivery evidence |
| Delivered letters | delivery.postal.delivery_confirmed |
Strong delivery evidence if product/status supports delivery confirmation |
Important:
A "sent letters" event should not be interpreted as "recipient received the letter".
A "delivered letters" event must be interpreted according to the postal product and provider semantics.
16. Pingen Return Mail Model
Pingen supports automated return-mail processing and provides return details via channels including webhooks.
PingenReturnEvent:
return_event_id: string
pingen_letter_id: string
provider_return_id: string?
return_type: undeliverable | address_unknown | recipient_moved | refused | insufficient_address | other | unknown
return_details: string?
address_correction: PostalRecipient?
return_document_ref: ResourceRef?
occurred_at: timestamp?
observed_at: timestamp
raw_event_ref: string?
Return events usually create strong negative delivery evidence:
delivery.postal.return_received
delivery.postal.undeliverable
Return events may arrive late and MUST be preserved even if the coordination case has already progressed.
17. Pingen Delivery Confirmation Model
Pingen delivery-confirmation evidence is product-dependent.
PingenDeliveryConfirmation:
confirmation_id: string
pingen_letter_id: string
product_type: delivery_confirmation | registered | provider_specific
provider_status: string?
normalized_status: delivered | attempted | refused | undeliverable | returned | unknown
occurred_at: timestamp?
observed_at: timestamp
raw_event_ref: string?
The adapter MUST only emit:
delivery.postal.delivery_confirmed
when the Pingen status and selected postal product semantically support delivery confirmation.
Ordinary letter dispatch MUST NOT be mapped to delivery.postal.delivery_confirmed.
18. Pingen Status Model
The Pingen flavor MUST preserve raw provider status and map it to normalized status.
PingenStatusRecord:
status_record_id: string
pingen_letter_id: string
provider_status: string
normalized_status: string
status_scope: letter | validation | sending | track_and_trace | webhook | return_mail | unknown
observed_at: timestamp
raw_provider_response_ref: string?
19. Normalized Pingen Status Categories
The Pingen flavor SHOULD map native statuses into these normalized categories:
letter.created
letter.uploaded
letter.validation_pending
letter.validation_passed
letter.validation_failed
letter.action_required
letter.ready_for_sending
letter.submitted_for_sending
letter.processing
letter.handed_to_postal_service
letter.sent
letter.delivery_confirmed
letter.undeliverable
letter.return_received
letter.cancelled
letter.failed
letter.status_unknown
Where Pingen status granularity is insufficient, the adapter MUST use the nearest weaker event and preserve the raw status in metadata.
20. Pingen-to-Generic Event Mapping
| Pingen workflow event | Generic event | Evidence interpretation |
|---|---|---|
| File/letter accepted | delivery.payload.accepted |
Digital submission accepted |
| Letter rejected | delivery.payload.rejected |
Attempt failed |
| Validation passed | payload.validation_passed |
Provider-processable |
| Letter issue | payload.validation_failed or delivery.payload.rejected |
Issue/action-required/failure |
| Ready for sending | delivery.payload.available |
Operational readiness |
| Auto-send triggered | delivery.payload.submitted |
Provider instructed to send |
| Manual send triggered | delivery.payload.submitted |
Provider instructed to send |
| Processing | delivery.production.started |
Provider processing began |
| Sent-letter event | delivery.postal.handed_over if semantics support; otherwise delivery.payload.submitted |
Strong dispatch or send-process evidence |
| Delivered-letter event | delivery.postal.delivery_confirmed if product/status supports |
Strong delivery evidence |
| Undeliverable-letter event | delivery.postal.undeliverable |
Strong negative evidence |
| Return details received | delivery.postal.return_received |
Strong negative evidence |
| Track & Trace update | status-specific mapped event | Preserve raw status |
| Cancellation | delivery.payload.failed or cancellation metadata |
Attempt stopped |
21. Evidence Grading Rules
21.1 Pingen Letter Accepted
event_type: delivery.payload.accepted
evidence_grade:
strength: weak
actor_certainty: none
authority_certainty: none
payload_certainty: medium
interaction_certainty: none
timing_certainty: medium
channel_certainty: medium
non_repudiation_strength: low
notes:
- Pingen accepted the letter or file into the API workflow.
- This does not prove validation, sending, postal handover, or delivery.
21.2 Pingen Validation Passed
event_type: payload.validation_passed
evidence_grade:
strength: medium
actor_certainty: none
authority_certainty: none
payload_certainty: high
interaction_certainty: none
timing_certainty: high
channel_certainty: high
non_repudiation_strength: low
notes:
- Pingen validation passed.
- The letter can proceed to sending according to provider rules.
21.3 Pingen Letter Issue / Validation Failed
event_type: payload.validation_failed
evidence_grade:
strength: negative
actor_certainty: none
authority_certainty: none
payload_certainty: high
interaction_certainty: none
timing_certainty: high
channel_certainty: high
non_repudiation_strength: low
notes:
- Pingen reported a letter issue or validation failure.
- The issue should be categorized and preserved.
21.4 Pingen Sent-Letter Event
event_type: delivery.postal.handed_over
evidence_grade:
strength: strong
actor_certainty: none
authority_certainty: none
payload_certainty: high
interaction_certainty: none
timing_certainty: high
channel_certainty: high
non_repudiation_strength: medium
notes:
- Pingen reports the letter as sent or handed into the postal process.
- This is strong dispatch evidence.
- It does not prove that the recipient received or read the letter.
If the native status only means “submitted for sending” and not postal handover, the adapter MUST instead map to:
delivery.payload.submitted
21.5 Pingen Delivered-Letter Event
event_type: delivery.postal.delivery_confirmed
evidence_grade:
strength: strong
actor_certainty: low
authority_certainty: none
payload_certainty: high
interaction_certainty: low
timing_certainty: high
channel_certainty: high
non_repudiation_strength: medium
notes:
- Pingen reports delivered-letter evidence.
- This event is product- and status-dependent.
- It may still not prove that the intended human personally read the payload.
21.6 Pingen Undeliverable / Return Mail
event_type: delivery.postal.return_received
evidence_grade:
strength: negative
actor_certainty: none
authority_certainty: none
payload_certainty: high
interaction_certainty: none
timing_certainty: high
channel_certainty: high
non_repudiation_strength: medium
notes:
- Pingen reports undeliverable or return-mail processing.
- This is strong negative evidence for the physical delivery attempt.
22. Pingen Evidence Assessment
The Pingen flavor SHOULD provide a Pingen-native evidence assessment.
PingenEvidenceAssessment:
hybridmail_letter_id: string
pingen_letter_id: string?
participant_id: string?
category: success | fail | undef
subclass: string
confidence: low | medium | high
strongest_signal: string?
evidence_summary:
- string
recommended_coordination_interpretation: string?
22.1 Pingen Adapter Success Subclasses
success.letter_created
success.validation_passed
success.ready_for_sending
success.submitted_for_sending
success.sent_letter
success.handed_to_postal_service
success.delivery_confirmed
success.return_info_processed
22.2 Pingen Adapter Fail Subclasses
fail.upload_rejected
fail.validation_failed
fail.letter_issue
fail.address_position_invalid
fail.address_invalid
fail.unsupported_file_type
fail.unsupported_country
fail.product_invalid
fail.send_limit_exceeded
fail.provider_rejected
fail.cancelled
fail.undeliverable
fail.return_received
22.3 Pingen Adapter Undef Subclasses
undef.pending
undef.uploaded_only
undef.validation_pending
undef.action_required
undef.ready_but_not_sent
undef.auto_send_pending
undef.submitted_for_sending
undef.processing
undef.sent_but_delivery_unproven
undef.handed_to_postal_service_but_delivery_unproven
undef.track_and_trace_pending
undef.return_mail_pending
undef.no_final_status_expected
undef.delivered_status_semantics_unclear
undef.conflicting_evidence
undef.channel_degraded
23. Pingen Workflow States
The Pingen flavor SHOULD support these normalized workflow states:
created
upload_requested
uploaded
upload_failed
validation_pending
validation_passed
validation_failed
action_required
ready_for_sending
auto_send_pending
send_requested
submitted_for_sending
processing
sent
handed_to_postal_service
delivery_confirmed
undeliverable
return_received
cancelled
failed
unknown
These are Pingen-flavor states, not coordination result states.
24. Pingen Idempotency and Duplicate Send Prevention
Pingen publicly supports Idempotency-Key headers. The Pingen flavor MUST use them for externally visible create/send operations where supported.
The adapter MUST also maintain local idempotency records to prevent duplicate physical sends.
Idempotency scope SHOULD include:
coordination_case_id
participant_id
delivery_id
payload_id
payload_integrity_hash
provider_flavor
postal recipient
letter options
auto_send flag
A repeated delivery.submit_letter request with the same idempotency key MUST NOT create a second physical send.
If the repeated request refers to a changed payload, address, auto-send setting, or delivery product, the adapter MUST reject it as an idempotency conflict unless a new idempotency key is provided.
25. Pingen Rate Limits and Send Limits
Pingen publicly advertises rate limiting and configurable send limits.
The adapter SHOULD model rate-limit and send-limit events.
PingenLimitState:
provider_account_ref: string?
rate_limit_status: available | limited | exhausted | unknown
send_limit_status: available | limited | exhausted | unknown
reset_at: timestamp?
metadata: object?
Relevant events:
system.provider.degraded
delivery.payload.rejected
If a send limit blocks dispatch, the adapter SHOULD classify the letter as:
undef.pending
if retry/continuation is expected, or:
fail.provider_rejected
if the provider rejects the request as final.
26. Pingen Webhook Handling
The Pingen flavor SHOULD prefer webhooks for status changes where available and use polling as a fallback.
Webhook handling MUST:
- verify authenticity where supported.
- deduplicate events.
- preserve raw payload references.
- map categories conservatively.
- accept late return-mail events.
- emit per-letter evidence events.
- avoid treating webhook delivery to the adapter as postal delivery to the recipient.
PingenWebhookHandling:
enabled: boolean
verification_mode: signature | shared_secret | ip_allowlist | none | unknown
subscribed_categories:
- letter_issue
- sent_letter
- undeliverable_letter
- delivered_letter
fallback_polling_enabled: boolean
27. Pingen Status Polling
The Pingen flavor MUST support polling if the API exposes status retrieval.
PingenStatusPollingConfig:
enabled: boolean
initial_delay_seconds: integer
interval_seconds: integer
max_duration_seconds: integer
terminal_statuses:
- delivered
- undeliverable
- returned
- failed
- cancelled
no_final_status_expected_after_seconds: integer?
Polling MUST preserve status history and MUST NOT overwrite raw evidence.
28. Pingen Raw Event Preservation
The Pingen flavor SHOULD preserve raw provider responses or references to them.
RawPingenEventRef:
raw_event_id: string
source: api_response | status_poll | webhook | track_and_trace | validation | operator
endpoint: string?
storage_ref: string?
received_at: timestamp
redacted: boolean
Normalized events SHOULD reference raw Pingen event data where available.
29. Pingen Channel Health
PingenChannelHealth:
provider_name: pingen
provider_account_ref: string?
status: healthy | degraded | failing | unknown
authentication_status: valid | expired | missing | insufficient | unknown
api_status: healthy | degraded | unavailable | unknown
upload_status: healthy | degraded | unavailable | unknown
validation_status: healthy | degraded | unavailable | unknown
track_and_trace_status: healthy | degraded | unavailable | unknown
webhook_status: healthy | degraded | unavailable | not_configured | unknown
rate_limit_status: available | limited | exhausted | unknown
send_limit_status: available | limited | exhausted | unknown
staging_status: healthy | degraded | unavailable | not_configured | unknown
known_degradations:
- string
Health events SHOULD map to:
system.provider.degraded
system.provider.unavailable
system.adapter.health_changed
30. Security Requirements
The Pingen flavor MUST:
- protect Pingen API credentials.
- use secure transport.
- use provider Idempotency-Key support where available.
- maintain local idempotency records.
- avoid duplicate physical sends.
- verify webhooks where supported.
- avoid logging document contents.
- protect postal recipient data.
- protect return-mail details.
- separate staging/sandbox and production configuration.
- support tenant/account separation where applicable.
31. Privacy Requirements
The Pingen flavor SHOULD:
- store payload references instead of payload content where possible.
- support metadata-only mode after provider submission.
- mask postal address data in logs.
- support configurable retention of raw provider responses.
- support configurable retention of return-mail details.
- separate operational diagnostics from coordination evidence.
- document provider-side retention limitations.
- support deletion or anonymization workflows where legally possible.
32. Reliability Requirements
The Pingen flavor MUST support:
- idempotent create/send requests.
- duplicate webhook event detection.
- out-of-order status handling.
- polling-based status recovery.
- late return-mail events.
- late delivered-letter events.
- retryable upload failures.
- non-retryable validation failures.
- provider timeout handling.
- validation issue preservation.
- rate-limit handling.
- send-limit handling.
- Track & Trace history preservation.
- correlation preservation.
- dead-letter handling for unprocessable provider responses.
33. Minimal API Surface
The Pingen flavor SHOULD implement or expose these conceptual operations through hybridmail-connect.
33.1 Adapter Contract Operations
GET /adapter/descriptor
GET /adapter/health
POST /adapter/actions
POST /adapter/events/provider
GET /adapter/events
GET /adapter/letters/{id}/timeline
GET /adapter/letters/{id}/assessment
33.2 Pingen Flavor Operations
POST /pingen/letters
POST /pingen/letters/{id}/send
POST /pingen/letters/{id}/cancel
GET /pingen/letters/{id}
GET /pingen/letters/{id}/status
GET /pingen/letters/{id}/track-and-trace
GET /pingen/letters/{id}/return-info
GET /pingen/letters/{id}/delivery-confirmation
GET /pingen/letters/{id}/timeline
GET /pingen/letters/{id}/assessment
POST /pingen/webhooks
GET /pingen/channel-health
The exact provider endpoint names MUST be implemented according to the live Pingen API documentation. The conceptual operations above define the adapter-facing semantic model.
34. Example End-to-End Flow
34.1 Single Pingen Letter with Manual Send
coordination-enginecreates a coordination case.- A PDF payload is registered.
- Policy selects
hybridmail-connectwith provider flavorpingen. coordination-enginesendsdelivery.submit_letter.hybridmail-connectcreates a Pingen letter withauto_send=false.- Pingen accepts the letter.
- The adapter emits
delivery.payload.accepted. - Pingen validates the letter.
- If validation passes, the adapter emits
payload.validation_passed. - Policy approves sending.
- The adapter sends or submits the letter.
- The adapter emits
delivery.payload.submitted. - Pingen Track & Trace reports sent-letter progress.
- The adapter emits
delivery.postal.handed_overonly if the native event semantics support physical dispatch/handover. coordination-engineevaluates whether dispatch evidence is sufficient for the case policy.
34.2 Auto-Send Letter
coordination-enginesubmits a letter withauto_send=true.- The adapter validates idempotency and payload identity.
- Pingen accepts the request.
- Validation and send may proceed without separate manual approval.
- The adapter emits distinct events for validation and send stages as they become observable.
- If validation fails, the adapter emits
payload.validation_failed. - If sending proceeds, the adapter emits
delivery.payload.submittedand later stronger status events.
34.3 Pingen Letter Issue
- Pingen reports a letter issue through webhook or status polling.
- The adapter classifies the issue.
- The adapter emits
payload.validation_failedordelivery.payload.rejected. coordination-enginemarks the participant attempt as action-required or failed.- Policy requests correction, alternate document generation, or fallback.
34.4 Undeliverable / Return Mail
- A letter was sent.
- Pingen later reports it as undeliverable or return mail is processed.
- The adapter emits
delivery.postal.undeliverableordelivery.postal.return_received. coordination-engineupdates the participant delivery assessment.- Policy may trigger address correction, alternate channel, or manual review.
34.5 Delivered-Letter Product
- A letter is sent using a delivery-confirmation-capable product.
- Pingen reports delivered-letter evidence.
- The adapter confirms the product/status semantics.
- The adapter emits
delivery.postal.delivery_confirmed. coordination-engineevaluates whether this satisfies the intended result.
35. Pingen MVP Scope
The first Pingen flavor implementation should include:
- Pingen provider flavor descriptor.
- Adapter descriptor integration.
- Pingen credential/config handling.
- Letter creation or upload.
- Auto-send flag support.
- Address-position option mapping.
- Validation result mapping.
- Sending submission.
- Track & Trace status polling.
- Webhook ingestion for supported categories.
- Return-mail / undeliverable event mapping.
- Delivered-letter event mapping, product-dependent.
- Evidence event generation.
- Letter timeline.
- Pingen evidence assessment.
- Provider idempotency header usage.
- Local idempotency protection.
MVP Required Pingen Events
delivery.payload.accepted
delivery.payload.rejected
payload.validation_passed
payload.validation_failed
delivery.payload.available
delivery.payload.submitted
delivery.production.started
delivery.postal.handed_over
delivery.postal.delivery_confirmed
delivery.postal.undeliverable
delivery.postal.return_received
delivery.postal.status_unknown
system.provider.degraded
system.provider.unavailable
Where a provider status is unavailable or semantically unclear, the adapter MUST emit the weakest safe event and preserve the raw status.
36. Pingen MVP Acceptance Criteria
The Pingen flavor MVP is acceptable when it can:
- Accept a coordination-compatible
delivery.submit_letterrequest. - Create or simulate a Pingen letter.
- Preserve correlation and idempotency.
- Use Pingen Idempotency-Key support where available.
- Prevent duplicate physical sends for duplicate idempotency keys.
- Support auto-send configuration.
- Map validation success to
payload.validation_passed. - Map letter issues or validation failure to
payload.validation_failed. - Map send submission to
delivery.payload.submitted. - Map sent-letter evidence conservatively.
- Map delivered-letter evidence only when provider/product semantics support delivery confirmation.
- Map undeliverable/return-mail evidence to strong negative delivery evidence.
- Provide a Pingen letter timeline.
- Provide a Pingen evidence assessment.
- Integrate with
coordination-enginewithout overclaiming physical delivery or human awareness.
37. Open Questions
- Which exact Pingen native statuses map to
delivery.production.started,delivery.postal.handed_over, anddelivery.postal.delivery_confirmed? - Which event payload fields are present for Pingen webhook categories in the target API version?
- How does the target Pingen account expose delivery-confirmation products?
- Which return-mail details are available through API versus email/webhook?
- Does the implementation need organization/workspace selection before letter creation?
- Which Pingen country/product combinations are enabled for the target account?
- How should configurable send limits be surfaced to coordination-engine policy?
- How should staging/full-feature simulation be represented in evidence grades?
- Which address-position values are available in the live API?
- Should Pingen return details update a shared postal address quality registry?
38. Non-Goals
The Pingen flavor is not:
- a document authoring system.
- a PDF renderer by default.
- a legal notice system by itself.
- a postal carrier.
- a general Pingen UI replacement.
- the owner of coordination case success.
- the owner of contract, payment, or signature result semantics.
It integrates Pingen hybrid-mail capabilities into the coordination framework.
39. Summary
HybridmailPingenSpecification.md defines the Pingen provider flavor for hybridmail-connect.
The Pingen flavor models Pingen as a letter-centric hybrid-mail provider with:
- letter/file creation
- validation
- configurable address position
- auto-send/manual-send control
- Track & Trace
- webhook status categories
- sent-letter evidence
- delivered-letter evidence where product-supported
- undeliverable and return-mail evidence
- idempotency and rate-limit support
- staging/simulation support
The key rule is:
Pingen events are provider, production, postal-chain, Track & Trace, and return-mail evidence. They are not automatic coordination result satisfaction. hybridmail-connect reports Pingen-channel facts and uncertainty. coordination-engine evaluates intended results.