Skip to main content

Secure Exchanges Python SDK

English | Français

Python SDK for the Secure Exchanges API: secure file transfer, end-to-end encrypted messaging, and digital signing of PDF documents.

The SDK covers the entire protocol: post-quantum handshake, end-to-end encryption of messages and files, electronic signatures with PKI certification, and message logs.


Table of contents

  1. Installation
  2. Prerequisites
  3. Credentials and configuration
  4. Security
  5. SDK architecture
  6. Usage guide
  7. API reference
  8. Data models
  9. Support
  10. License

Installation

pip install secure-exchanges-sdk

This installs everything needed for sending messages, attachments, logs, and phone number validation.

Electronic signature on PDF (signature extra)

Defining signature zones (ZoneBuilder) and PDF certification (PkiFileHelper) require two additional dependencies, pypdf and playwright, deliberately not installed by default: playwright downloads a browser of roughly 150 MB:

pip install "secure-exchanges-sdk[signature]"
playwright install chromium

Prerequisites

To use the SDK, you need:

  • Python 3.10+
  • A serial number (serial) : the UUID of your licence
  • An API user ID (api_user) : the UUID of the API user
  • An API password (api_password) : the UUID of the API password

Credentials and configuration

Where to find your credentials

The 3 required credentials (serial, api_user, api_password) are UUIDs (GUIDs) that you obtain from your Secure Exchanges administration portal when creating your API licence.

Credential Description Example
serial Serial number of your licence UUID("d17ca972-5f70-4961-bac4-98e6b91b1dc4")
api_user API user identifier UUID("0fa0cf77-4ca5-4406-8623-1ed0ffd47290")
api_password API user password UUID("4bfeabdf-c498-448a-9255-1e17c3ef8c0b")

Configuration

SettingsHelper selects the environment and returns its endpoints, nothing else. The SDK stores no credentials and never reads them from the process environment: the serial, the API user and the API password are yours, and are passed explicitly to every call.

from secure_exchanges_sdk.client import SecureExchangesClient, SEMSClient
from secure_exchanges_sdk.helpers.settings_helper import SettingsHelper

cfg = SettingsHelper.configure_production()

client      = SecureExchangesClient(cfg['api_endpoint'])
sems_client = SEMSClient(cfg['sems_endpoint'])

# load_my_credentials() is your own function: it returns the three UUID objects
# of your licence (uuid.UUID, not str). See "Protecting your credentials"
# below for where to keep them.
serial, api_user, api_password = load_my_credentials()
Function Environment Endpoints
configure_production() production www.secure-exchanges.com
configure_preview() preview (test) preview.secure-exchanges.com

Each one returns a dict with api_endpoint, sems_endpoint, file_handler, file_upload_handler and environment.

Preview and production credentials are different: a production serial will not work in preview, and vice versa.

Protecting your credentials

These three UUIDs are the equivalent of a password on your Secure Exchanges account: whoever holds them can send, read and delete messages in your name, and the usage is billed to you. How they are stored is entirely your decision, and your responsibility.

  • Never commit them. Keep them out of the repository, and check the history too: git log -S <serial> finds a secret committed once and removed later. A secret that reached a remote is compromised: rotate it, don't just delete the line.
  • Never hard-code them in source. They end up in stack traces, in bug reports, in the packages you ship, and in every fork of the code.
  • Prefer a secret manager. Encrypted at rest, access audited, rotation possible without a redeploy.
  • If you keep them in a file, encrypt it or lock it down. Outside the web root, owned by the service account, permissions 0400, and excluded from your backups or encrypted inside them.
  • Beware of the process environment. Environment variables are readable from /proc/<pid>/environ by anything running under the same user, they show up in crash dumps and in most error reporters. Load the credentials at the moment you need them rather than exporting them for the whole process lifetime.
  • Keep them out of your logs. Exclude them explicitly from your error handler, from your crash reporter and from request dumps, which capture environment and local variables by default.
  • Rotate them from the administration portal the moment you suspect an exposure: a laptop lost, a log shipped to a third party, a developer leaving.

Security

  • End-to-end encryption: the content (message body and files) is encrypted locally, with keys generated on your machine and never sent to the server: the server only stores and relays encrypted data.
  • Post-quantum key exchange: ML-KEM-1024 (FIPS 203), resistant to quantum computer attacks, signed with ML-DSA-87 (FIPS 204).
  • AES-256 encryption of the content and of all exchanges with the server.
  • Interception protection: any man-in-the-middle (MITM) attack attempt causes the connection to fail.
  • Nothing to manage: the SDK automatically applies the entire protocol on every call: you never have to handle any cryptographic primitives.

SDK architecture

Overview of the main modules. In practice, you will mostly use the helpers, which orchestrate the full protocol for you:

Module Role
client/ HTTP clients: SecureExchangesClient (main API), SEMSClient (email delivery)
helpers/message_helper.py Sending, reading, deleting messages, reply envelopes
helpers/handshake_helper.py Post-quantum handshake (ML-KEM-1024 + ML-DSA-87)
helpers/post_quantum_crypto_helper.py Post-quantum primitives for the handshake
helpers/crypto_helper.py Low-level symmetric/RSA cryptography (AES-256, SHA-512, .NET GUIDs)
helpers/logs_helper.py Retrieval of message logs
helpers/sign_helper.py, helpers/zone_builder.py Electronic signature zones on PDF
helpers/pki_file_helper.py PKI certification of PDFs (headless browser)
helpers/file_helper.py Encrypted file upload/download (chunked, parallel)
helpers/settings_helper.py Configuration (environments, endpoints)
helpers/contact_helper.py, licence_helper.py Contacts, licence validation
helpers/email_helper.py, phone_helper.py, mime_helper.py Validations (email, phone, MIME types)
models/ Data models: responses (answer/), entities (entity/), enumerations (enum/), transport, JSON
callback/ Models for notification callbacks

Usage guide

All the examples below assume the following setup (see Configuration):

from secure_exchanges_sdk.client import SecureExchangesClient, SEMSClient
from secure_exchanges_sdk.helpers.settings_helper import SettingsHelper

cfg = SettingsHelper.configure_production()

client      = SecureExchangesClient(cfg['api_endpoint'])
sems_client = SEMSClient(cfg['sems_endpoint'])

# Your own function: it returns the three UUID objects of your licence.
serial, api_user, api_password = load_my_credentials()

