Pular para o conteúdo

Desenvolvedores

Construa sobre os seus dados de calibração.

A API pública do Axiospec é uma interface REST para seus instrumentos e registros de calibração. Leia e crie instrumentos, registre calibrações no registro com detecção de adulteração e traga seus locais e suas normas para os seus sistemas. Autentique com uma chave de API do espaço de trabalho e pronto.

Primeiros passos

Tudo que você precisa antes da primeira chamada

Leia isto uma vez e depois abra a referência interativa completa para ver o formato exato de requisição e de resposta de cada endpoint.

O que a API faz

A API pública do Axiospec é uma interface REST para o seu programa de calibração. Leia e crie instrumentos, registre calibrações no registro com detecção de adulteração e leia os locais do seu espaço de trabalho e as normas de conformidade que você selecionou.

É um contrato curado e estável, separado dos endpoints internos que os apps web e móvel usam, então sua integração continua funcionando conforme o produto evolui. Toda resposta é JSON.

URL base

Todos os endpoints ficam sob uma única URL base. Cada caminho da referência abaixo é relativo a ela.

https://axiospec.com/api/public/v1

Autenticação

Autentique cada requisição com uma chave de API do espaço de trabalho. Um administrador do espaço de trabalho cria a chave no app, em Configurações e depois Chaves de API. As chaves aparecem uma única vez, na criação, e têm o prefixo ctk_. Guarde a chave como um segredo e nunca a publique em código que roda no cliente.

Envie a chave em toda requisição como bearer token:

Authorization: Bearer ctk_your_api_key

O cabeçalho padrão X-API-Key também é aceito, se você preferir: X-API-Key: ctk_your_api_key. Uma requisição sem chave retorna 401.

Requisito de plano

A API está disponível nos planos Professional e acima. Uma chave de um espaço de trabalho no plano Free ou Starter recebe 403 com o código API_ACCESS_TIER_REQUIRED. Mude o plano do espaço de trabalho para liberá-la.

Escopos

Cada chave é emitida com um escopo. Uma chave de leitura lista e consulta. Uma chave de escrita também cria instrumentos, atualiza instrumentos e registra calibrações (escrita sempre implica leitura).

Uma chave somente leitura que tenta escrever recebe 403 com o código INSUFFICIENT_SCOPE, nomeando o escopo necessário. Emita chaves somente leitura para integrações de relatório, assim elas nunca conseguem alterar um registro.

Limites de requisição e seus cabeçalhos

As requisições são limitadas a 120 por minuto, contadas por chave de API e não por IP, então uma integração não sufoca a outra e várias chaves atrás de uma mesma rede de escritório não são limitadas juntas.

Toda resposta da API carrega a janela atual em cabeçalhos, então você acerta o ritmo sem adivinhar. X-RateLimit-Limit é o teto (120), X-RateLimit-Remaining é quantas requisições restam na janela atual e X-RateLimit-Reset é quantos segundos faltam até a janela reiniciar e Remaining voltar ao limite cheio.

Passar do limite retorna 429 com o código RATE_LIMITED. No 429, o cabeçalho Retry-After (em segundos) diz exatamente quanto esperar. Respeite-o e tente de novo. Ler esses cabeçalhos, em vez de fixar um atraso no código, mantém você rápido quando há folga e educado quando não há.

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 118
X-RateLimit-Reset: 41
Retry-After: 41   (present only on a 429)

Sincronização incremental

Para manter um sistema externo em dia sem reler tudo, puxe só o que mudou desde a sua última execução. Cada coleção aceita o parâmetro updated_since (um timestamp ISO-8601 em UTC) que retorna apenas os registros modificados naquele instante ou depois, além do parâmetro sort, para você percorrer do mais antigo ao mais novo e avançar um marcador conforme anda.

O feed de calibrações de todo o espaço de trabalho, GET /calibrations, foi feito exatamente para isso: devolve todas as calibrações de todos os seus instrumentos em um único fluxo paginado, então você não precisa percorrer instrumento por instrumento. Ordene por updated_at de forma crescente, pagine e guarde o created_at do último registro que viu. O registro é apenas de acréscimo, então um registro de calibração nunca muda depois de escrito e o created_at dele é a hora da última modificação. sort=updated_at aponta para esse instante.

