Gerar ou importar a chave de endpoint do Flow
Põe o par de chaves data_exchange em UM número, por um de DOIS verbos, distinguidos por um único campo: envie privateKey e ele IMPORTA a chave que você já tem; deixe-o de fora e ele GERA um par novo. Responde 200 com a mesma forma que o GET devolve, mais replaced.
- GERAR — sem
privateKey. Cria o par, guarda a metade privada cifrada e REGISTRA a metade pública na Meta. - IMPORTAR —
privateKey, opcionalmente compassphrase. Guarda uma chave que você JÁ tem, e ⛔ NÃO REGISTRA NADA NA META.
⛔ GERAR É UMA OPERAÇÃO DESTRUTIVA COM CARA DE CRIAÇÃO. A Meta guarda exatamente UMA chave pública por phone id: registrar uma segunda não a acrescenta, SUBSTITUI a primeira, e todos os Flows data_exchange daquele número deixam de decifrar de uma vez. Do lado do cliente o sintoma é um formulário que não abre mais, sem erro nenhum do nosso lado — o endpoint simplesmente responde 421 a um corpo cifrado para uma chave que já não temos. A metade privada guardada aqui é sobrescrita no mesmo instante e não tem volta.
⛔ IMPORTAR NÃO REGISTRA NADA NA META, e é exatamente esse o ponto. A sua chave pública já está registrada — muitas vezes por um sistema anterior a nós — e a Meta guarda exatamente uma chave por phone id, então registrar aqui substituiria justamente a configuração que a importação existe para preservar. O que torna isso seguro é uma LEITURA: derivamos a metade pública da privada que você enviou e comparamos com a chave que a Meta diz ter para o número.
- batem → guardada,
uploadedAtcarimbado,metaStatus: "VALID". - não batem → 400
FLOW_ENDPOINT_KEY_IMPORT_MISMATCH, e NADA é escrito. Guardá-la deixaria um número dizendoconfigured: truesem decifrar coisa nenhuma. - a Meta não pôde ser consultada, ou não tem chave → guardada mesmo assim, com
uploadedAt: nullemetaStatusUNKNOWN/NOT_SET. Esse null É o sinal de “não verificada” e você tem de lê-lo: um 200 sozinho não distingue os dois casos.
Um PEM protegido por passphrase é aceito; a chave é aberta uma vez, aqui, e guardada normalizada. O PEM tem de ser RSA de 2048 bits ou mais — a Meta cifra o data_exchange com RSA/OAEP.
⛔ confirm NÃO É SEMPRE OBRIGATÓRIO. Ele é exigido exatamente quando a chamada SUBSTITUI UMA CHAVE VIVA — e essa regra é a mesma para OS DOIS verbos. Uma única checagem de estado decide: já existe uma chave nossa viva na Meta (uploadedAt diferente de null). A PRIMEIRA configuração nunca pergunta, seja qual for o verbo, e repetir um par que a Meta nunca aceitou (uploadedAt: null) também não — essa chamada reenvia a MESMA metade pública guardada e converge em vez de substituir, então não há o que destruir. Quando ele É exigido, a checagem é === true, então "true", 1 e {} são todos recusados.
⚠️ Importar também tem portão, e o que ele protege é o NOSSO lado, não o da Meta. Uma importação não registra nada na Meta, mas sobrescreve a metade privada guardada aqui — a chave com que NÓS decifamos. Se o número já tinha uma chave que funcionava e a Meta não conseguir confirmar a importada (indisponível, por exemplo), a importada é guardada assim mesmo e todo data_exchange daquele número deixa de decifrar, sem nada ter mudado na Meta para apontar a causa. Por isso os dois verbos partilham o campo e respondem com códigos DIFERENTES: FLOW_ENDPOINT_KEY_REQUIRES_CONFIRMATION ao gerar (o que está em jogo é o registro na Meta) e FLOW_ENDPOINT_KEY_IMPORT_REQUIRES_CONFIRMATION ao importar (o que está em jogo é a metade privada guardada aqui).
⚠️ replaced está no payload porque um 200 sozinho não diz qual das duas coisas aconteceu. replaced: false é “agora existe uma chave onde não havia nenhuma viva”; replaced: true é “a chave que funcionava acabou, e todo Flow que respondia com o par antigo passa a responder com o novo”.
O corpo aceita três campos — confirm, privateKey e passphrase — e qualquer outro dá 400 FLOW_UNKNOWN_FIELDS. passphrase sozinha é RECUSADA, 400 FLOW_ENDPOINT_KEY_PASSPHRASE_ORPHAN, e nunca ignorada: um privateKey digitado errado cairia senão no GERAR, que registra uma chave nova na Meta e substitui o que lá estava — o resultado mais destrutivo desta rota, alcançado por um erro de digitação e reportado como sucesso. Um privateKey que não seja string não vazia, ou um passphrase que não seja string, dá 400 FLOW_ENDPOINT_KEY_IMPORT_INVALID, respondido antes de qualquer criptografia rodar. Um PEM que não dá para usar é um 400 cujo código nomeia o conserto: FLOW_ENDPOINT_KEY_PASSPHRASE_REQUIRED, FLOW_ENDPOINT_KEY_PASSPHRASE_WRONG ou FLOW_ENDPOINT_KEY_PEM_INVALID (ilegível, não-RSA, ou com menos de 2048 bits).
Corpo truncado não é lido como corpo vazio — o payload é parseado do texto cru, então {"confirm": true (uma chave faltando) dá 400 FLOW_BODY_INVALID em vez de um confuso “confirmação necessária”. Nenhum corpo continua sendo legítimo, e significa GERAR. Nomear o número no corpo — whatsappNumberId, numberId ou wabaId — tem recusa própria, 400 FLOW_NUMBER_FROM_KEY, porque o número vem da credencial. Permissão flows:manage.
Exige chave com escopo de número. Uma chave de tenant precisa nomear o número no header x-whatsapp-number-id, senão recebe 403 TENANT_SCOPE_NOT_ALLOWED.
Autorizações
Sua chave de API ps_
Parâmetros de caminho
O id do número ao qual a chave está vinculada — o id (ou o id da instância) que GET /v1/numbers devolve. Ele é CONFERIDO contra o número da própria credencial, nunca usado para procurar um.
Corpo
Tem de ser o booleano true, exatamente. ⛔ NÃO é sempre obrigatório: é exigido exatamente quando a chamada SUBSTITUI UMA CHAVE VIVA — ou seja, quando já existe uma chave nossa viva na Meta (uploadedAt diferente de null) — e essa regra vale para OS DOIS verbos, gerar e importar. A primeira configuração não pergunta, e repetir um par que a Meta nunca aceitou também não. O que ele reconhece muda com o verbo: ao gerar, que a chave registrada na Meta é SUBSTITUÍDA e todos os Flows data_exchange deste número deixam de decifrar; ao importar, que a metade privada guardada aqui é SUBSTITUÍDA, o que quebra a decifragem do nosso lado se a Meta não conseguir confirmar a chave importada.
true true
O PEM de uma chave privada que você JÁ tem, cuja metade pública a Meta tem registrada para este número. ⛔ A PRESENÇA dele é o que transforma este POST de GERAR em IMPORTAR: enviado, nada é registrado na Meta e só a metade privada guardada muda; omitido, um par novo é criado e a metade pública dele REGISTRADA na Meta. Tem de ser string não vazia — privateKey: 42 dá 400 FLOW_ENDPOINT_KEY_IMPORT_INVALID e nunca é convertido. Envie o conteúdo do arquivo .pem inteiro, incluindo as linhas -----BEGIN …----- e -----END …-----. RSA, 2048 bits ou mais; um PEM protegido por passphrase é aceito junto de passphrase. Se a metade pública dele não for a que a Meta tem, a resposta é 400 FLOW_ENDPOINT_KEY_IMPORT_MISMATCH e nada é escrito.
1"-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQ...\n-----END PRIVATE KEY-----\n"
A passphrase que abre privateKey, quando o PEM está cifrado. Opcional, e só faz sentido junto de privateKey: ⛔ enviada sozinha é RECUSADA com 400 FLOW_ENDPOINT_KEY_PASSPHRASE_ORPHAN em vez de ignorada, porque um privateKey digitado errado cairia senão no GERAR e substituiria o registro na Meta. Tem de ser string. Um PEM cifrado sem passphrase dá 400 FLOW_ENDPOINT_KEY_PASSPHRASE_REQUIRED; uma passphrase que não o abre dá 400 FLOW_ENDPOINT_KEY_PASSPHRASE_WRONG — dois códigos, porque são dois consertos diferentes.
"a-passphrase-que-abre-o-pem"
Resposta
Agora existe um par de chaves no número. GERAR também registrou a metade pública na Meta; IMPORTAR não registrou NADA — nesse caso, uploadedAt: null com metaStatus UNKNOWN/NOT_SET significa que a chave foi GUARDADA e a Meta não a confirmou, que é a única coisa que um 200 sozinho não conta. replaced diz se uma chave que estava VIVA acabou de ser deslocada — um 200 sozinho não diz