Sending a simple message

from secure_exchanges_sdk.helpers.message_helper import MessageHelper
from secure_exchanges_sdk.models.entity.recipient_info import RecipientInfo

recipients = [
    RecipientInfo(email="recipient@example.com")
]

answer = MessageHelper.multi_recipient_message(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    recipients=recipients,
    message="<p>Hello, here is a secure message.</p>",
    subject="Confidential message",
    culture_id="en-US"
)

if answer.status == 200:
    print("Message sent successfully!")
    for ra in answer.recipients_answer:
        if ra.answer and ra.answer.url:
            print(f"  URL: {ra.answer.url}")
else:
    print(f"Error {answer.status}: {answer.data}")

Sending with password and SMS code (2FA)

from secure_exchanges_sdk.models.enum.send_method_enum import SendMethodEnum

recipients = [
    RecipientInfo(email="user@example.com", phone="+15145551234")
]

answer = MessageHelper.multi_recipient_message(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    recipients=recipients,
    message="<p>Confidential document attached.</p>",
    subject="Protected document",
    password="SecretPassword123",
    send_method=SendMethodEnum.EMAIL_WITH_SMS_CODE,  # link by email, code by SMS
    culture_id="en-US",
    maximum_open_time=3,    # Maximum number of opens (1-99)
    minutes_expiration=1440 # Expiration in minutes (1440 = 24h)
)

SendMethodEnum values:

Value Description
ONLY_EMAIL (0) Link sent by email only (default)
SMS_ONLY (1) Link sent by SMS only
SMS_WITH_EMAIL_CODE (2) Link by SMS, opening code by email
EMAIL_WITH_SMS_CODE (3) Link by email, opening code by SMS

Password protection (password) is independent of the delivery channel and can be combined with any send_method value.

Sending with attachments

# From disk
answer = MessageHelper.multi_recipient_message(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    recipients=recipients,
    message="<p>See attached files.</p>",
    subject="Secure files",
    files_path=["/path/to/document.pdf", "/path/to/image.png"]
)

# From memory (bytes)
pdf_bytes = open("/path/to/report.pdf", "rb").read()
csv_bytes = open("/path/to/data.csv", "rb").read()

files_in_memory = [
    {"binary": pdf_bytes, "file_name": "report.pdf"},
    {"binary": csv_bytes, "file_name": "data.csv"}
]

answer = MessageHelper.multi_recipient_message(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    recipients=recipients,
    message="<p>Report and data attached.</p>",
    subject="Monthly report",
    files_list=files_in_memory
)

Sending with PKI certification

PKI certification applies a digital certificate to a PDF before sending it for signature. The process uses a headless browser (Playwright, signature extra). Signature zones are defined with ZoneBuilder, which reads the actual dimensions of the PDF pages:

import asyncio
from secure_exchanges_sdk.helpers.crypto_helper import CryptoHelper
from secure_exchanges_sdk.helpers.zone_builder import ZoneBuilder
from secure_exchanges_sdk.helpers.sign_helper import SignHelper
from secure_exchanges_sdk.helpers.pki_file_helper import PkiFileHelper, CertifyPdfArgs
from secure_exchanges_sdk.models.entity.sign_zone_definition import SignZoneDefinition
from secure_exchanges_sdk.models.transport.file_zone_definition import FileZoneDefinition
from secure_exchanges_sdk.models.transport.recipient_zone_definition import RecipientZoneDefinition

# 1. Read the PDF and compute its SHA512
pdf_path = "contract.pdf"
with open(pdf_path, "rb") as f:
    pdf_bytes = f.read()
sha512 = CryptoHelper.get_sha512_hash_of_bytes(pdf_bytes)

# 2. Define the signature zones with ZoneBuilder
with ZoneBuilder(pdf_path, is_pki=True) as zone_builder:
    zones = [
        # Signature zone on page 1
        zone_builder.create_field_sign_zone(
            page=1, field_name="signature1",
            x=60, y=400, width=200, height=50
        ),
        # Date zone filled automatically at signing time
        zone_builder.create_field_date_sign_zone(
            page=1, field_name="date1",
            x=60, y=500, width=100, height=25, font_size=12
        ),
    ]

# 3. Associate the zones with the recipient (file referenced by its SHA512)
recipient_zones = [
    RecipientZoneDefinition(
        email="signer@example.com",
        phone=None,
        zones_def_by_file=[
            FileZoneDefinition(
                unique_name=sha512,
                do_not_encrypt_pdf=False,
                do_not_append_certificate_to_file=False,
                is_pki_file=True,
                zones_def=SignZoneDefinition(mode="define", zones=zones)
            )
        ]
    )
]

# 4. Get the certification token
cert_response = SignHelper.get_certification_token(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    original_hash=sha512,
    culture_id="en-US",
    token_type="CertifyDocument"
)
cert_data = cert_response["certification_data"]

# 5. Certify the PDF via headless browser
certify_args = CertifyPdfArgs(
    file_bytes=pdf_bytes,
    file_name="contract.pdf",
    recipients=["signer@example.com"],
    certify_data=cert_data,
    detect_existing_fields=True,
    recipient_zone_definitions=recipient_zones
)

async def certify():
    async with PkiFileHelper(is_preview=False, culture="en-US") as helper:
        return await helper.certify_pki_pdf(certify_args)

certified = asyncio.run(certify())

# 6. Send the certified PDF
answer = MessageHelper.multi_recipient_message(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    recipients=[RecipientInfo(email="signer@example.com")],
    message="<p>Please sign this certified document.</p>",
    subject="PKI document to sign",
    certified_pdfs=[certified],
    owner_dont_need_to_sign=True,
    sems_client=sems_client
)

A complete, runnable example, including the signature options (SignOptions: signature mode restriction, requesting a file in return) and the callback parameters (contextual keys), can be found in example_pki_with_signature_options.py at the root of pythonSDK/.

Retrieving a message

# Parse a Secure Exchanges link
link = "https://www.secure-exchanges.com/message.aspx?msgid=xxx&sems=yyy&cpart=zzz"
msg_params = MessageHelper.get_secure_exchanges_message_from_link(link)

# Retrieve and decrypt the message
response = MessageHelper.get_message(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    msg_params=msg_params,
    password="MyPassword"     # if protected
)

Note: each read consumes one of the message's allowed opens (maximum_open_time).

