Como integrar a API Tuya Cloud: guia passo a passo
Do projeto de nuvem ao primeiro comando enviado a um dispositivo. Este guia cobre a sequência completa — credenciais, data center, vínculo de conta, token, assinatura HMAC-SHA256, leitura de estado e envio de comandos — e os erros que travam praticamente toda integração de primeira viagem.
A API Tuya Cloud — oficialmente a Tuya OpenAPI — é o caminho servidor a servidor para ler, comandar e automatizar dispositivos da plataforma Tuya a partir do seu próprio software. Ela é bem documentada, mas a documentação é enorme e organizada por referência, não por percurso. Quem chega pela primeira vez costuma perder dias em três ou quatro detalhes que não aparecem em destaque.
Este guia é o percurso. A ordem importa: pular uma etapa faz a seguinte falhar com uma mensagem que não explica o motivo real.
A Tuya evolui os endpoints e reorganiza os planos com frequência. Os caminhos e nomes aqui refletem o comportamento estável da plataforma, mas confirme sempre contra o console e a documentação oficial da sua conta antes de fixar algo em produção.
1. O que você precisa antes de escrever código
A integração pela API Cloud não pareia dispositivos. Ela enxerga dispositivos que já foram instalados e vinculados a uma conta. Então você precisa de três coisas prontas:
- Os dispositivos já pareados em um aplicativo Tuya Smart ou Smart Life.
- Uma conta no Tuya IoT Development Platform (o console de desenvolvedor, distinto da conta do aplicativo).
- Saber em qual data center a conta do aplicativo vive — o detalhe que mais causa confusão.
Se o seu caso exige que o usuário final instale os dispositivos pelo seu app, a API Cloud sozinha não resolve — você vai precisar do App SDK. Comparamos os dois caminhos em detalhe aqui.
2. Criar o projeto de nuvem e pegar as credenciais
No console de desenvolvedor, crie um projeto do tipo de desenvolvimento em nuvem. Na criação você escolhe o setor de atuação e, principalmente, a região de disponibilidade. Ao terminar, o projeto expõe duas credenciais na aba de visão geral:
Access ID— também chamado declient_id.Access Secret— o segredo usado para assinar cada requisição. Nunca vai para o front-end.
Assinar os produtos de API
Este é o primeiro tropeço clássico. Ter o projeto não dá acesso a nada: cada família de endpoints é um produto que precisa ser assinado e depois autorizado para aquele projeto específico. Os essenciais para começar costumam ser os de gestão de dispositivo e de estado, além do serviço de autorização.
A Tuya oferece um período de avaliação gratuito, em geral prorrogável uma vez. Se você assinar o produto mas esquecer de autorizá-lo no projeto, as chamadas voltam com erro de permissão — e a mensagem não diz que o problema é esse.
3. Escolher o data center certo
A Tuya opera regiões independentes, e a conta do usuário do aplicativo pertence a uma delas, definida quando a conta foi criada, com base no país informado. Se o seu código apontar para a região errada, a autenticação até funciona — e a lista de dispositivos volta vazia, sem nenhuma indicação do motivo.
| Região | Endpoint base |
|---|---|
| América — Oeste (padrão para o Brasil na maioria dos casos) | https://openapi.tuyaus.com |
| Europa — Central | https://openapi.tuyaeu.com |
| China | https://openapi.tuyacn.com |
| Índia | https://openapi.tuyain.com |
Contas brasileiras normalmente caem na região das Américas. Mas "normalmente" não é garantia: se a conta foi criada com outro país selecionado, ela ficou em outro data center e não há como movê-la. Na dúvida, teste as duas mais prováveis — a que devolver dispositivos é a certa.
4. Vincular a conta do aplicativo ao projeto
Com o projeto criado, os dispositivos ainda não aparecem. É preciso vincular a conta do app onde eles estão cadastrados. No console isso fica na área de dispositivos do projeto, na opção de associação por conta de aplicativo: o console mostra um QR Code que você lê com o próprio aplicativo Tuya Smart ou Smart Life, autenticado com a conta dona dos dispositivos.
Esse vínculo é frágil por natureza. Se alguém desvincular a conta, trocar a senha de forma que invalide a sessão ou remover a associação no console, todos os dispositivos somem de uma vez da sua integração. O sintoma no seu sistema é uma lista vazia — não um erro.
Trate lista vazia como estado anômalo e alerte. Em projetos de produção, isso poupa horas de investigação no dia em que acontecer.
5. A assinatura HMAC-SHA256
Toda chamada à OpenAPI é assinada. É aqui que a maioria das integrações trava, porque a assinatura do pedido de token é ligeiramente diferente da assinatura das demais chamadas — e a diferença é fácil de não perceber.
A montagem tem duas partes. Primeiro, a string canônica da requisição:
stringToSign =
MÉTODO + "\n" + // GET, POST…
SHA256(corpo) + "\n" + // hex minúsculo; corpo vazio também tem hash
cabeçalhosAssinados + "\n" + // normalmente vazio
caminho + query // query com parâmetros ordenados alfabeticamente
Depois, a string que efetivamente vai para o HMAC:
# Requisição de TOKEN — sem access_token
str = client_id + t + nonce + stringToSign
# Demais requisições — COM access_token
str = client_id + access_token + t + nonce + stringToSign
sign = HMAC_SHA256(str, access_secret) em hexadecimal MAIÚSCULO
O t é o instante atual em milissegundos — não em segundos. O
nonce é opcional; se você não usar, ele entra como string vazia na concatenação, e não
como a palavra "null". O hash do corpo vazio não é vazio: é o SHA-256 da string vazia.
Implementação de referência em Python
import hashlib, hmac, time, json, requests
BASE = "https://openapi.tuyaus.com"
CLIENT = "seu_access_id"
SECRET = "seu_access_secret"
EMPTY_BODY_HASH = hashlib.sha256(b"").hexdigest()
def _sign(method, path, body="", token=""):
t = str(int(time.time() * 1000))
content_hash = hashlib.sha256(body.encode()).hexdigest() if body else EMPTY_BODY_HASH
string_to_sign = f"{method}\n{content_hash}\n\n{path}"
payload = CLIENT + token + t + string_to_sign
sign = hmac.new(
SECRET.encode(), payload.encode(), hashlib.sha256
).hexdigest().upper()
headers = {
"client_id": CLIENT,
"sign": sign,
"t": t,
"sign_method": "HMAC-SHA256",
}
if token:
headers["access_token"] = token
if body:
headers["Content-Type"] = "application/json"
return headers
def get_token():
path = "/v1.0/token?grant_type=1"
r = requests.get(BASE + path, headers=_sign("GET", path))
data = r.json()
if not data.get("success"):
raise RuntimeError(data)
return data["result"]["access_token"]
def api_get(path, token):
r = requests.get(BASE + path, headers=_sign("GET", path, token=token))
return r.json()
def api_post(path, token, payload):
body = json.dumps(payload, separators=(",", ":"))
r = requests.post(
BASE + path, headers=_sign("POST", path, body=body, token=token), data=body
)
return r.json()
O corpo usado para calcular o hash tem que ser byte a byte idêntico ao corpo
enviado. Serializar o JSON duas vezes, ou deixar a biblioteca HTTP reserializar o dicionário,
produz espaçamento diferente e derruba a assinatura. Serialize uma vez, use a mesma string nos
dois lugares — é o que o separators e o data=body garantem acima.
6. Listar dispositivos e ler o estado
Com o token na mão, o primeiro objetivo é enxergar os dispositivos. O identificador do dispositivo
(device_id) é a chave de tudo daqui pra frente, e você pode obtê-lo pelo console, na
lista de dispositivos do projeto, ou pelas APIs de listagem.
token = get_token()
# metadados do dispositivo
print(api_get(f"/v1.0/devices/{DEVICE_ID}", token))
# estado atual — a lista de data points
print(api_get(f"/v1.0/devices/{DEVICE_ID}/status", token))
# o que este modelo aceita como comando
print(api_get(f"/v1.0/devices/{DEVICE_ID}/functions", token))
O endpoint de functions é o mais subestimado dos três. Ele responde exatamente quais comandos aquele modelo aceita, com o tipo e a faixa de cada valor. Consultá-lo uma vez por modelo, durante o desenvolvimento, evita a maior parte das tentativas às cegas.
Data points: o conceito central
A Tuya não expõe "ligar a lâmpada". Ela expõe data points: pares de código e
valor que representam cada função do dispositivo. Uma tomada simples pode ter
switch_1 booleano; um medidor pode ter cur_power, cur_voltage
e cur_current; uma lâmpada colorida tem modo, brilho, temperatura e cor, cada um com
sua própria escala.
Esses códigos não são padronizados entre fabricantes. Dois dispositivos da mesma
categoria, de marcas diferentes, podem usar códigos distintos para a mesma função — e escalas
diferentes para o mesmo valor. Fixar switch_1 no código funciona até chegar o modelo
que usa outro identificador.
A arquitetura correta é uma camada de normalização: um mapa por modelo que traduz os data points brutos para o vocabulário do seu domínio. Custa uma tarde para escrever e economiza a reescrita que acontece quando o cliente compra o segundo lote de outro fornecedor.
7. Enviar comandos
api_post(
f"/v1.0/devices/{DEVICE_ID}/commands",
token,
{"commands": [{"code": "switch_1", "value": True}]},
)
Duas coisas importam aqui e costumam ser ignoradas. A primeira: a resposta de sucesso significa que a nuvem aceitou o comando, não que o dispositivo executou. Se o aparelho estiver offline, a chamada retorna sucesso e nada acontece no mundo físico. Confirmação real exige reconsultar o estado ou receber o evento correspondente.
A segunda: comandos em lote no mesmo array são mais eficientes e mais confiáveis do que várias chamadas seguidas — especialmente quando você precisa mudar modo e valor de uma vez, e a ordem importa.
8. Tempo real: pare de fazer polling
O reflexo natural é consultar o endpoint de status em laço. Funciona com cinco dispositivos e desmorona com quinhentos: estoura a cota de requisições, gera custo desnecessário e ainda entrega dado atrasado.
O caminho correto é o serviço de mensageria da Tuya, que publica eventos de mudança de estado, de conexão e de alarme. Você assina a fila do seu projeto e recebe os eventos conforme acontecem. Dois pontos práticos:
- As mensagens vêm cifradas, com chave derivada do seu Access Secret. Você precisa decifrar antes de usar.
- A entrega é ao menos uma vez. Eventos podem chegar duplicados ou fora de ordem — seu processamento precisa ser idempotente e usar o carimbo de tempo do evento, não o de recebimento.
Um bom desenho combina os dois: eventos para reagir em tempo real, e uma reconciliação periódica de baixa frequência para corrigir divergências acumuladas.
9. Os erros mais comuns e o que eles realmente significam
| Sintoma | Causa provável |
|---|---|
| Assinatura inválida | Timestamp em segundos em vez de milissegundos; corpo serializado duas vezes; esquecer o access_token na concatenação das chamadas de negócio; relógio do servidor fora de sincronia. |
| Sem permissão para a API | O produto de API não foi assinado, ou foi assinado mas não autorizado para este projeto. Confira na aba de serviços do projeto. |
| Token inválido ou expirado | O token tem validade curta. Sem renovação automática, a integração funciona no teste e falha depois. Trate a expiração como caminho normal, não como exceção. |
| Lista de dispositivos vazia | Data center errado, ou vínculo da conta do aplicativo desfeito. Quase sempre um dos dois — dificilmente é o código. |
| Dispositivo não encontrado | O device_id pertence a outra conta ou a outra região; ou o aparelho foi removido do app e o vínculo caiu junto. |
| Comando aceito, nada acontece | Dispositivo offline, ou o código do data point não existe naquele modelo. Consulte o endpoint de funções do dispositivo específico. |
10. O que separa um teste de uma integração de produção
O código acima liga tudo e é suficiente para provar o conceito. Para colocar no ar e dormir tranquilo, faltam seis coisas:
- Cache e renovação de token com proteção contra corrida — várias requisições simultâneas não podem disparar várias renovações.
- Retentativa com recuo exponencial para falhas temporárias e limites de taxa, com teto e desistência.
- Normalização de data points por modelo, isolando o resto do sistema das particularidades de cada fabricante.
- Idempotência no consumo de eventos, com deduplicação por identificador e carimbo de tempo.
- Observabilidade — registro das chamadas, latência, taxa de erro por endpoint e alerta quando dispositivos ficam offline em bloco.
- Segredos fora do código, com rotação prevista. O Access Secret assina tudo; vazá-lo entrega o controle dos dispositivos.
Conclusão
A API Tuya Cloud não é difícil — ela é específica. Praticamente todo o tempo perdido em uma primeira integração se concentra em quatro pontos: a região errada, o produto de API não autorizado, a assinatura montada com uma diferença sutil e o vínculo de conta que ninguém sabia que existia. Resolvidos esses, o resto é uma API REST comum.
A partir daí o trabalho interessante começa: transformar leitura de sensor em decisão, cruzar telemetria com dados do negócio e automatizar o que hoje alguém faz olhando um painel. Escrevemos sobre esse próximo passo aqui.
Precisa dessa integração pronta e funcionando?
A NasteSoft faz integração Tuya de ponta a ponta — e também assume projetos existentes que estão instáveis em produção.