Na execução seguinte, passe o valor guardado como updated_since. Sobreponha a fronteira em um ou dois segundos e descarte duplicatas pelo id do registro, para se proteger de diferenças de relógio. Guarde o marcador só depois de ter processado a página de forma durável.

Instrumentos aceitam os mesmos parâmetros updated_since e sort (GET /instruments), filtrando pela hora da última modificação do instrumento. As linhas da lista não trazem um campo de timestamp, então, para instrumentos, use como próximo updated_since a hora de relógio que você capturou logo antes da requisição. O GET /instruments/{id} de um único instrumento retorna created_at e updated_at, se você precisar deles.

# First run: no watermark, oldest-first, page through.
GET /api/public/v1/calibrations?sort=updated_at&limit=100

# Save the created_at of the LAST record you processed, e.g.
#   watermark = "2026-07-09T15:30:00Z"

# Next run: only what is new since the watermark.
GET /api/public/v1/calibrations?updated_since=2026-07-09T15:30:00Z&sort=updated_at&limit=100

Filtrar instrumentos

GET /instruments aceita filtros para você buscar uma fatia precisa em vez de paginar a lista inteira. asset_tag e serial_number casam com um valor exato (útil para conferir um instrumento contra um registro do ERP). status filtra pelo estado no ciclo de vida, por exemplo active ou retired. site_id restringe a um local.

Dois filtros vêm do estado de calibração. compliance_status filtra pelo token calculado, um entre COMPLIANT, WARNING, NON_COMPLIANT ou NOT_CALIBRATED. next_due_before recebe uma data (YYYY-MM-DD) e retorna os instrumentos cuja próxima calibração vence antes dela, que é a consulta por trás de uma lista de vencimentos próximos ou em atraso. Os filtros se combinam, então você pede instrumentos ativos e não conformes em um local em uma única chamada.

# Everything overdue or due before a date, oldest instruments first:
GET /api/public/v1/instruments?compliance_status=NON_COMPLIANT&next_due_before=2026-08-01

# Reconcile one instrument by its asset tag:
GET /api/public/v1/instruments?asset_tag=MM-0042

Idempotência

Registrar uma calibração é a única escrita que nunca pode ser duplicada: o registro é apenas de acréscimo, então não há como desfazer um envio em dobro. Por isso POST /instruments/{id}/calibrations exige o cabeçalho Idempotency-Key (qualquer string única que você gerar, por exemplo um UUID). Ele é obrigatório, não opcional.

Se uma requisição for interrompida e você tentar de novo com a mesma chave, a API devolve o registro que já escreveu em vez de escrever um segundo. Uma chave ausente retorna 400 com o código IDEMPOTENCY_KEY_REQUIRED. Gere uma chave nova para cada calibração que pretende registrar.

Criar um instrumento (POST /instruments) também respeita um Idempotency-Key, mas aqui ele é opcional. Envie um e uma nova tentativa com a mesma chave devolve o instrumento que a primeira chamada criou, em vez de um duplicado, exatamente como no log de calibração. A única diferença é que a chave não é obrigatória. Se você preferir não gerenciar chaves nas criações, dá para remover duplicatas do seu lado usando o asset_tag ou o serial_number do instrumento, que são únicos dentro de um espaço de trabalho, antes do POST.

Idempotency-Key: 6f9619ff-8b86-d011-b42d-00cf4fc964ff

Certificados

Toda calibração aprovada tem um certificado em PDF com a sua marca. Busque-o com GET /calibrations/{calibration_id}/certificate. A resposta é o próprio PDF (Content-Type application/pdf) como anexo, idêntico byte a byte ao certificado que o app produz, então você pode arquivá-lo ou anexá-lo a uma ordem de serviço.

Um certificado existe apenas para uma calibração aprovada e vigente. Se o registro foi anulado, substituído por um lançamento posterior ou não é certificável por outro motivo, a requisição retorna 404 com o código CERTIFICATE_UNAVAILABLE. Um id de calibração que não é seu, ou que não existe, retorna um 404 simples que não revela nada sobre ele.