Message logs

Track the lifecycle of your messages (sending, opens, signatures):

from datetime import datetime, timedelta
from uuid import UUID
from secure_exchanges_sdk.helpers.logs_helper import LogsHelper

# All logs from the last 60 days
logs_response = LogsHelper.get_logs(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    from_date=datetime.now() - timedelta(days=60),
    to_date=datetime.now()
)

# The log of a specific message (by message_id OR tracking_id)
log_response = LogsHelper.get_log(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    tracking_id=UUID("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
)

Deleting a message

from uuid import UUID

success = MessageHelper.delete_message_by_tracking_id(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    tracking_id=UUID("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
)

Reply envelopes

Envelopes let a recipient reply to you securely:

# Single envelope (one recipient)
env_response = MessageHelper.get_enveloppe(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    subject="Send me your documents",
    destination="recipient@example.com",
    culture_id="en-US",
    reply_expiration_hours=48,
    maximum_reply_open_time=3,
    reply_to_api=True,
    authorized_extensions=[".pdf", ".docx"]
)

if env_response.url:
    print(f"Envelope URL: {env_response.url}")

# Multiple envelopes
env_responses = MessageHelper.get_envelopes(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    subject="Required documents",
    recipients=[
        {"Email": "user1@example.com"},
        {"Email": "user2@example.com"}
    ]
)

API reference

MessageHelper

Static class for sending and receiving messages.

Method Description
multi_recipient_message(api_client, serial, api_user, api_password, recipients, message, subject, ...) Sends a message to multiple recipients
get_message(api_client, serial, api_user, api_password, msg_params, password=None, digit_code=None, sems_client=None) Retrieves and decrypts a message
delete_message_by_tracking_id(api_client, serial, api_user, api_password, tracking_id, ...) Deletes a message by tracking ID
get_enveloppe(api_client, serial, api_user, api_password, subject, destination, ...) Creates a reply envelope
get_envelopes(api_client, serial, api_user, api_password, subject, recipients, ...) Creates multiple envelopes
get_secure_exchanges_message_from_link(link) Parses an SE link into parameters
send_trace(api_client, trace_content) Sends a support trace

Parameters of multi_recipient_message

Parameter Type Default Description
api_client SecureExchangesClient required API client
serial UUID required Serial number
api_user UUID required API user ID
api_password UUID required API password
recipients List[RecipientInfo] required Recipients
message str required HTML content of the message
subject str required Message subject
password str None Protection password
files_list List[dict] None In-memory files ({"binary": bytes, "file_name": str})
files_path List[str] None Paths of files on disk
send_method SendMethodEnum ONLY_EMAIL Delivery channel (see the SendMethodEnum table above)
get_back_html bool True True=you send the email, False=SEMS sends it
show_subject bool True Show the subject in the notification
get_notify bool True Notify on open
culture_id str "en-US" Language ("fr-CA", "en-US")
maximum_open_time int 1 Maximum number of opens (1-99)
minutes_expiration int 10080 Expiration in minutes (default: 7 days)
create_message_copy bool False Copy for the sender
name str "Secure Exchanges" Sender name
callback_parameters str None Free-form parameters (JSON) returned in notification callbacks
reply_options dict None Recipient reply options (see below)
owner_dont_need_to_sign bool True The sender does not sign
certified_pdfs List[CertifiedPdfContainer] None PKI-certified PDFs
sign_options SignOptions None Signature options: mode restriction, CC/BCC recipients, upload options
sems_client SEMSClient None SEMS client (created automatically if omitted)

reply_options is a dictionary (PascalCase keys, matching the API) that controls what the recipient can do in reply:

from secure_exchanges_sdk.models.enum.reply_file_upload_mode import ReplyFileUploadMode

reply_options = {
    "UploadMode": int(ReplyFileUploadMode.UPLOAD_MANDATORY),  # NO_UPLOAD, UPLOAD_OPTIONAL, UPLOAD_MANDATORY
    "AuthorizedExtensions": [".jpg", ".png", ".pdf"],
    "Messages": [
        {"CultureID": "fr-CA", "Message": "Veuillez joindre votre document."},
        {"CultureID": "en-CA", "Message": "Please attach your document."},
    ],
    "NoEditor": False,   # disable the reply text editor
    "NoReply": False,    # disallow any reply
}

sign_options (SignOptions, in models/json_models/sign_options.py) provides, for a signature send: signature_restriction (SignatureModeRestriction), cc_recipients / bcc_recipients (carbon-copy recipients, non-signers) and upload_file_options.

LogsHelper

Retrieval of message logs (sends, opens, activities).

Method Description
get_logs(api_client, serial, api_user, api_password, from_date, to_date, user_log_serial=None) All logs over a date range (datetime) → GetLogsResponse
get_log(api_client, serial, api_user, api_password, message_id=None, tracking_id=None, user_log_serial=None) Log of a specific message: provide message_id or tracking_idGetLogResponse

SignHelper

Management of digital signature zones on PDFs.

Method Description
add_file_zone_def_to_recipient_index(recipient_index, template_zones, sha512, recipients_match) Converts templates into zone definitions
convert_recipient_index_to_list(recipient_index) Converts the index into a list for multi_recipient_message
concat_recipient_zone_definition_lists(list1, list2) Merges two lists of zone definitions
validate_all_recipients_have_zones(files_to_sign, recipients, recipients_zone_def) Checks that all recipients have zones
validate_document_signature_integrity(api_client, file_sha512) Validates the integrity of a signed document
get_certification_token(api_client, serial, api_user, api_password, original_hash, culture_id, ...) Obtains a PKI certification token

PkiFileHelper

PKI certification of PDFs via headless browser (Playwright, signature extra).

# Asynchronous (recommended)
async with PkiFileHelper(is_preview=True, culture="en-US") as helper:
    result = await helper.certify_pki_pdf(args)

# Synchronous
helper = PkiFileHelper(is_preview=True)
result = helper.certify_pki_pdf_sync(args)
helper.close_sync()

CertifyPdfArgs

Property Type Description
file_bytes bytes Binary content of the PDF
file_name str File name
recipients List[str] Recipient email addresses
certify_data dict Certification token (from get_certification_token)
detect_existing_fields bool Detect existing fields (default: True)
recipient_zone_definitions List[RecipientZoneDefinition] Predefined zones
define_recipients Callable Callback for distributing zones among recipients

CertifiedPdfContainer

Property Type Description
file_bytes bytes Certified PDF
file_name str File name
sign_file_def dict Signature definition (SHA512, IsPKIFile, etc.)
recipient_zone_definitions List[RecipientZoneDefinition] Zones updated with the new SHA512

ZoneBuilder

Builds signature zones from a PDF (helpers/zone_builder.py, signature extra). The builder reads the actual dimensions of the PDF pages and computes the coordinates expected by the server.

from secure_exchanges_sdk.helpers.zone_builder import ZoneBuilder

with ZoneBuilder(pdf_path, is_pki=True) as builder:
    zone = builder.create_field_sign_zone(
        page=1, field_name="signature1",
        x=60, y=400, width=200, height=50
    )

Zone types: signature (create_field_sign_zone), signature date (create_field_date_sign_zone), initials, text, number, date, checkbox, radio buttons, text area, option list, dropdown list.

CryptoHelper

Low-level cryptographic functions (normally used indirectly through the helpers).

Category Methods
AES-256-CBC encrypt_string_to_bytes, decrypt_string_from_bytes, encrypt_binary, decrypt_binary_from_bytes, encrypt_string_to_b64, decrypt_string_from_base64, encrypt_file, decrypt_file
RSA create_new_private_key, get_public_key_from_private_key, encrypt_rsa_content, decrypt_rsa_content
Hashing get_sha512_hash_of_bytes, get_sha512_hash_of_string, get_sha256_hash_of_bytes, get_sha512_of_file
.NET GUIDs guid_to_bytes_le, bytes_le_to_guid
Keys generate_aes_keys, generate_secure_random_byte_array
Utilities alter_binary, bytes_xor, concat_byte_arrays, hex_to_byte_array

Data models

RecipientInfo

RecipientInfo(
    email="user@example.com",
    phone="+15145551234"  # Optional, enables SMS 2FA
)

SignZoneDetails

Defines a signature zone on a PDF. In practice, you do not instantiate SignZoneDetails yourself: zones are created via ZoneBuilder, which computes the coordinates for you.

SignZoneDetails(
    type="sign",         # "sign", "initial", "stamp", "text", "checkbox"
    page=1,              # Page number (1-indexed)
    left=100,            # X position (pixels)
    top=400,             # Y position (pixels)
    width=200,           # Width (pixels)
    height=80,           # Height (pixels)
    page_height=792,     # Page height
    canvas_width=612,    # Canvas width
    canvas_height=792,   # Canvas height
    rotate_degree=0,     # Rotation (0, 90, 180, 270)
    default_value=None   # JSON string with field metadata (required for PKI)
)

RecipientZoneDefinition

Associates signature zones with a recipient for one or more files.

RecipientZoneDefinition(
    email="signer@example.com",
    phone=None,
    zones_def_by_file=[
        FileZoneDefinition(
            unique_name=sha512,          # SHA512 of the file
            do_not_encrypt_pdf=False,
            do_not_append_certificate_to_file=False,
            is_pki_file=True,            # PKI certification
            zones_def=SignZoneDefinition(
                mode="define",
                zones=[...]
            )
        )
    ]
)

MultiRecipientAnswer

Response of multi_recipient_message:

Property Type Description
status int Status code (200=success)
data str Descriptive message
recipients_answer List[RecipientAnswer] Answers per recipient

Each RecipientAnswer contains a SendMessageAnswer with url (the link to send to the recipient).


Support

For any questions or issues, contact supportdev@secure-exchanges.info or visit secure-exchanges.com. Product documentation: help.secure-exchanges.com.


License

Licensed under the Apache License, Version 2.0. Full text at https://www.apache.org/licenses/LICENSE-2.0. The copyright notice is in the NOTICE file.

Using the SDK also requires a Secure Exchanges licence (serial, API user and API password) obtained from your administration portal. The Apache licence covers this source code, not access to the service.


Secure Exchanges Python SDK (version française)

English | Français

SDK Python pour l'API Secure Exchanges : transfert de fichiers sécurisé, messagerie chiffrée de bout en bout et signature numérique de documents PDF.

Le SDK prend en charge l'intégralité du protocole : handshake post-quantique, chiffrement bout-en-bout des messages et des fichiers, signatures électroniques avec certification PKI et journaux de messages.


Table des matières

  1. Installation
  2. Prérequis
  3. Identifiants et configuration
  4. Sécurité
  5. Architecture du SDK
  6. Guide d'utilisation
  7. Référence API
  8. Modèles de données
  9. Support
  10. Licence

Installation

pip install secure-exchanges-sdk

Cela installe tout le nécessaire pour l'envoi de messages, les pièces jointes, les journaux et la validation des numéros de téléphone.

Signature électronique sur PDF (extra signature)

La définition de zones de signature (ZoneBuilder) et la certification PDF (PkiFileHelper) demandent deux dépendances supplémentaires, pypdf et playwright, volontairement non installées par défaut : playwright télécharge un navigateur d'environ 150 Mo :

pip install "secure-exchanges-sdk[signature]"
playwright install chromium

Prérequis

Pour utiliser le SDK, vous devez disposer de :

  • Python 3.10+
  • Un numéro de série (serial) : UUID de votre licence
  • Un identifiant API (api_user) : UUID de l'utilisateur API
  • Un mot de passe API (api_password) : UUID du mot de passe API

Identifiants et configuration

Où trouver vos identifiants

Les 3 identifiants nécessaires (serial, api_user, api_password) sont des UUID (GUIDs) que vous obtenez dans votre portail d'administration Secure Exchanges lors de la création de votre licence API.

Identifiant Description Exemple
serial Numéro de série de votre licence UUID("d17ca972-5f70-4961-bac4-98e6b91b1dc4")
api_user Identifiant de l'utilisateur API UUID("0fa0cf77-4ca5-4406-8623-1ed0ffd47290")
api_password Mot de passe de l'utilisateur API UUID("4bfeabdf-c498-448a-9255-1e17c3ef8c0b")

Configuration

SettingsHelper sélectionne l'environnement et retourne ses endpoints, rien d'autre. Le SDK ne stocke aucun identifiant et ne va jamais les chercher dans l'environnement du processus : le serial, l'utilisateur et le mot de passe API vous appartiennent, et sont passés explicitement à chaque appel.

from secure_exchanges_sdk.client import SecureExchangesClient, SEMSClient
from secure_exchanges_sdk.helpers.settings_helper import SettingsHelper

cfg = SettingsHelper.configure_production()

client      = SecureExchangesClient(cfg['api_endpoint'])
sems_client = SEMSClient(cfg['sems_endpoint'])

# charger_mes_identifiants() est votre propre fonction : elle retourne les trois UUID
# de votre licence (uuid.UUID, pas str). Voir « Protéger vos identifiants »
# ci-dessous pour savoir où les conserver.
serial, api_user, api_password = charger_mes_identifiants()
Fonction Environnement Endpoints
configure_production() production www.secure-exchanges.com
configure_preview() preview (test) preview.secure-exchanges.com

Chacune retourne un dictionnaire avec api_endpoint, sems_endpoint, file_handler, file_upload_handler et environment.

Vos identifiants preview et production sont différents : un serial de production ne fonctionnera pas en preview, et inversement.

Protéger vos identifiants

Ces trois UUID valent un mot de passe sur votre compte Secure Exchanges : quiconque les détient peut envoyer, lire et supprimer des messages en votre nom, et la consommation vous est facturée. Leur stockage est entièrement votre décision, et votre responsabilité.

  • Ne les committez jamais. Gardez-les hors du dépôt, et vérifiez aussi l'historique : git log -S <serial> retrouve un secret committé une fois puis retiré. Un secret parti sur un remote est compromis : il faut le régénérer, pas seulement supprimer la ligne.
  • Ne les écrivez jamais en dur dans le code. Ils se retrouvent dans les traces d'exception, dans les rapports de bogue, dans les paquets que vous distribuez et dans chaque fork du code.
  • Privilégiez un gestionnaire de secrets. Chiffrés au repos, accès journalisé, rotation possible sans redéploiement.
  • Si vous les gardez dans un fichier, chiffrez-le ou verrouillez-le. Hors de la racine web, appartenant au compte de service, permissions 0400, et exclu de vos sauvegardes ou chiffré à l'intérieur.
  • Méfiez-vous de l'environnement du processus. Les variables d'environnement sont lisibles depuis /proc/<pid>/environ par tout ce qui tourne sous le même utilisateur, et apparaissent dans les vidages mémoire comme dans la plupart des rapporteurs d'erreurs. Chargez les identifiants au moment où vous en avez besoin plutôt que de les exporter pour toute la durée de vie du processus.
  • Tenez-les hors de vos journaux. Excluez-les explicitement de votre gestionnaire d'erreurs, de votre rapporteur d'incidents et des vidages de requête, qui capturent l'environnement et les variables locales par défaut.
  • Régénérez-les depuis le portail d'administration dès que vous soupçonnez une exposition : un portable perdu, un journal transmis à un tiers, le départ d'un développeur.

Sécurité

  • Chiffrement de bout en bout : le contenu (corps du message et fichiers) est chiffré localement, avec des clés générées sur votre machine et jamais transmises au serveur : le serveur ne stocke et ne relaie que des données chiffrées.
  • Échange de clés post-quantique : ML-KEM-1024 (FIPS 203), résistant aux attaques par ordinateur quantique, signé en ML-DSA-87 (FIPS 204).
  • Chiffrement AES-256 du contenu et des échanges avec le serveur.
  • Protection anti-interception : toute tentative d'attaque de type homme du milieu (MITM) fait échouer la connexion.
  • Rien à gérer : le SDK applique automatiquement l'intégralité du protocole à chaque appel : vous n'avez aucune primitive cryptographique à manipuler.

Architecture du SDK

Survol des grands modules. Dans la pratique, vous utiliserez surtout les helpers, qui orchestrent le protocole complet pour vous :

Module Rôle
client/ Clients HTTP : SecureExchangesClient (API principale), SEMSClient (livraison des courriels)
helpers/message_helper.py Envoi, lecture, suppression de messages, enveloppes de réponse
helpers/handshake_helper.py Handshake post-quantique (ML-KEM-1024 + ML-DSA-87)
helpers/post_quantum_crypto_helper.py Primitives post-quantiques du handshake
helpers/crypto_helper.py Cryptographie symétrique/RSA de bas niveau (AES-256, SHA-512, GUID .NET)
helpers/logs_helper.py Récupération des journaux de messages
helpers/sign_helper.py, helpers/zone_builder.py Zones de signature électronique sur PDF
helpers/pki_file_helper.py Certification PKI de PDF (navigateur headless)
helpers/file_helper.py Upload/download chiffré de fichiers (par morceaux, parallèle)
helpers/settings_helper.py Configuration (environnements, endpoints)
helpers/contact_helper.py, licence_helper.py Contacts, validation de licence
helpers/email_helper.py, phone_helper.py, mime_helper.py Validations (courriel, téléphone, types MIME)
models/ Modèles de données : réponses (answer/), entités (entity/), énumérations (enum/), transport, JSON
callback/ Modèles pour les callbacks de notification

Guide d'utilisation

Tous les exemples ci-dessous supposent la configuration suivante (voir Configuration) :

from secure_exchanges_sdk.client import SecureExchangesClient, SEMSClient
from secure_exchanges_sdk.helpers.settings_helper import SettingsHelper

cfg = SettingsHelper.configure_production()

client      = SecureExchangesClient(cfg['api_endpoint'])
sems_client = SEMSClient(cfg['sems_endpoint'])

# Votre propre fonction : elle retourne les trois UUID de votre licence.
serial, api_user, api_password = charger_mes_identifiants()

Envoi d'un message simple

from secure_exchanges_sdk.helpers.message_helper import MessageHelper
from secure_exchanges_sdk.models.entity.recipient_info import RecipientInfo

recipients = [
    RecipientInfo(email="destinataire@example.com")
]

answer = MessageHelper.multi_recipient_message(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    recipients=recipients,
    message="<p>Bonjour, voici un message sécurisé.</p>",
    subject="Message confidentiel",
    culture_id="fr-CA"
)

if answer.status == 200:
    print("Message envoyé avec succès!")
    for ra in answer.recipients_answer:
        if ra.answer and ra.answer.url:
            print(f"  URL: {ra.answer.url}")
else:
    print(f"Erreur {answer.status}: {answer.data}")

Envoi avec mot de passe et code SMS (2FA)

from secure_exchanges_sdk.models.enum.send_method_enum import SendMethodEnum

recipients = [
    RecipientInfo(email="user@example.com", phone="+15145551234")
]

answer = MessageHelper.multi_recipient_message(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    recipients=recipients,
    message="<p>Document confidentiel ci-joint.</p>",
    subject="Document protégé",
    password="MotDePasseSecret123",
    send_method=SendMethodEnum.EMAIL_WITH_SMS_CODE,  # lien par courriel, code par SMS
    culture_id="fr-CA",
    maximum_open_time=3,    # Nombre max d'ouvertures (1-99)
    minutes_expiration=1440 # Expiration en minutes (1440 = 24h)
)

Valeurs de SendMethodEnum :

Valeur Description
ONLY_EMAIL (0) Lien envoyé par courriel uniquement (défaut)
SMS_ONLY (1) Lien envoyé par SMS uniquement
SMS_WITH_EMAIL_CODE (2) Lien par SMS, code d'ouverture par courriel
EMAIL_WITH_SMS_CODE (3) Lien par courriel, code d'ouverture par SMS

La protection par mot de passe (password) est indépendante du canal d'envoi et peut être combinée avec n'importe quelle valeur de send_method.

Envoi avec fichiers joints

# Depuis le disque
answer = MessageHelper.multi_recipient_message(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    recipients=recipients,
    message="<p>Voir fichiers joints.</p>",
    subject="Fichiers sécurisés",
    files_path=["/chemin/vers/document.pdf", "/chemin/vers/image.png"]
)

# Depuis la mémoire (bytes)
pdf_bytes = open("/chemin/vers/rapport.pdf", "rb").read()
csv_bytes = open("/chemin/vers/donnees.csv", "rb").read()

files_in_memory = [
    {"binary": pdf_bytes, "file_name": "rapport.pdf"},
    {"binary": csv_bytes, "file_name": "donnees.csv"}
]

answer = MessageHelper.multi_recipient_message(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    recipients=recipients,
    message="<p>Rapport et données en pièces jointes.</p>",
    subject="Rapport mensuel",
    files_list=files_in_memory
)

Envoi avec certification PKI

La certification PKI appose un certificat numérique sur un PDF avant l'envoi pour signature. Le processus utilise un navigateur headless (Playwright, extra signature). Les zones de signature se définissent avec ZoneBuilder, qui lit les dimensions réelles des pages du PDF :

import asyncio
from secure_exchanges_sdk.helpers.crypto_helper import CryptoHelper
from secure_exchanges_sdk.helpers.zone_builder import ZoneBuilder
from secure_exchanges_sdk.helpers.sign_helper import SignHelper
from secure_exchanges_sdk.helpers.pki_file_helper import PkiFileHelper, CertifyPdfArgs
from secure_exchanges_sdk.models.entity.sign_zone_definition import SignZoneDefinition
from secure_exchanges_sdk.models.transport.file_zone_definition import FileZoneDefinition
from secure_exchanges_sdk.models.transport.recipient_zone_definition import RecipientZoneDefinition

# 1. Lire le PDF et calculer son SHA512
pdf_path = "contrat.pdf"
with open(pdf_path, "rb") as f:
    pdf_bytes = f.read()
sha512 = CryptoHelper.get_sha512_hash_of_bytes(pdf_bytes)

# 2. Définir les zones de signature avec ZoneBuilder
with ZoneBuilder(pdf_path, is_pki=True) as zone_builder:
    zones = [
        # Zone de signature en page 1
        zone_builder.create_field_sign_zone(
            page=1, field_name="signature1",
            x=60, y=400, width=200, height=50
        ),
        # Zone de date remplie automatiquement à la signature
        zone_builder.create_field_date_sign_zone(
            page=1, field_name="date1",
            x=60, y=500, width=100, height=25, font_size=12
        ),
    ]

# 3. Associer les zones au destinataire (fichier référencé par son SHA512)
recipient_zones = [
    RecipientZoneDefinition(
        email="signataire@example.com",
        phone=None,
        zones_def_by_file=[
            FileZoneDefinition(
                unique_name=sha512,
                do_not_encrypt_pdf=False,
                do_not_append_certificate_to_file=False,
                is_pki_file=True,
                zones_def=SignZoneDefinition(mode="define", zones=zones)
            )
        ]
    )
]

# 4. Obtenir le token de certification
cert_response = SignHelper.get_certification_token(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    original_hash=sha512,
    culture_id="fr-CA",
    token_type="CertifyDocument"
)
cert_data = cert_response["certification_data"]

# 5. Certifier le PDF via navigateur headless
certify_args = CertifyPdfArgs(
    file_bytes=pdf_bytes,
    file_name="contrat.pdf",
    recipients=["signataire@example.com"],
    certify_data=cert_data,
    detect_existing_fields=True,
    recipient_zone_definitions=recipient_zones
)

async def certify():
    async with PkiFileHelper(is_preview=False, culture="fr-CA") as helper:
        return await helper.certify_pki_pdf(certify_args)

certified = asyncio.run(certify())

# 6. Envoyer le PDF certifié
answer = MessageHelper.multi_recipient_message(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    recipients=[RecipientInfo(email="signataire@example.com")],
    message="<p>Veuillez signer ce document certifié.</p>",
    subject="Document PKI à signer",
    certified_pdfs=[certified],
    owner_dont_need_to_sign=True,
    sems_client=sems_client
)

Un exemple complet et exécutable, incluant les options de signature (SignOptions : restriction du mode de signature, demande de fichier en retour) et les paramètres de callback (clés contextuelles), se trouve dans example_pki_with_signature_options.py à la racine de pythonSDK/.

Récupération d'un message

# Parser un lien Secure Exchanges
link = "https://www.secure-exchanges.com/message.aspx?msgid=xxx&sems=yyy&cpart=zzz"
msg_params = MessageHelper.get_secure_exchanges_message_from_link(link)

# Récupérer et déchiffrer le message
response = MessageHelper.get_message(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    msg_params=msg_params,
    password="MotDePasse"     # si protégé
)

Note : chaque lecture consomme une ouverture du message (maximum_open_time).

Journaux de messages

Suivez le cycle de vie de vos messages (envoi, ouvertures, signatures) :

from datetime import datetime, timedelta
from uuid import UUID
from secure_exchanges_sdk.helpers.logs_helper import LogsHelper

# Tous les logs des 60 derniers jours
logs_response = LogsHelper.get_logs(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    from_date=datetime.now() - timedelta(days=60),
    to_date=datetime.now()
)

# Le log d'un message précis (par message_id OU tracking_id)
log_response = LogsHelper.get_log(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    tracking_id=UUID("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
)

Suppression d'un message

from uuid import UUID

success = MessageHelper.delete_message_by_tracking_id(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    tracking_id=UUID("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
)

Enveloppes de réponse

Les enveloppes permettent à un destinataire de vous répondre de manière sécurisée :

# Enveloppe simple (un destinataire)
env_response = MessageHelper.get_enveloppe(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    subject="Envoyez-moi vos documents",
    destination="destinataire@example.com",
    culture_id="fr-CA",
    reply_expiration_hours=48,
    maximum_reply_open_time=3,
    reply_to_api=True,
    authorized_extensions=[".pdf", ".docx"]
)

if env_response.url:
    print(f"URL de l'enveloppe: {env_response.url}")

# Enveloppes multiples
env_responses = MessageHelper.get_envelopes(
    api_client=client,
    serial=serial,
    api_user=api_user,
    api_password=api_password,
    subject="Documents requis",
    recipients=[
        {"Email": "user1@example.com"},
        {"Email": "user2@example.com"}
    ]
)

Référence API

MessageHelper

Classe statique pour l'envoi et la réception de messages.

Méthode Description
multi_recipient_message(api_client, serial, api_user, api_password, recipients, message, subject, ...) Envoie un message à plusieurs destinataires
get_message(api_client, serial, api_user, api_password, msg_params, password=None, digit_code=None, sems_client=None) Récupère et déchiffre un message
delete_message_by_tracking_id(api_client, serial, api_user, api_password, tracking_id, ...) Supprime un message par tracking ID
get_enveloppe(api_client, serial, api_user, api_password, subject, destination, ...) Crée une enveloppe de réponse
get_envelopes(api_client, serial, api_user, api_password, subject, recipients, ...) Crée des enveloppes multiples
get_secure_exchanges_message_from_link(link) Parse un lien SE en paramètres
send_trace(api_client, trace_content) Envoie une trace de support

Paramètres de multi_recipient_message

Paramètre Type Défaut Description
api_client SecureExchangesClient requis Client API
serial UUID requis Numéro de série
api_user UUID requis Identifiant API
api_password UUID requis Mot de passe API
recipients List[RecipientInfo] requis Destinataires
message str requis Contenu HTML du message
subject str requis Sujet du message
password str None Mot de passe de protection
files_list List[dict] None Fichiers en mémoire ({"binary": bytes, "file_name": str})
files_path List[str] None Chemins de fichiers sur le disque
send_method SendMethodEnum ONLY_EMAIL Canal d'envoi (voir tableau SendMethodEnum plus haut)
get_back_html bool True True=vous envoyez l'email, False=SEMS envoie
show_subject bool True Afficher le sujet dans la notification
get_notify bool True Notifier à l'ouverture
culture_id str "en-US" Langue ("fr-CA", "en-US")
maximum_open_time int 1 Nombre max d'ouvertures (1-99)
minutes_expiration int 10080 Expiration en minutes (défaut : 7 jours)
create_message_copy bool False Copie pour l'expéditeur
name str "Secure Exchanges" Nom de l'expéditeur
callback_parameters str None Paramètres libres (JSON) renvoyés dans les callbacks de notification
reply_options dict None Options de réponse du destinataire (voir ci-dessous)
owner_dont_need_to_sign bool True L'expéditeur ne signe pas
certified_pdfs List[CertifiedPdfContainer] None PDFs certifiés PKI
sign_options SignOptions None Options de signature : restriction de mode, destinataires CC/BCC, options d'upload
sems_client SEMSClient None Client SEMS (créé automatiquement si omis)

reply_options est un dictionnaire (clés PascalCase, comme l'API) qui contrôle ce que le destinataire peut faire en réponse :

from secure_exchanges_sdk.models.enum.reply_file_upload_mode import ReplyFileUploadMode

reply_options = {
    "UploadMode": int(ReplyFileUploadMode.UPLOAD_MANDATORY),  # NO_UPLOAD, UPLOAD_OPTIONAL, UPLOAD_MANDATORY
    "AuthorizedExtensions": [".jpg", ".png", ".pdf"],
    "Messages": [
        {"CultureID": "fr-CA", "Message": "Veuillez joindre votre document."},
        {"CultureID": "en-CA", "Message": "Please attach your document."},
    ],
    "NoEditor": False,   # désactiver l'éditeur de texte de réponse
    "NoReply": False,    # interdire toute réponse
}

sign_options (SignOptions, dans models/json_models/sign_options.py) permet, pour un envoi en signature : signature_restriction (SignatureModeRestriction), cc_recipients / bcc_recipients (destinataires en copie, non-signataires) et upload_file_options.

LogsHelper

Récupération des journaux de messages (envois, ouvertures, activités).

Méthode Description
get_logs(api_client, serial, api_user, api_password, from_date, to_date, user_log_serial=None) Tous les logs sur une plage de dates (datetime) → GetLogsResponse
get_log(api_client, serial, api_user, api_password, message_id=None, tracking_id=None, user_log_serial=None) Log d'un message précis : fournir message_id ou tracking_idGetLogResponse

SignHelper

Gestion des zones de signature numérique sur les PDF.

Méthode Description
add_file_zone_def_to_recipient_index(recipient_index, template_zones, sha512, recipients_match) Convertit des templates en définitions de zones
convert_recipient_index_to_list(recipient_index) Convertit l'index en liste pour multi_recipient_message
concat_recipient_zone_definition_lists(list1, list2) Fusionne deux listes de définitions de zones
validate_all_recipients_have_zones(files_to_sign, recipients, recipients_zone_def) Vérifie que tous les destinataires ont des zones
validate_document_signature_integrity(api_client, file_sha512) Valide l'intégrité d'un document signé
get_certification_token(api_client, serial, api_user, api_password, original_hash, culture_id, ...) Obtient un token de certification PKI

PkiFileHelper

Certification PKI de PDF via navigateur headless (Playwright, extra signature).

# Asynchrone (recommandé)
async with PkiFileHelper(is_preview=True, culture="fr-CA") as helper:
    result = await helper.certify_pki_pdf(args)

# Synchrone
helper = PkiFileHelper(is_preview=True)
result = helper.certify_pki_pdf_sync(args)
helper.close_sync()

CertifyPdfArgs

Propriété Type Description
file_bytes bytes Contenu binaire du PDF
file_name str Nom du fichier
recipients List[str] Emails des destinataires
certify_data dict Token de certification (de get_certification_token)
detect_existing_fields bool Détecter les champs existants (défaut: True)
recipient_zone_definitions List[RecipientZoneDefinition] Zones prédéfinies
define_recipients Callable Callback pour distribuer les zones entre destinataires

CertifiedPdfContainer

Propriété Type Description
file_bytes bytes PDF certifié
file_name str Nom du fichier
sign_file_def dict Définition de signature (SHA512, IsPKIFile, etc.)
recipient_zone_definitions List[RecipientZoneDefinition] Zones mises à jour avec le nouveau SHA512

ZoneBuilder

Construction de zones de signature à partir d'un PDF (helpers/zone_builder.py, extra signature). Le builder lit les dimensions réelles des pages du PDF et calcule les coordonnées attendues par le serveur.

from secure_exchanges_sdk.helpers.zone_builder import ZoneBuilder

with ZoneBuilder(pdf_path, is_pki=True) as builder:
    zone = builder.create_field_sign_zone(
        page=1, field_name="signature1",
        x=60, y=400, width=200, height=50
    )

Types de zones : signature (create_field_sign_zone), date de signature (create_field_date_sign_zone), initiales, texte, nombre, date, case à cocher, boutons radio, zone de texte, liste d'options, liste déroulante.

CryptoHelper

Fonctions cryptographiques de bas niveau (normalement utilisées indirectement via les helpers).

Catégorie Méthodes
AES-256-CBC encrypt_string_to_bytes, decrypt_string_from_bytes, encrypt_binary, decrypt_binary_from_bytes, encrypt_string_to_b64, decrypt_string_from_base64, encrypt_file, decrypt_file
RSA create_new_private_key, get_public_key_from_private_key, encrypt_rsa_content, decrypt_rsa_content
Hachage get_sha512_hash_of_bytes, get_sha512_hash_of_string, get_sha256_hash_of_bytes, get_sha512_of_file
GUID .NET guid_to_bytes_le, bytes_le_to_guid
Clés generate_aes_keys, generate_secure_random_byte_array
Utilitaires alter_binary, bytes_xor, concat_byte_arrays, hex_to_byte_array

Modèles de données

RecipientInfo

RecipientInfo(
    email="user@example.com",
    phone="+15145551234"  # Optionnel, active le 2FA par SMS
)

SignZoneDetails

Définit une zone de signature sur un PDF. En pratique, vous n'instanciez pas SignZoneDetails vous-même : les zones sont créées via ZoneBuilder, qui calcule les coordonnées pour vous.

SignZoneDetails(
    type="sign",         # "sign", "initial", "stamp", "text", "checkbox"
    page=1,              # Numéro de page (1-indexé)
    left=100,            # Position X (pixels)
    top=400,             # Position Y (pixels)
    width=200,           # Largeur (pixels)
    height=80,           # Hauteur (pixels)
    page_height=792,     # Hauteur de la page
    canvas_width=612,    # Largeur du canvas
    canvas_height=792,   # Hauteur du canvas
    rotate_degree=0,     # Rotation (0, 90, 180, 270)
    default_value=None   # JSON string avec métadonnées du champ (requis pour PKI)
)

RecipientZoneDefinition

Associe des zones de signature à un destinataire pour un ou plusieurs fichiers.

RecipientZoneDefinition(
    email="signataire@example.com",
    phone=None,
    zones_def_by_file=[
        FileZoneDefinition(
            unique_name=sha512,          # SHA512 du fichier
            do_not_encrypt_pdf=False,
            do_not_append_certificate_to_file=False,
            is_pki_file=True,            # certification PKI
            zones_def=SignZoneDefinition(
                mode="define",
                zones=[...]
            )
        )
    ]
)

MultiRecipientAnswer

Réponse de multi_recipient_message :

Propriété Type Description
status int Code de statut (200=succès)
data str Message descriptif
recipients_answer List[RecipientAnswer] Réponses par destinataire

Chaque RecipientAnswer contient un SendMessageAnswer avec url (le lien à envoyer au destinataire).


Support

Pour toute question ou problème, contactez supportdev@secure-exchanges.info ou visitez secure-exchanges.com. Documentation produit : help.secure-exchanges.com.


Licence

Distribué sous licence Apache, version 2.0. Texte complet sur https://www.apache.org/licenses/LICENSE-2.0. Le copyright figure dans le fichier NOTICE.

L'utilisation du SDK requiert par ailleurs une licence Secure Exchanges (serial, usager et mot de passe API) obtenue depuis votre portail d'administration. La licence Apache couvre ce code source, pas l'accès au service.

Release files for secure-exchanges-sdk 2026.8.26

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for secure-exchanges-sdk 2026.8.26
File Size Uploaded
secure_exchanges_sdk-2026.8.26.tar.gz 171.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for secure-exchanges-sdk 2026.8.26
File Interpreter ABI Platform
secure_exchanges_sdk-2026.8.26-py3-none-any.whl Python 3 none any Details

Total release size:374.3 kB

Release files / secure_exchanges_sdk-2026.8.26.tar.gz

Download URL secure_exchanges_sdk-2026.8.26.tar.gz
Size 171.1 kB
Tags Source
SHA-256 checksum
How to use checksums
73418879bf01b84d86c6d94f66eb1bbb24e013717ed19e8c1ae0fe89070db1c6
BLAKE2b-256 checksum
How to use checksums
002fed6187be773ba60b67114ba6ef280957ead190cd3ee0d17a4da6ffce1a0d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / secure_exchanges_sdk-2026.8.26-py3-none-any.whl

Download URL secure_exchanges_sdk-2026.8.26-py3-none-any.whl
Size 203.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
89ecdd9a1ae68cd7dcec726b606e5513b84ee889255da3cc56b257e9642b2592
BLAKE2b-256 checksum
How to use checksums
58d6169888e64a077afc0440a24ee9732f4ae501fe55f40b496b69b7c147e329
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release history Release notifications | RSS feed

This release

2026.8.26 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page