Requisitos previos
- Cuenta de desarrollador y una app configurada para OAuth 2.0
- Token de acceso de usuario con
dm.read,dm.write,tweet.readyusers.read
1. Instala las dependencias
- Python
- TypeScript
- Rust
- Go
- C#
- Java
chatxdk; impórtalo como chat_xdk. Requiere Python 3.10+.- Python
- TypeScript
- Rust
- Go
- C#
- Java
2. Inicializa el Chat XDK con claves existentes
Este paso carga claves que ya tienes—úsalo cuando esta identidad ya completó la configuración inicial antes:- Copia de seguridad segura de claves: construye el SDK con el
juicebox_configde tu registro de clave pública y luego usaunlockcon tu código de acceso para recuperar las claves privadas (por ejemplo, en un dispositivo nuevo). - Blob de claves:
import_keyscon un blob que exportaste previamente medianteexport_keys, pasando la versión registrada de la clave junto con él (Rust y Go llaman a esta varianteimport_keys_with_version/ImportKeysWithVersion).
set_identity(user_id, signing_key_version) una vez, con tu ID de usuario y el public_key_version de tu registro. Esto guarda la identidad de sesión: cada llamada posterior a encrypt y prepare firma como esta identidad, así que nunca pasas un ID de remitente ni una versión de clave de firma por llamada.
¿Configuras por primera vez? Construye el SDK de la misma forma pero omite unlock/import_keys y continúa en el paso 3 para crear, respaldar y registrar tus claves.
- Python
- TypeScript
- Rust
- Go
- C#
- Java
export_keys / import_keys). Las apps cliente suelen usar la copia de seguridad segura de claves (setup / unlock con un código de acceso). Consulta la referencia del Chat XDK para ambos caminos.
¿Traes tus propias claves?
import_keys solo acepta el blob opaco que produce export_keys del Chat XDK—es una serialización privada y versionada del estado completo de las claves, no claves P-256 en bruto ni codificadas en PEM. No puedes construir este blob por tu cuenta: genera las claves con generate_keypairs (paso 3), exporta el blob una vez y guárdalo codificado en base64. Los blobs hechos a mano o modificados fallan al importarse.3. Crea y registra las claves (configuración inicial)
Omite este paso si cargaste claves existentes en el paso 2. De lo contrario, la configuración inicial de una identidad nueva hace tres cosas:- Crear los pares de claves —
generate_keypairsproduce los pares de claves de identidad y de firma. - Guardar las claves privadas —
setupcon un código de acceso las escribe en la copia de seguridad segura de claves (clientes), oexport_keysdevuelve un blob de claves para que lo guardes de forma segura (servidores y bots). - Registrar las claves públicas — envía el payload de registro con POST al endpoint add-public-key para que otros puedan cifrar hacia ti y verificar tus firmas.
set_identity con la versión de clave del registro, para que esta sesión firme como la nueva identidad.
- Python
- TypeScript
- Rust
- Go
- C#
- Java
4. Configura las claves de conversación
Llama aprepare_conversation_key_change con la clave pública de identidad de cada participante; la identidad del remitente proviene de la sesión que estableciste en el paso 2. Una sola llamada genera una nueva clave de conversación, la cifra para cada participante y firma el cambio. Envía el resultado con POST al endpoint add conversation keys (POST /2/chat/conversations/{id}/keys)—el cuerpo necesita conversation_key_version, conversation_participant_keys (SDK encrypted_key → API encrypted_conversation_key) y action_signatures (obligatorio; la API rechaza la llamada sin ellas). Conserva la clave de conversación en bruto para enviar.
La respuesta devuelve el id canónico de la conversación (data.conversation_id—el par unido con guión para un 1:1, o el id con prefijo g para un grupo) y el data.sequence_id del cambio de clave. Usa ese id devuelto para solicitudes posteriores en lugar de reconstruirlo en el cliente. La misma llamada también rota las claves más adelante: pasa el id de conversación existente a prepare_conversation_key_change y haz POST con la versión de clave más reciente. Rota cuando sospeches que la clave de conversación quedó expuesta—la rotación protege mensajes futuros únicamente; los mensajes cifrados bajo versiones anteriores de la clave siguen siendo legibles para cualquiera que tenga esas versiones.
- Python
- TypeScript
- Rust
- Go
- C#
- Java
5. Envía un mensaje
Cifra con la clave de conversación en bruto del paso 4. El SDK genera el id del mensaje (un UUID), lo incrusta en el evento firmado y lo devuelve en el payload—nunca acuñas uno tú mismo. En la solicitud de envío, mapea:
Usa un id de conversación con guión en la ruta URL cuando la API lo requiera (
: → -). El propio SDK es flexible: encrypt_message y encrypt_reply aceptan el id en cualquier forma que tengas—A:B de eventos, A-B de listados o rutas URL (en cualquier orden), o solo el id de usuario del destinatario—y lo canonicalizan antes de firmar. Los ids de grupo (con prefijo g) pasan sin cambios.
- Python
- TypeScript
- Rust
- Go
- C#
- Java
Los snippets pasan la clave de conversación explícitamente porque en este flujo acabas de crearla en el paso 4. Una vez que la caché de claves esté activada y una pasada de
decrypt_events haya verificado la clave de la conversación (paso 6), basta con encrypt_message(conversation_id, text) a solas—el SDK completa con la última clave verificada. Los reintentos deberían reenviar el mismo payload cifrado, así que nunca se acuña dos veces un id.6. Recibe y descifra
Usa webhooks o el activity stream para el tráfico en vivo, o pagina los events de la conversación para el historial.- Campos de payload en vivo:
encoded_event,conversation_key_change_eventopcional - Historial:
GET /2/chat/conversations/{id}/events— prefieredecrypt_eventssobre todos los eventos másmeta.conversation_key_events - Descifrar necesita las claves de firma de los remitentes para que el SDK pueda verificar quién escribió cada mensaje. Estas son las claves públicas de los demás participantes — obténlas del mismo endpoint de claves públicas que usaste en el paso 4 y mapea los campos a
SigningKeyEntry(los snippets de abajo incluyen el mapeo) - Puedes pasar las claves de firma (y, para
decrypt_event, las claves de conversación) en cada llamada, o establecer dos almacenes de sesión opcionales una vez y usar las formas cortas de llamada. Los snippets siguientes usan los almacenes:set_signing_keys(entries)mantiene las claves de los participantes, yset_cache_keys(true)(desactivado por defecto) guarda la última clave verificada por firma de cada conversación para que las llamadas posteriores puedan omitir los argumentos de clave. Ambos estilos verifican de forma idéntica - JavaScript usa tipos de evento en camelCase (
message); los demás lenguajes usan"Message"y campos snake_case en JSON
- Python
- TypeScript
- Rust
- Go
- C#
- Java
¿Serverless o multi-instancia? El almacén de claves de firma y la caché de claves viven en la memoria de la instancia del SDK. Cuando eso no encaja—una invocación descifra, otra envía—pasa las claves explícitamente en su lugar:
decrypt_events(events, signing_keys), decrypt_event(event_b64, conversation_keys, signing_keys) y las sobrecargas conversation_key/conversation_key_version en los métodos de cifrado. Persiste tú mismo las conversation_keys que devuelve decrypt_events y pásalas de nuevo.Buenas prácticas
- Mantén fresco el almacén de claves de firma: vuelve a llamar a
set_signing_keyscon el conjunto completo de participantes cuando un remitente registre una nueva versión de clave, y actualízalo ante fallos de verificación de firma - Deduplica las entregas en vivo con
event_uuid