curl "https://axiospec.com/api/public/v1/calibrations/CALIBRATION_ID/certificate" \
  -H "Authorization: Bearer ctk_your_api_key" \
  -o certificate.pdf

Desativar um instrumento

Quando um instrumento sai de serviço, desative-o com POST /instruments/{id}/retire (uma chamada de escopo de escrita). É uma baixa suave: o status do instrumento passa a retired e ele sai da lista padrão de ativos, mas nada é apagado e o histórico de calibração dele no registro fica intacto para auditoria. Não existe exclusão definitiva na API.

A chamada devolve o instrumento atualizado. Ela é idempotente: desativar um instrumento já desativado não faz nada e devolve o mesmo registro desativado, então repetir é sempre seguro. Desativar exige uma chave de gerente ou de administrador. Uma chave somente leitura ou de técnico recebe 403.

curl -X POST "https://axiospec.com/api/public/v1/instruments/INSTRUMENT_ID/retire" \
  -H "Authorization: Bearer ctk_your_api_key"

Timestamps e fusos horários

Todo timestamp que a API devolve é ISO-8601 em UTC, terminando em Z, por exemplo 2026-07-09T15:30:00Z. Envie os timestamps do mesmo jeito. Não há respostas com offset nem com hora local para normalizar.

Um campo é uma data simples, não um timestamp: a data de vencimento da calibração de um instrumento. As datas de vencimento são calculadas no fuso horário configurado no seu espaço de trabalho, então uma data de vencimento é o dia do calendário em que ela vence lá, e o filtro next_due_before recebe uma data (YYYY-MM-DD), não um timestamp. Se seus sistemas rodam em outro fuso, compare pela data, não por um instante de meia-noite em UTC.

O envelope de erro

Todo erro, em todo endpoint, tem o mesmo formato JSON: um code legível por máquina, uma message legível por pessoas e, em alguns erros, um objeto details com as especificidades. Ramifique pelo code, nunca pelo texto da message, que pode ser reescrito. O status HTTP continua tendo significado (401 contra 403 contra 404), então use-o também.

Registrar uma calibração também aplica as exigências de campo das normas que o seu espaço de trabalho selecionou. Se um campo obrigatório estiver em branco, a requisição retorna 422 com o código FIELD_REQUIREMENTS_UNMET e um array missing_fields, em que cada item nomeia o campo e qual norma o exige, para você pedir exatamente o que falta.

{
  "code": "FIELD_REQUIREMENTS_UNMET",
  "message": "This calibration is missing fields your workspace's selected standard(s) require: measurement_uncertainty, decision_rule.",
  "details": {
    "missing_fields": [
      { "field": "measurement_uncertainty", "required_by": ["ISO/IEC 17025"] },
      { "field": "decision_rule", "required_by": ["ISO/IEC 17025"] }
    ]
  }
}

Webhooks

Em vez de consultar a API de tempos em tempos para descobrir o que mudou, inscreva um endpoint de webhook uma vez e o Axiospec entrega cada evento na sua URL assim que ele acontece. Você ganha menos latência e muito menos tráfego desperdiçado do que relendo coleções que já viu, e nunca perde uma mudança entre duas consultas.

Inscreva com POST /webhooks, passando uma url e uma lista opcional de tipos de evento a receber. Omita o campo events para receber todos os eventos (o catálogo completo está abaixo). A resposta devolve o segredo de assinatura do endpoint exatamente uma vez e nunca mais, então copie-o direto para o seu cofre de segredos. Gerenciar webhooks exige uma chave de escrita de administrador ou de gerente, porque o endpoint recebe os dados de calibração e de instrumentos do seu espaço de trabalho.

curl -X POST "https://axiospec.com/api/public/v1/webhooks" \
  -H "Authorization: Bearer ctk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/axiospec",
    "events": ["calibration.approved", "calibration.overdue"],
    "description": "Sync approvals into our QMS"
  }'

