Files
coordination-engine/spec/HybridmailPingenSpecification.md

39 KiB
Raw Blame History

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 Pingens 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

  1. coordination-engine creates a coordination case.
  2. A PDF payload is registered.
  3. Policy selects hybridmail-connect with provider flavor pingen.
  4. coordination-engine sends delivery.submit_letter.
  5. hybridmail-connect creates a Pingen letter with auto_send=false.
  6. Pingen accepts the letter.
  7. The adapter emits delivery.payload.accepted.
  8. Pingen validates the letter.
  9. If validation passes, the adapter emits payload.validation_passed.
  10. Policy approves sending.
  11. The adapter sends or submits the letter.
  12. The adapter emits delivery.payload.submitted.
  13. Pingen Track & Trace reports sent-letter progress.
  14. The adapter emits delivery.postal.handed_over only if the native event semantics support physical dispatch/handover.
  15. coordination-engine evaluates whether dispatch evidence is sufficient for the case policy.

34.2 Auto-Send Letter

  1. coordination-engine submits a letter with auto_send=true.
  2. The adapter validates idempotency and payload identity.
  3. Pingen accepts the request.
  4. Validation and send may proceed without separate manual approval.
  5. The adapter emits distinct events for validation and send stages as they become observable.
  6. If validation fails, the adapter emits payload.validation_failed.
  7. If sending proceeds, the adapter emits delivery.payload.submitted and later stronger status events.

34.3 Pingen Letter Issue

  1. Pingen reports a letter issue through webhook or status polling.
  2. The adapter classifies the issue.
  3. The adapter emits payload.validation_failed or delivery.payload.rejected.
  4. coordination-engine marks the participant attempt as action-required or failed.
  5. Policy requests correction, alternate document generation, or fallback.

34.4 Undeliverable / Return Mail

  1. A letter was sent.
  2. Pingen later reports it as undeliverable or return mail is processed.
  3. The adapter emits delivery.postal.undeliverable or delivery.postal.return_received.
  4. coordination-engine updates the participant delivery assessment.
  5. Policy may trigger address correction, alternate channel, or manual review.

34.5 Delivered-Letter Product

  1. A letter is sent using a delivery-confirmation-capable product.
  2. Pingen reports delivered-letter evidence.
  3. The adapter confirms the product/status semantics.
  4. The adapter emits delivery.postal.delivery_confirmed.
  5. coordination-engine evaluates whether this satisfies the intended result.

35. Pingen MVP Scope

The first Pingen flavor implementation should include:

  1. Pingen provider flavor descriptor.
  2. Adapter descriptor integration.
  3. Pingen credential/config handling.
  4. Letter creation or upload.
  5. Auto-send flag support.
  6. Address-position option mapping.
  7. Validation result mapping.
  8. Sending submission.
  9. Track & Trace status polling.
  10. Webhook ingestion for supported categories.
  11. Return-mail / undeliverable event mapping.
  12. Delivered-letter event mapping, product-dependent.
  13. Evidence event generation.
  14. Letter timeline.
  15. Pingen evidence assessment.
  16. Provider idempotency header usage.
  17. 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:

  1. Accept a coordination-compatible delivery.submit_letter request.
  2. Create or simulate a Pingen letter.
  3. Preserve correlation and idempotency.
  4. Use Pingen Idempotency-Key support where available.
  5. Prevent duplicate physical sends for duplicate idempotency keys.
  6. Support auto-send configuration.
  7. Map validation success to payload.validation_passed.
  8. Map letter issues or validation failure to payload.validation_failed.
  9. Map send submission to delivery.payload.submitted.
  10. Map sent-letter evidence conservatively.
  11. Map delivered-letter evidence only when provider/product semantics support delivery confirmation.
  12. Map undeliverable/return-mail evidence to strong negative delivery evidence.
  13. Provide a Pingen letter timeline.
  14. Provide a Pingen evidence assessment.
  15. Integrate with coordination-engine without overclaiming physical delivery or human awareness.

37. Open Questions

  1. Which exact Pingen native statuses map to delivery.production.started, delivery.postal.handed_over, and delivery.postal.delivery_confirmed?
  2. Which event payload fields are present for Pingen webhook categories in the target API version?
  3. How does the target Pingen account expose delivery-confirmation products?
  4. Which return-mail details are available through API versus email/webhook?
  5. Does the implementation need organization/workspace selection before letter creation?
  6. Which Pingen country/product combinations are enabled for the target account?
  7. How should configurable send limits be surfaced to coordination-engine policy?
  8. How should staging/full-feature simulation be represented in evidence grades?
  9. Which address-position values are available in the live API?
  10. 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.