{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["tabs","tab","admonition","json-schema"]},"type":"markdown"},"seo":{"title":"Delivery","description":"Developer documentation for integrating systems that send messages, plus reporting and operational APIs for platform holders."},"dynamicMarkdocComponents":["openapi"],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"delivery","__idx":0},"children":["Delivery"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A delivery consists of one or more envelopes. An envelope is a JSON file that specifies what content"," ","must be delivered to which recipients, furthermore the envelope can specify how the recipients can"," ","interact with the message that will be placed in their mailbox."]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["It is guaranteed that all the recipients on the envelope receive the message or none of them do."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When the Digital Post Platform (DPP) receives a delivery request, it will:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Process each of the envelopes in the S3 bucket, this involves:",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Validating that the envelope conforms to the"," ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/assets/envelope-schema_1.0.2.6db0c2fce8721fa4233908d680497214b3c47a500e07f317ee6d23d7f5cd31c4.de6e0f62.json"},"children":["Envelope schema"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensuring that the referenced message body and attachments are present in the S3 bucket."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Copying of the message body and attachments to the DPP's server, from where they will be served"," ","to the recipients. During this copy each unique body or attachment is encrypted with a unique"," ","key that will only be available to the recipients."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["As envelopes are validated and the content they reference is copied, each of the envelopes goes through the delivery process that involves:",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Checking that the Sender is allowed to use the utilized ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#message-features"},"children":["message features"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Identification of the recipients and their mailboxes."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Checking that the recipients are all subscribed to the Sender."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensuring the virus scanner clears the message's content."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Preparing a message to become available to all its recipients at the same time."]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"encryption-during-delivery","__idx":1},"children":["Encryption during delivery"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In addition to the at-rest encryption that may be provided by your chosen S3 service, the objects may be"," ","encrypted before uploading them to the S3 bucket and the encryption key passed on with the delivery"," ","request. The Digital Post Platform (DPP) will then decrypt the content for processing and encrypt"," ","each with a unique key only the recipients can access."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The content must be encrypted using AES 256. The DPP supports using either"," ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://knowledge.complexsecurity.io/cryptography/cbc/"},"children":["CBC"]}," or"," ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://knowledge.complexsecurity.io/cryptography/gcm/"},"children":["GCM"]}," mode, the"," ","latter being the preferred mode. Note, if using CBC then the DPP will not be able to detect"," ","decryption failures, e.g. due to incorrect encryption key or corrupted data. So in this case"," ","it is important to specify a hash for the content in the envelopes, so the DPP will be able to"," ","detect that the cleartext content is not the expected content. Regardless of the encryption mode -"," ","or encryption at all - it is always a good practice to specify the cleartext content hash in the"," ","envelopes."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"GCM encryption and encoding","disable":false},"children":[{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Not supported yet"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Support for using GCM mode is currently not supported by the DPP."," ","Support is planned to be released in the near term."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Data encryption using AES-256 in GCM mode must be encoded in chunks of a maximum of 1 MB."," ","A total of 20 chunks may be used, limiting the encrypted data to approximately 20 MB."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Encoding:"]}," ",{"$$mdtype":"Tag","name":"img","attributes":{"src":"/assets/aes-gcm-enc.d36f40d016b913213136f3f7f2ce5bfa048d24373f9b634bc74c5cd0d0b011ec.9c1bb791.png","alt":"Layout of a file encrypted using AES GCM","title":"AES GCM encrypted file"},"children":[]}]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Encryption Indicator:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The first byte must be set to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["2"]}," to indicate that the data is AES-256 GCM encrypted."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Chunked Encryption:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Data must be divided into chunks, each a maximum of 1 MB."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Each chunk must have the following structure:",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Chunk Size (4 bytes):"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The first 4 bytes of each chunk contain an integer representing the total chunk"," ","size in bytes, including the nonce, encrypted data, and authentication tag."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Nonce (12 bytes):"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The next 12 bytes must store a unique nonce for each chunk."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensure that the nonce is unique per chunk to maintain data integrity and security."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Encrypted Data:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Following the nonce, the chunk contains the encrypted data."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Authentication Tag (16 bytes):"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The last 16 bytes of each chunk must be the AES-GCM authentication tag for that"," ","specific chunk."]}]}]}]}]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Total Size Limit:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["A maximum of 20 chunks is permitted, with each chunk being no larger than 1 MB."," ","This limits the total encoded data size to approximately 20 MB."]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/tutorials/gcm-encryption-and-encoding"},"children":["Encrypting data using AES256 GCM and encoding for DPP"]}," for a reference implementation."]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"CBC encryption and encoding","disable":false},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Encoding:"]}," ",{"$$mdtype":"Tag","name":"img","attributes":{"src":"/assets/aes-cbc-enc.a6f83331843e149e96929a76af0767fc8e458f29fe595af9b2ed63d176ef8310.9c1bb791.png","alt":"Layout of a file encrypted using AES CBC","title":"AES CBC encrypted file"},"children":[]}]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Encryption Indicator:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The first byte must be set to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["1"]}," to indicate that the data is AES-256 CBC encrypted."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Initialization Vector (IV):"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The next 16 bytes must contain a unique initialization vector (IV) for each encryption,"," ","specific to the encryption key in use."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensure that the IV is unique with respect to the encryption key to maintain security."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Encrypted Data:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Following the IV, the remaining data consists of the AES-256 CBC encrypted content."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The total encrypted data (including the IV) must not exceed 20 MB."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Data Integrity Consideration:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Note:"]}," CBC mode does not include any data integrity checks. This means:",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Corruption in the encrypted data or an incorrect/corrupted key passed to the DPP"," ","will not be detected."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["If the data is corrupted, recipients will be unable to read the message or certain"," ","parts of it."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Recommendation:"]}," For improved security and data integrity, AES-GCM mode is preferred"," ","over CBC for encryption."]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/tutorials/cbc-encryption-and-encoding"},"children":["Encrypting data using AES256 CBC and encoding for DPP"]}," for a reference implementation."]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"message-features","__idx":2},"children":["Message features"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"interim-repository","__idx":3},"children":["Interim repository"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If a recipient does not have an account on the platform, any delivery to that recipient will normally be rejected. However, the recipient can explicitly be marked to have the platform place their message in the interim repository instead."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To enable interim storage for a recipient, set ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["interim.enable"]}," to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]},". If you also specify ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["interim.notificationEmail"]},", the platform will send an email to that address, notifying the recipient that a message is waiting and guiding them through the process of creating an account to access it. The ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/documentation/message-envelope#envelope-schema"},"children":["envelope schema can be found here"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Once the recipient creates an account, messages stored in the interim repository will be delivered"," ","shortly thereafter."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Messages that remain in the interim repository will be purged after a retention period."," ","Contact your solution administrator to learn the applicable retention period."]},{"$$mdtype":"Tag","name":"JsonSchema","attributes":{"schema":{"title":"Envelope recipients","type":"array","items":{"$ref":"../static/envelope-schema_1.0.2.yaml#/$defs/userRecipient"}},"options":{},"schemaResolved":{"openapi":"3.1.0","components":{"schemas":{"__root":{"title":"Envelope recipients","type":"array","items":{"$ref":"#/components/schemas/userRecipient"}},"email":{"type":"string","format":"email"},"interim":{"description":"Configuration for interim message handling when a recipient does not have an active mailbox.","type":"object","required":["enable"],"additionalProperties":false,"properties":{"enable":{"description":"Indicates whether interim messaging is enabled for this recipient.","type":"boolean"},"notificationEmail":{"description":"Email address to notify when a message is placed in the interim repository.","$ref":"#/components/schemas/email"}}},"userRecipient":{"description":"Represents a recipient of the message.","type":"object","required":["identity"],"additionalProperties":false,"properties":{"identity":{"description":"Key-value identity attributes used to resolve the recipient. Exactly one key-value pair is required.","type":"object","minProperties":1,"maxProperties":1,"propertyNames":{"type":"string","minLength":1,"maxLength":50,"pattern":"^[a-zA-Z0-9/\\._-]{1,30}$"},"additionalProperties":{"type":"string","minLength":1}},"interim":{"description":"Interim message handling configuration for this recipient.","$ref":"#/components/schemas/interim"}}}}}},"schemaResolvedErrors":[]},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"multiple-recipients","__idx":4},"children":["Multiple recipients"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["An envelope with multiple recipients will be delivered to all the recipients or none of them."," ","E.g. if one of the recipients is not subscribed or does not have an account (and interim repository"," ","is not enabled) then the envelope will not be delivered to any of the recipients. A maximum of 10 recipients would be allowed in an envelope."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"scheduled-delivery","__idx":5},"children":["Scheduled delivery"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A delivery time can be set on an envelope, which will postpone the delivery to the recipients until"," ","the specified time."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["See the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/documentation/message-envelope#envelope-schema"},"children":["envelope schema"]}," for the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["deliverAt"]}," field."]},{"$$mdtype":"Tag","name":"JsonSchema","attributes":{"schema":{"title":"Envelope recipients","type":"object","properties":{"deliverAt":{"$ref":"../static/envelope-schema_1.0.2.yaml#/properties/deliverAt"}}},"options":{},"schemaResolved":{"openapi":"3.1.0","components":{"schemas":{"__root":{"title":"Envelope recipients","type":"object","properties":{"deliverAt":{"$ref":"#/components/schemas/deliverAt"}}},"datetime":{"description":"RFC 3339 date-time string.","type":"string","format":"date-time"},"deliverAt":{"description":"Scheduled delivery timestamp in RFC 3339 format. The message is processed immediately, but delivery is deferred until this time.","$ref":"#/components/schemas/datetime"}}}},"schemaResolvedErrors":[]},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"open-receipt","__idx":6},"children":["Open receipt"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["An open receipt can be required to be registered before the recipient can access the body or"," ","attachments."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Open receipt limited to single-recipient envelopes"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If open receipt is required, then the envelope may only have 1 recipient."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Receipts can be accessed in the Digital Post Platform's administration portal."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["See the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/documentation/message-envelope#envelope-schema"},"children":["envelope schema"]}," for the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["requireOpenReceipt"]}," field."]},{"$$mdtype":"Tag","name":"JsonSchema","attributes":{"schema":{"title":"Envelope recipients","type":"object","properties":{"requireOpenReceipt":{"$ref":"../static/envelope-schema_1.0.2.yaml#/properties/requireOpenReceipt"}}},"options":{},"schemaResolved":{"openapi":"3.1.0","components":{"schemas":{"__root":{"title":"Envelope recipients","type":"object","properties":{"requireOpenReceipt":{"$ref":"#/components/schemas/requireOpenReceipt"}}},"requireOpenReceipt":{"description":"If true, an open receipt must be registered before the recipient can access the message content. Only supported for single recipient envelopes.","type":"boolean","default":false}}}},"schemaResolvedErrors":[]},"children":[]}]},"headings":[{"value":"Delivery","id":"delivery","depth":1},{"value":"Encryption during delivery","id":"encryption-during-delivery","depth":2},{"value":"Message features","id":"message-features","depth":2},{"value":"Interim repository","id":"interim-repository","depth":3},{"value":"Multiple recipients","id":"multiple-recipients","depth":3},{"value":"Scheduled delivery","id":"scheduled-delivery","depth":3},{"value":"Open receipt","id":"open-receipt","depth":3}],"frontmatter":{"markdown":{"toc":{"depth":3}},"seo":{"title":"Delivery"}},"lastModified":"2026-05-19T07:20:06.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/documentation/delivery","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}