Cada evento é entregue como um POST HTTP cujo corpo JSON é um envelope fixo: { "id", "type", "created_at", "data" }. O id é o id estável do evento, enviado também no cabeçalho Axiospec-Event-Id, junto de Axiospec-Event-Type, Axiospec-Webhook-Id e Axiospec-Delivery-Attempt. A entrega é pelo menos uma vez, então o mesmo evento pode chegar mais de uma vez (por exemplo depois de uma nova tentativa). Remova duplicatas pelo id do envelope.

Uma entrega conta como falha em qualquer resposta que não seja 2xx, e isso inclui um redirecionamento 3xx: um redirecionamento poderia apontar para um endereço interno, então ele nunca é seguido. Erros de transporte e tempos esgotados também contam como falha. As entregas com falha são repetidas com espera exponencial ao longo de cerca de três dias, e depois disso a entrega é marcada como esgotada. Um endpoint cujas entregas recentes se esgotam todas é desativado automaticamente, para que uma URL morta ou hostil pare de consumir capacidade. Os endpoints precisam ser HTTPS, e uma URL que resolve para um endereço privado ou interno é recusada na inscrição.

Veja o que foi enviado com GET /webhooks/{id}/deliveries, que pagina o log de entregas de um endpoint e aceita um filtro status (pending, failed, succeeded, exhausted). Para repetir uma entrega, use POST /webhooks/{id}/deliveries/{delivery_id}/retry: ele volta a entrega para pending e vencida agora, para que o próximo disparo reenvie, com um novo horizonte de tentativas. Troque o segredo de um endpoint com POST /webhooks/{id}/rotate-secret (o segredo antigo para de validar na hora) e pare as entregas com DELETE /webhooks/{id}.

Catálogo de eventos de webhook

Estes são os tipos de evento que um webhook pode assinar. Liste os que você quer ao se inscrever, ou omita o campo events para receber todos. O mesmo catálogo está em GET /webhooks/events, para descoberta programática.

calibration.created
calibration.approved
calibration.rejected
calibration.corrected
calibration.voided
calibration.due_soon
calibration.overdue
instrument.created
instrument.updated
instrument.retired
instrument.status_changed

Verificar assinaturas de webhook

Toda entrega traz um cabeçalho Axiospec-Signature no formato t=<unix-seconds>,v1=<hex>. Verifique-o antes de confiar em um payload: uma assinatura válida prova que a requisição veio do Axiospec e que o corpo não foi alterado no caminho.

Leia o cabeçalho Axiospec-Signature e separe-o na vírgula, na parte t= (um timestamp Unix em segundos) e na parte v1= (um HMAC em hexadecimal minúsculo). Recalcule o HMAC-SHA256, com a chave do segredo de assinatura do seu endpoint, sobre a string formada pelo timestamp, um ponto literal e o corpo bruto exato da requisição, ou seja f"{t}.{raw_body}". Compare seu digest hexadecimal com o valor v1 usando uma comparação de tempo constante, nunca uma igualdade comum.

Assine os bytes brutos exatamente como recebidos, antes de qualquer parsing ou reserialização de JSON, para que sua entrada bata com o que foi assinado. Recuse a entrega se os digests não baterem, ou se t tiver mais de uns cinco minutos, o que limita por quanto tempo uma requisição capturada poderia ser reenviada contra você.

# Axiospec-Signature: t=1720625400,v1=3f6a9c...e1
t, v1    = split the header on "," then read the "t=" and "v1=" values
signed   = t + "." + raw_request_body        # the exact bytes received
expected = hex(hmac_sha256(secret, signed))  # lowercase hex digest

if not constant_time_equals(expected, v1):
    reject        # signature mismatch, do not trust the payload
if now_unix_seconds() - int(t) > 300:
    reject        # older than ~5 minutes, treat as a possible replay

accept            # then dedupe on the envelope id (Axiospec-Event-Id)

Experimente: dois exemplos

Troque ctk_your_api_key pela sua chave e INSTRUMENT_ID por um id de instrumento da chamada de listagem.

1. Listar instrumentos

curl "https://axiospec.com/api/public/v1/instruments?status=active&limit=25" \
  -H "Authorization: Bearer ctk_your_api_key"

2. Registrar uma calibração

Note o cabeçalho Idempotency-Key obrigatório. Tentar de novo com a mesma chave devolve o registro que já foi escrito em vez de registrar um duplicado.

