Migrando de outro provedor
O que muda ao trocar o provedor de push — o que a API aceita tal e qual, o que precisa ser trocado no aplicativo, e os passos que ninguém automatiza.
Migrando de outro provedor
Trocar de provedor de push costuma significar reescrever a camada de
integração inteira. Aqui não: o /api/v1 do PushMesh fala o formato clássico
de push do mercado — o modelo player, com include_player_ids,
contents, included_segments e companhia.
Na prática, o lado do servidor é apontar a URL base e trocar a chave. O lado do aplicativo dá mais trabalho, e esta página é honesta sobre isso: há passos manuais e há uma etapa que depende da sua curva de atualização de app. Ninguém migra uma base de aparelhos por chave de API.
O retrato honesto em três linhas
| Camada | Esforço real |
|---|---|
| Servidor (envio, consulta, relatórios) | baixo — URL base + chave |
| Aplicativo (SDK) | médio — trocar o pacote e a inicialização |
| Base de aparelhos | é um período, não um comando — os aparelhos se registram conforme o app atualiza |
Parte 1 — O servidor
O que já está no formato que você conhece
Envio, POST /api/v1/notifications, com os nomes clássicos:
| Grupo | Campos aceitos |
|---|---|
| Alvo (exatamente um) | include_player_ids, include_external_user_ids, included_segments |
| Conteúdo | contents, headings, subtitle, data |
| Destino do toque | url, app_url, web_url |
| Entrega | ttl, priority (5 ou 10), collapse_id, send_after |
| Plataforma | isIos, isAndroid, isAnyWeb |
| Android | android_channel_id, android_accent_color, android_sound, big_picture, large_icon, small_icon |
| iOS | ios_sound, ios_attachments, content_available, mutable_content |
| Identidade | name, external_id, idempotency_key |
| Canal | channel_for_external_user_ids (aceito: "push") |
Semânticas preservadas, inclusive as esquisitas:
-
url/app_url/web_urlviram o destino do toque, nessa precedência; -
os flags de plataforma seguem a lógica por exclusão: ausente inclui,
falseexplícito exclui.isIos: truenão restringe nada; -
ninguém alcançável não é erro — é 200 com
idvazio:{ "errors": ["All included players are not subscribed"], "id": "", "recipients": 0 } -
envio parcial também é 200, com
errorscomo objeto:{ "errors": { "invalid_player_ids": ["1111…"] }, "id": "0198…", "recipients": 1 }
Segmentos reconhecidos: Subscribed Users, Total Subscriptions (apelido do
primeiro), Active Users (visto nos últimos 7 dias) e Engaged Users (com
recibo nos últimos 7 dias).
A troca
# antes
curl -X POST https://<provedor-anterior>/api/v1/notifications \
-H "Authorization: Basic $CHAVE_ANTIGA" ...
# depois
curl -X POST https://api.pushmesh.io/api/v1/notifications \
-H "Authorization: Basic $PUSHMESH_KEY" ...
A chave tem o formato pm_live_<identificador>_<segredo> e vai em
Authorization: Basic. Também são aceitos Bearer <chave> e o Basic com
base64 de usuario:chave — o que o seu cliente HTTP já fizer, funciona.
Diferenças que valem um teste antes do corte
| Comportamento | O que esperar |
|---|---|
| Sucesso do envio | 200, sempre — não 201 |
errors na resposta 200 | array quando ninguém é alcançável, objeto no envio parcial |
id vazio | significa “ninguém alcançável” ou ensaio — não é falha |
| Textos de erro | em português; ramifique pelo status HTTP, nunca pela frase |
| Limite do conteúdo | 3.891 bytes no payload montado, já incluindo 96 bytes que o servidor injeta |
app_id | obrigatório no corpo/query, e precisa casar com a chave |
Um desserializador tipado com errors fixo como lista de strings quebra
exatamente no cenário mais comum de migração — uma lista com identificadores
antigos, que responde com errors objeto. Ajuste isso antes de virar.
O que é recusado de propósito
Estes campos respondem 400 nomeado em vez de serem aceitos em silêncio. Aceitar e ignorar mandaria a mensagem errada para a base toda sem avisar ninguém:
| Campo | O que fazer |
|---|---|
template_id | modelos de mensagem ainda não existem: monte em contents/headings |
custom_data | use data |
existing_android_channel_id | use android_channel_id |
filters | não há equivalente hoje — resolva o público do seu lado e mande a lista |
excluded_segments | idem |
buttons | botões de ação ainda não existem |
delayed_option, delivery_time_of_day | agendamento por preferência do usuário ainda não existe; use send_after |
throttle_rate_per_minute | o ritmo de entrega é do aplicativo, não do disparo |
android_visibility, android_led_color, android_group, ios_category | ainda não configuráveis por disparo |
include_aliases, include_subscription_ids | são do modelo mais novo de usuário; esta compatibilidade é a do modelo player |
web_buttons é a única exceção: aceito e ignorado, porque integrações antigas
mandam array vazio.
Leia essa tabela antes de decidir. Se a sua operação depende de filters
ou de modelos de mensagem, a migração exige refazer isso no seu lado — e é
melhor descobrir agora do que na véspera.
Parte 2 — O aplicativo
React Native
npm install @pushmesh/sdk
O SDK tem uma superfície clássica justamente para você não reescrever as chamadas do app:
import { ClassicApi } from '@pushmesh/sdk/compat';
await ClassicApi.initialize(APP_ID, { baseUrl: 'https://api.pushmesh.io' });
await ClassicApi.login('usuario-42');
await ClassicApi.Notifications.requestPermission();
await ClassicApi.User.addTags({ plano: 'pro' });
ClassicApi.InAppMessages.addTrigger('tela', 'checkout');
Cobre initialize, login/logout, permissão, listeners de notificação, tags
de usuário e gatilhos de in-app. Onde os nomes batem, a troca é o import.
A API nativa do SDK é a mesma coisa com nomes próprios:
import { PushMesh } from '@pushmesh/sdk';
await PushMesh.init({ appId: APP_ID, baseUrl: 'https://api.pushmesh.io' });
await PushMesh.login('usuario-42');
baseUrlnão é opcional na versão publicada hoje. O pacote@pushmesh/sdk@0.7.2traz outro endereço embutido como padrão para quando o campo é omitido, e esse endereço não está no ar: o aparelho não registra e nenhum erro de servidor aparece, porque a chamada nem sai. PassebaseUrl: 'https://api.pushmesh.io'nos dois caminhos —PushMesh.initeClassicApi.initialize— até uma versão nova corrigir o padrão. É a primeira coisa a conferir se a base nova não cresce depois da publicação do app.
O que precisa da sua atenção no app
- Remova o SDK anterior. Dois SDKs de push disputando o token do aparelho é a receita para o push sumir sem erro nenhum.
- Cadastre os parâmetros do Firebase no painel (Android). O SDK os busca no boot — o app deixa de precisar do arquivo de configuração embutido. E não confunda com a credencial que envia: as duas estão em Credenciais de entrega.
- Confirme o envio do token no seu fluxo de renovação.
- Não coloque a chave da API no aplicativo. As rotas que o app usa não pedem credencial exatamente por isso: um APK publicado é um segredo publicado.
Parte 3 — A base de aparelhos (a parte que não é mágica)
Não existe botão de importar base. Existem dois caminhos, e você provavelmente vai usar os dois.
Caminho A — registro orgânico (o padrão, seguro)
Você publica a versão do app com o SDK novo. Cada aparelho que abre o app se
registra, e o player_id nasce daquele registro. A base cresce na velocidade
da sua adoção de versão.
- Vantagem: zero risco, zero trabalho, e a base que se forma é composta só de aparelhos vivos.
- Custo: leva o tempo da sua curva de atualização — semanas, tipicamente.
- Continuidade da identidade: mande
external_user_idno login e o seu identificador de sempre continua valendo. É o que faz a segmentação do seu lado sobreviver à troca.
Caminho B — registro em massa dos tokens que você já tem
Se você guarda a lista de tokens de push, dá para registrá-los diretamente:
curl -X POST https://api.pushmesh.io/api/v1/players \
-H "Content-Type: application/json" \
-d '{
"app_id": "'"$APP_ID"'",
"device_type": 1,
"identifier": "<token de push do aparelho>",
"external_user_id": "usuario-42"
}'
A rota é idempotente por token: registrar duas vezes devolve o mesmo
player_id.
Antes de contar com isso, confira se os tokens continuam válidos:
- Android: o token está vinculado ao projeto Firebase. Se você mantiver o mesmo projeto, os tokens continuam valendo. Se trocar de projeto, não valem — e não há como convertê-los.
- iOS: o token está vinculado ao aplicativo e ao ambiente de notificação, e não ao provedor. Mantendo o mesmo aplicativo e enviando a mesma chave de autenticação, eles continuam valendo.
E confira o custo de tempo, que costuma surpreender: a rota de registro tem teto de 120 requisições por minuto por endereço de origem e o aplicativo tem teto de 50.000 registros de aparelho por hora. Uma base grande, saindo de um único servidor, leva dias. Se esse for o seu caso, fale com a gente antes de começar, em vez de descobrir batendo em 429.
Uma observação que evita expectativa errada: um token registrado por essa via só é alcançável de fato quando o aparelho está rodando um app capaz de receber pelo PushMesh. Registrar o token não instala o SDK.
Parte 4 — Rodando os dois em paralelo
O modo mais seguro de virar é não virar de uma vez.
-
Publique o app com o SDK novo, mantendo o provedor anterior ativo.
-
Espere a adoção subir. Nada muda no seu envio ainda.
-
Meça a base nova com o export, que devolve quem está vivo:
curl -X POST "https://api.pushmesh.io/api/v1/players/csv_export?app_id=$APP_ID" \ -H "Authorization: Basic $PUSHMESH_KEY"{ "csv_file_url": "https://…/exports/…/players-20260827T150000Z-….csv.gz", "pm_pronto_em_s_estimado": 30, "pm_validade_h": 72 }O arquivo é CSV comprimido, com as colunas
id,external_user_id,notification_types,invalid_identifier,last_active. Baixe a URL: ela responde 404 enquanto o arquivo não fica pronto e 200 quando fica. A URL é a credencial — o arquivo é público para quem tiver o endereço, e ele carrega os seus identificadores de usuário. Não cole em ticket nem em chat. -
Dispare em paralelo para uma fatia pequena, dos dois lados, e compare. Aqui você tem uma vantagem que a comparação costuma revelar: além de
successful(o provedor aceitou), o PushMesh devolverecebidos— a confirmação vinda do próprio aparelho. -
Vire o tráfego quando a base nova cobrir o que você precisa.
-
Desligue o provedor anterior.
Checklist
Servidor
- URL base apontada para
https://api.pushmesh.io - Chave nova no cofre; nenhuma chave no repositório
- Nenhum campo da tabela de recusados no seu payload
-
errorstratado como união de array e objeto - Ramificação por status HTTP, não por texto de erro
-
Idempotency-Keynos envios que não podem duplicar
Aplicativo
- SDK anterior removido
-
@pushmesh/sdkinstalado e inicializado no boot combaseUrl - Parâmetros do Firebase cadastrados no painel (Android)
-
external_user_idenviado no login - Nenhuma chave de API embutida no app
Base
- Caminho escolhido (orgânico, em massa, ou os dois)
- Se em massa: validade dos tokens confirmada e ritmo combinado
- Período de paralelo definido
- Export conferido antes do corte
Onde pedir ajuda
Se algo nesta página não bater com o que você está vendo na prática, é a página
que está errada — e queremos saber. Toda resposta da API traz o cabeçalho
X-Pm-Request-Id; cite esse identificador e a gente encontra a chamada exata.