Pular para o conteúdo principal

APIs e programas externos

Use esta página quando desejar que um programa externo simples, um script, um servidor local ou um serviço de backend controle seu bloqueio Chastify atual.

A maneira mais fácil é criar um token DEV válido para todo o usuário e, em seguida, enviá-lo como um token de portador para os endpoints /api/apps/v1/*.

/api/apps/v1/* destina-se apenas às suas próprias sessões de bloqueio ativas. Se estiver a criar uma extensão pública utilizada por outros utilizadores de Chastify, utilize uma chave de API de desenvolvedor com escopo de aplicativo com /api/extensions/sessions/:sessionId/* e passe o iframe mainToken em x-chastify-main-token.

Criar um token DEV

  1. Abra Chastify.
  2. Acesse Developer API.
  3. Encontre User-wide DEV API keys.
  4. Criar uma chave.
  5. Copie o token imediatamente. Ele só é exibido uma vez.

Use-o em solicitações como esta:

curl https://chastify.net/api/apps/v1/session \
-H "Authorization: Bearer YOUR_DEV_TOKEN"

Tokens DEV:

  • não exigem a criação de uma extensão
  • não expira automaticamente
  • Funciona para sua fechadura ativa atual e para futuras sessões de fechadura ativa.
  • Use sua função na fechadura ativa, seja usuário ou detentor da chave.
  • pode ser revogado na página da API do desenvolvedor.

Trate o token DEV como uma senha. Qualquer pessoa que possua o token pode acessar a API de desenvolvedor em seu nome.

Primeiro passo: Verificar a fechadura atual

Comece por:

GET https://chastify.net/api/apps/v1/session

Exemplo:

curl https://chastify.net/api/apps/v1/session \
-H "Authorization: Bearer YOUR_DEV_TOKEN"

Isso retorna seu contexto de bloqueio atual, função, escopos, tempo restante e lockData.

Auxiliares de bloqueio de dados

GET /api/apps/v1/session inclui lockData, que foi projetado para ser fácil de ler para programas e mecanismos de regras.

Booleanos comuns:

  • frozen
  • unlockable
  • trusted
  • taskAssigned: true quando a fechadura ativa tem um TaskRun aberto

Números comuns:

  • timeLockedSeconds
  • timeRemainingSeconds
  • maxTimeRemainingSeconds
  • taskPoints

Cadeias comuns:

  • lockTitle
  • campos do perfil do usuário
  • Campos do perfil do responsável pela chave

Nota sobre privacidade:

  • wearerLastSeenTimestamp e keyholderLastSeenTimestamp são null quando o usuário desativou o status online.

Pontos finais da ação de bloqueio principal

Esses são os pontos de extremidade que a maioria dos programas externos utiliza para modificar um bloqueio.

POST https://chastify.net/api/apps/v1/action
POST https://chastify.net/api/apps/v1/lock/apply-time
POST https://chastify.net/api/apps/v1/lock/freeze
POST https://chastify.net/api/apps/v1/lock/unfreeze
POST https://chastify.net/api/apps/v1/logs/custom

Todas as solicitações utilizam:

Authorization: Bearer YOUR_DEV_TOKEN
Content-Type: application/json

Adicionar ou remover tempo

Use o endpoint de tempo simples quando você quiser alterar apenas o tempo restante.

Acrescente 10 minutos:

curl -X POST https://chastify.net/api/apps/v1/lock/apply-time \
-H "Authorization: Bearer YOUR_DEV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"deltaSeconds":600}'

Remover 5 minutos:

curl -X POST https://chastify.net/api/apps/v1/lock/apply-time \
-H "Authorization: Bearer YOUR_DEV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"deltaSeconds":-300}'

Congelar e descongelar

Congele por 30 minutos:

curl -X POST https://chastify.net/api/apps/v1/lock/freeze \
-H "Authorization: Bearer YOUR_DEV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"durationSeconds":1800}'

Descongelar:

curl -X POST https://chastify.net/api/apps/v1/lock/unfreeze \
-H "Authorization: Bearer YOUR_DEV_TOKEN"

Ponto final de ação geral

Usar:

POST https://chastify.net/api/apps/v1/action

Tipo físico:

{
"name": "add_time",
"params": 600
}

Exemplo:

curl -X POST https://chastify.net/api/apps/v1/action \
-H "Authorization: Bearer YOUR_DEV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"add_time","params":600}'

Nomes de ações suportados

name suporta:

  • add_time
  • remove_time
  • freeze
  • pillory
  • unfreeze
  • toggle_freeze
  • settings.patch
  • task.assign
  • task.start_timer
  • task.complete
  • hygienic_unlock.start
  • pillory.end

Restrições de ação:

  • As ações de tarefas exigem que o módulo Tarefas esteja ativado na fechadura.
  • hygienic_unlock.start requer que a Abertura Higiênica esteja ativada e que não haja nenhuma sessão de higiene ativa.
  • Os comandos do dispositivo exigem um dispositivo conectado compatível e permissões adequadas.

Exemplos de ações úteis

Remova 15 minutos:

{
"name": "remove_time",
"params": 900
}

Congele por 5 minutos:

{
"name": "freeze",
"params": {
"durationSeconds": 300
}
}

Alternar congelamento:

{
"name": "toggle_freeze",
"params": {
"durationSeconds": 300
}
}

Atribua uma tarefa:

{
"name": "task.assign",
"params": {
"actor": "extension",
"taskText": "Drink water",
"points": 5,
"verificationRequired": false,
"durationSeconds": 900
}
}

Isso cria um código TaskRun para o bloqueio ativo. Se outra execução de tarefa já estiver aberta, a implementação atual cancela a execução antiga e cria uma nova.

Inicie o cronômetro da tarefa ativa:

{
"name": "task.start_timer",
"params": {}
}

Conclua a tarefa ativa:

{
"name": "task.complete",
"params": {
"successful": true
}
}

Isso conclui a abertura mais recente do TaskRun para a fechadura ativa.

Comece um desbloqueio higiênico:

{
"name": "hygienic_unlock.start",
"params": {
"durationSeconds": 900
}
}

Fim do pelourinho ativo:

{
"name": "pillory.end",
"params": {}
}

Registro de bloqueio personalizado

Use isso quando seu programa executar alguma ação e você quiser que ela seja visível no histórico de bloqueios.

POST https://chastify.net/api/apps/v1/logs/custom

Exemplo:

curl -X POST https://chastify.net/api/apps/v1/logs/custom \
-H "Authorization: Bearer YOUR_DEV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"Program check completed","description":"The external rule script ran successfully.","role":"extension"}'

Campos corporais:

  • title: obrigatório
  • description: opcional
  • role: extension, wearer ou keyholder
  • icon: opcional
  • color: cor hexadecimal opcional, por exemplo #ffcc00

Comandos do dispositivo

Os comandos do dispositivo permitem acionar choques e vibrações no dispositivo conectado do usuário.

POST https://chastify.net/api/apps/v1/device-command

Funciona com seu token DEV — sem necessidade de ID de sessão. O servidor resolve automaticamente a fechadura e o usuário a partir do seu token.

curl -X POST https://chastify.net/api/apps/v1/device-command \
-H "Authorization: Bearer YOUR_DEV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"command":"shock.start","params":{"intensityPct":75,"durationSeconds":10}}'

Corpo da solicitação

{
"command": "<command>",
"params": { ... }
}
  • command (string, obrigatório) — o comando do dispositivo a ser executado.
  • params (objeto, opcional) — parâmetros específicos do comando (veja abaixo).

Comandos suportados e seus parâmetros

shock.start

Inicia um choque no dispositivo do usuário.

ParâmetroTipoIntervaloPadrãoDescrição
intensityPctnúmero1–10050Shock intensidade em porcentagem
durationSecondsnúmero1–30060Shock duração em segundos
messagestringMensagem opcional exibida ao usuário
observação

A tensão máxima configurada pelo usuário é sempre aplicada como um limite rígido, independentemente do que você enviar. Para dispositivos Lockink, este é o limite de tensão por dispositivo. Para dispositivos QIUI, este é o limite de tensão shockVolt (escala de 1 a 4). Se você enviar intensityPct: 80, mas o limite do usuário for de 50%, o dispositivo fornecerá apenas 50%.

Exemplo:

curl -X POST https://chastify.net/api/apps/v1/device-command \
-H "Authorization: Bearer YOUR_DEV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"command":"shock.start","params":{"intensityPct":75,"durationSeconds":10,"message":"Extension shock"}}'

shock.stop

Interrompe todos os choques ativos no dispositivo do usuário. Não requer parâmetros.

curl -X POST https://chastify.net/api/apps/v1/device-command \
-H "Authorization: Bearer YOUR_DEV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"command":"shock.stop"}'

vibration.start

Inicia uma vibração no dispositivo do usuário.

ParâmetroTipoIntervaloPadrãoDescrição
intensityPctnúmero1–10050Intensidade de vibração em porcentagem
durationSecondsnúmero1–30030Duração da vibração em segundos
frequencyPctnúmero1–10050Frequência de vibração em porcentagem
messagestringMensagem opcional exibida ao usuário

Exemplo:

curl -X POST https://chastify.net/api/apps/v1/device-command \
-H "Authorization: Bearer YOUR_DEV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"command":"vibration.start","params":{"intensityPct":60,"durationSeconds":15,"frequencyPct":40}}'

vibration.stop

Interrompe todas as vibrações ativas. Não requer parâmetros.

curl -X POST https://chastify.net/api/apps/v1/device-command \
-H "Authorization: Bearer YOUR_DEV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"command":"vibration.stop"}'

all.stop

Interrompe toda a atividade do dispositivo (choques, vibrações, etc.). Não requer parâmetros.

curl -X POST https://chastify.net/api/apps/v1/device-command \
-H "Authorization: Bearer YOUR_DEV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"command":"all.stop"}'

shock.random.set

Ativa ou desativa o modo de choque aleatório no dispositivo do usuário.

ParâmetroTipoIntervaloPadrãoDescrição
enabledbooleanoAtivar (true) ou desativar (false) o modo aleatório
minIntensityPctnúmero1–10020Percentagem mínima de intensidade de choque
maxIntensityPctnúmero1–10080Percentagem máxima de intensidade do choque
messagestringMensagem opcional exibida ao usuário
observação

A voltagem máxima configurada para o usuário é sempre o limite máximo. Se você definir maxIntensityPct: 80, mas o limite do usuário for 50, o máximo real será 50%.

Exemplo:

curl -X POST https://chastify.net/api/apps/v1/device-command \
-H "Authorization: Bearer YOUR_DEV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"command":"shock.random.set","params":{"enabled":true,"minIntensityPct":25,"maxIntensityPct":75}}'

shock.berserk.set

Ativa ou desativa o modo de choque berserk no dispositivo do usuário.

ParâmetroTipoIntervaloPadrãoDescrição
enabledbooleanoAtivar (true) ou desativar (false) o modo berserk
messagestringMensagem opcional exibida ao usuário

Exemplo:

curl -X POST https://chastify.net/api/apps/v1/device-command \
-H "Authorization: Bearer YOUR_DEV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"command":"shock.berserk.set","params":{"enabled":true}}'

Os comandos do dispositivo dependem da fechadura ativa, da disponibilidade do dispositivo e da política de comandos.

Seleção de dispositivo

Não é necessário especificar um ID de dispositivo ou tipo de dispositivo. Cada usuário só pode ter um dispositivo ativo por vez — o servidor o identifica automaticamente.

O código deviceType é retornado na resposta para que você saiba qual dispositivo recebeu o comando.

Respostas

Sucesso (200)

{
"ok": true,
"command": "shock.start",
"result": {
"success": true,
"message": "Shock command sent (10s)",
"deviceType": "lockink-aa-a1012"
},
"active": {
"shock": true,
"vibration": false
}
}
CampoDescrição
oktrue quando o comando foi aceito
commandO comando que foi executado
result.successtrue se o dispositivo confirmou o comando
result.messageMensagem de status legível por humanos
result.deviceTypeTipo de dispositivo do usuário (ex.: lockink-aa-a1012, cellmate-pro-3)
active.shockIndica se há algum choque ativo no dispositivo do usuário
active.vibrationIndica se há vibração ativa no dispositivo do usuário

Nota: Os comandos shock.start e vibration.start aguardam até 25 segundos para que o dispositivo confirme o recebimento. Os comandos de parada (shock.stop, vibration.stop, all.stop) retornam imediatamente.

Falha

Todas as falhas retornam HTTP 4xx/5xx com um corpo JSON:

{
"success": false,
"error": "no_device",
"message": "No shock-capable device found for user"
}
CenárioHTTPerrormessage
Fechadura não encontrada ou nenhuma fechadura ativa404lock_not_foundNo active lock found
O bloqueio não está mais ativo409lock_endedThe lock is no longer active
Sessão do usuário ausente400no_wearerMissing wearer session
durationSeconds ausente ou inválido400invalid_paramsdurationSeconds is required for server-initiated shocks
Modo aleatório/berserk em dispositivo não compatível400unsupported_deviceRandom mode only supported on Lockink AA-A1012
O usuário não concedeu consentimento para choque403not_authorizedUser not eligible for shock commands (consent or device check failed)
Nenhum dispositivo compatível com choque/vibração emparelhado404no_deviceNo shock-capable device found for user
Dispositivo offline (sem conexão de soquete)404device_offlineNo active device socket found for user
O dispositivo não confirmou a tempo (25s)504device_timeoutDevice verification timeout
Falha não reconhecida ou não tratada400command_failedcommand_failed

Quando disponível, deviceType é incluído na resposta.

Explicação dos cenários de falha mais comuns

cuidado

O dispositivo deve estar conectado através do aplicativo móvel.

O uso do Shock e suas vibrações requer que o usuário tenha um dispositivo Bluetooth compatível emparelhado e o aplicativo móvel Chastify em execução no celular. O aplicativo mantém a conexão de socket em tempo real que envia os comandos para o dispositivo. Se o aplicativo for fechado ou o celular estiver sem internet, os comandos falharão.

no_device — O usuário não emparelhou um dispositivo com capacidade de detecção de choque (por exemplo, CellMate Pro 3, Cagink Metal, Lockink AA-A1012) no aplicativo Chastify. Os dispositivos devem ser emparelhados, estar ativos e totalmente configurados para que a API possa acessá-los.

device_offline — O dispositivo do usuário está emparelhado, mas o Serviço Nativo Shock não está ativado ou não está em execução no aplicativo Android. Esta é a falha mais comum — o usuário precisa ter o Serviço Nativo Shock ativado nas configurações do aplicativo Android para que os comandos sejam entregues de forma confiável.

device_timeout — O comando foi enviado para o aplicativo móvel, mas o aplicativo não confirmou que o dispositivo Bluetooth o recebeu em 25 segundos. Isso geralmente significa que o Bluetooth do usuário está desligado, o dispositivo está fora do alcance ou está desligado. Dispositivos Lockink entram em modo de espera após apenas 3 minutos de inatividade, a menos que a função keep-alive esteja ativada — e mesmo assim, as otimizações de bateria do fabricante do telefone podem restringir o Bluetooth em segundo plano e impedir que o keep-alive funcione corretamente.

not_authorized — O usuário não concedeu consentimento explícito para choques nas configurações do dispositivo. Este é um requisito de segurança — mesmo com um dispositivo emparelhado, o usuário deve optar por permitir comandos remotos de choque/vibração.

unsupported_device — Os modos aleatório e berserk estão disponíveis apenas no Lockink AA-A1012 (Beesting). Outros dispositivos, como o CellMate Pro 3 ou o Cagink Metal, não são compatíveis com esses modos.

Erros comuns

  • 401 missing_token: enviar Authorization: Bearer YOUR_DEV_TOKEN.
  • 401 invalid_token: o token está incorreto ou foi copiado incorretamente.
  • 401 revoked_token: a chave DEV foi revogada.
  • 403 insufficient_scope: a chave não possui o escopo necessário.
  • 409 no_active_lock_session: o usuário não possui nenhum bloqueio ativo no momento.
  • 409 lock_ended: o bloqueio resolvido não está mais ativo.
informação

Entendendo device_timeout (504)

O erro device_timeout significa que o servidor enviou o comando de choque para o aplicativo Android do usuário, mas o aplicativo não confirmou o recebimento pelo dispositivo Bluetooth em 25 segundos. Este é o erro mais complexo — veja o que acontece no lado do Android:

  1. Servidor → Aplicativo: O comando é transmitido via Socket.IO para o serviço nativo Shock em execução no telefone do usuário.
  2. Aplicativo → Dispositivo: O aplicativo se conecta ao dispositivo via Bluetooth Low Energy (BLE) e envia o comando de choque. Para dispositivos QIUI, isso envolve primeiro obter um token da API do fabricante do dispositivo e, em seguida, escrever o comando BLE. Para dispositivos Lockink, o comando BLE é enviado diretamente.
  3. Aplicativo → Servidor: O aplicativo envia uma confirmação de volta para o servidor.

O tempo limite de 25 segundos começa na etapa 1. Um tempo limite na etapa 2 pode ocorrer porque:

  • O Bluetooth está desligado ou o dispositivo está fora do alcance do telefone do usuário.
  • O dispositivo está em modo de hibernação. Os dispositivos Lockink entram em hibernação profunda após apenas 3 minutos de inatividade BLE. O recurso de manter a conexão ativa pode evitar isso, mas as otimizações de bateria dos fabricantes (Samsung, Xiaomi, Huawei, etc.) podem encerrar as conexões Bluetooth em segundo plano, tornando a função de manter a conexão ativa instável.
  • Falha na conexão BLE. O aplicativo tenta novamente a conexão BLE, mas se o dispositivo não responder, a conexão expira.
  • Bloqueio de segurança. O aplicativo possui um sistema de segurança integrado que bloqueia os choques se o usuário for detectado em movimento (por exemplo, dirigindo ou pedalando), com base no reconhecimento de atividade e na velocidade do GPS. Se o usuário estiver em movimento, o choque é bloqueado silenciosamente e relatado como falha.
  • Falha na obtenção do token QIUI. Para dispositivos CellMate Pro 3 e Cagink, o aplicativo precisa obter um token de comando da API em nuvem do QIUI antes de enviar o comando BLE. Se o telefone do usuário não tiver internet ou se a API do QIUI estiver lenta ou inacessível, essa etapa pode consumir a maior parte do intervalo de 25 segundos.

Padrão prático

A maioria dos programas externos segue este fluxo:

  1. Ligue para GET /api/apps/v1/session.
  2. Leia lockData.
  3. Decida o que deve acontecer.
  4. Chame /api/apps/v1/action ou um dos endpoints de bloqueio mais simples.
  5. Opcionalmente, escreva um log personalizado com /api/apps/v1/logs/custom.

Por exemplo, um script pode verificar timeRemainingSeconds, adicionar o tempo em que uma regra falha e, em seguida, escrever um log personalizado explicando o que aconteceu.