curl -X POST "https://axiospec.com/api/public/v1/instruments/INSTRUMENT_ID/calibrations" \
  -H "Authorization: Bearer ctk_your_api_key" \
  -H "Idempotency-Key: 6f9619ff-8b86-d011-b42d-00cf4fc964ff" \
  -H "Content-Type: application/json" \
  -d '{
    "result": "PASS",
    "performed_at": "2026-07-09T15:30:00Z",
    "nominal_value": "10.00 V",
    "tolerance": "±0.1%",
    "as_found_reading": "10.01 V",
    "as_left_reading": "10.00 V",
    "certificate_number": "CERT-2026-0142"
  }'

Códigos de erro

Todo código que a API retorna, o status HTTP dele e o que significa. Ramifique pelo código.

Código HTTP Significado
UNAUTHORIZED 401 Sem chave de API, ou a chave é inválida, revogada ou expirada.
API_ACCESS_TIER_REQUIRED 403 O espaço de trabalho está no plano Free ou Starter. A API precisa do Professional ou acima.
INSUFFICIENT_SCOPE 403 Uma chave somente leitura tentou escrever. Emita uma chave com escopo de escrita.
ACCESS_ENDED 403 A chave pertence a um auditor cuja data de término do acesso já passou. Um administrador do espaço de trabalho pode alterar ou remover a data de término.
FORBIDDEN 403 A chave é válida, mas a ação não é permitida para a função dela, por exemplo uma chave que não é de gerente desativando um instrumento.
INSUFFICIENT_ROLE 403 A ação exige função de administrador ou de gerente e a função da chave é menor, por exemplo uma chave de técnico gerenciando um webhook.
NOT_FOUND 404 O recurso não existe, ou está fora do escopo de espaço de trabalho ou de local desta chave. Retornado igual nos dois casos, para nada vazar.
CERTIFICATE_UNAVAILABLE 404 A calibração existe, mas não é certificável (não aprovada, anulada ou substituída).
IDEMPOTENCY_KEY_REQUIRED 400 Um registro de calibração foi enviado sem o cabeçalho Idempotency-Key obrigatório.
INVALID_REQUEST 400 ou 422 Uma requisição malformada ou que falhou em uma validação com código, por exemplo um token de consulta ruim, uma chave de documento inutilizável ou um campo de webhook inválido. A validação de documento e de webhook retorna 422. Uma requisição ruim genérica retorna 400. Ramifique pelo código, o status é secundário.
VALIDATION_ERROR 422 Um ou mais campos falharam na validação. details.errors lista cada campo e o motivo.
FIELD_REQUIREMENTS_UNMET 422 Faltou em uma calibração um campo que as normas que você selecionou exigem. details.missing_fields lista quais.
INVALID_WEBHOOK_URL 422 A url do webhook não serve: ela precisa ser HTTPS, e uma URL que resolve para um endereço privado ou interno é recusada.
CONFLICT 409 A requisição conflita com o estado atual do recurso.
WEBHOOK_LIMIT_REACHED 409 O espaço de trabalho já tem o número máximo de endpoints de webhook. Apague um antes de incluir outro.
DELIVERY_CONFLICT 409 Uma entrega de webhook não pode ser repetida no estado atual, por exemplo reenviar uma entrega que ainda não foi resolvida.
OBJECT_NOT_UPLOADED 409 Um documento foi registrado para uma chave cujo arquivo nunca foi enviado. Envie o arquivo para a URL pré-assinada primeiro, depois registre-o.
METHOD_NOT_ALLOWED 405 Esse método HTTP não é aceito neste caminho.
RATE_LIMITED 429 O limite de 120 por minuto foi ultrapassado. Espere os segundos do Retry-After e tente de novo.
INTERNAL_ERROR 500 Um erro inesperado no servidor. É seguro repetir uma leitura. Repita um registro de calibração com o mesmo Idempotency-Key.

Versionamento e estabilidade

Esta é a v1, refletida no caminho base /api/public/v1. É um contrato curado e estável, mantido de propósito separado dos endpoints internos que os apps usam.

Mudanças aditivas não quebram nada, e nós as fazemos sem mudar a versão: novos endpoints, novos campos opcionais de requisição, novos campos em uma resposta e novos valores em um campo enumerado (por exemplo um novo token de compliance_status). Escreva seu cliente para tolerá-las. Ignore os campos de resposta que você não reconhece em vez de falhar, e trate um valor de enum desconhecido como uma string repassada, não como um erro fatal.

Mudanças que quebram compatibilidade, que nós evitamos, seriam remover ou renomear um campo, mudar o tipo de um campo ou mudar o significado de um endpoint. Se algum dia precisássemos fazer uma, ela sairia em um novo caminho de versão (/api/public/v2), a versão antiga continuaria funcionando por um período de descontinuação comunicado com clareza, e anunciaríamos isso no registro de mudanças abaixo antes de remover qualquer coisa.

Rotação e guarda das chaves

Uma chave aparece por inteiro exatamente uma vez, no momento em que você a cria. Guardamos apenas um hash com sal (SHA-256), nunca a chave em si, então ela não pode ser recuperada nem enviada por e-mail depois. Copie-a para o seu cofre de segredos na hora. O app pode mostrar depois um prefixo não secreto (ctk_AbC1…) para ajudar você a distinguir as chaves, mas nunca a chave inteira de novo.

Para trocar uma chave, crie uma nova, publique-a e depois revogue a antiga. A revogação é imediata e permanente: a chave é desativada (nunca apagada de vez, para o seu histórico de auditoria ficar intacto) e toda requisição posterior com ela retorna 401 UNAUTHORIZED. Emita chaves separadas por integração e chaves somente leitura para o que só gera relatório, assim você troca ou revoga uma sem mexer nas outras.

Registro de mudanças

v1.1 2026-07-10

  • Webhooks: assine eventos (calibração registrada ou aprovada, instrumento com vencimento próximo ou em atraso, e outros) com entrega assinada por HMAC e repetida em caso de falha.
  • Exigências de campo: GET /standards/field-requirements publica os campos de calibração que as normas que você selecionou exigem, para você montar um payload de calibração válido antes do POST.
  • Lista de vencimentos: GET /due retorna os instrumentos a vencer ou em atraso dentro de um horizonte, cada um com o status de conformidade oficial, para agendamento e painéis.
  • Marcas de exclusão: passe include=retired (instrumentos) ou include=voided (calibrações) nos feeds incrementais para que um registro desativado ou anulado apareça no delta em vez de sumir em silêncio. Desligado por padrão. As sincronizações existentes não mudam.
  • Anexos: peça uma URL de upload pré-assinada, anexe um documento a um instrumento (opcionalmente a uma calibração específica), liste os documentos de um registro e busque uma URL de download de vida curta.

v1 2026-07-09

  • Sincronização incremental: updated_since e sort em instrumentos e calibrações, além de um feed GET /calibrations de todo o espaço de trabalho.
  • Filtros de instrumento: asset_tag, serial_number, compliance_status e next_due_before.
  • Busca de certificado: GET /calibrations/{id}/certificate retorna o PDF da calibração.
  • Desativação de instrumento: POST /instruments/{id}/retire dá baixa suave em um instrumento, deixando o registro intacto.
  • Cabeçalhos de limite de requisição (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset e Retry-After em um 429) em toda resposta.
  • Um envelope de erro uniforme ({ code, message, details? }) em todo endpoint.

v1 Versão inicial

  • Ler e criar instrumentos, registrar calibrações no registro com detecção de adulteração e ler locais e normas selecionadas.
  • Autenticação por Bearer ou X-API-Key, escopos de leitura e escrita, acesso a partir do Professional, limite de 120 por minuto e o envelope de lista paginado.

Referência

A referência REST completa

Cada endpoint, parâmetro, corpo de requisição e resposta, gerado a partir da especificação OpenAPI da API e apresentado como uma referência pesquisável em tela cheia.

A referência abre em uma nova aba, com um navegador pesquisável, esquemas de requisição e de resposta e exemplos prontos para copiar em cada operação. Prefere gerar um cliente? A especificação OpenAPI acima alimenta geradores de código em todas as linguagens principais.

---