Skip to content

API REST — referência

InnoLabs edited this page Aug 10, 2026 · 1 revision

Mapa de endpoints

Método Caminho Auth Descrição
POST /api/v1/auth/token/ Não Login → access + refresh
POST /api/v1/auth/token/refresh/ Não Novo access a partir do refresh
POST /api/v1/reference/ Sim Marcar referências a partir de texto / lista
GET /api/v1/reference/docx/ Sim Corpo vazio {} (form browsable)
POST /api/v1/reference/docx/ Sim Upload .docx, extrair secção e marcar
GET /api/v1/ Root do router somente se DEBUG (DefaultRouter)
GET /api/v1/reference/ Sim Rota “list” do router sem implementação → tipicamente 405

Convenções

Header de autenticação

Authorization: Bearer <access_token>

Formatos de saída (type)

Valor Significado Chave principal na resposta
json (default) Objeto marcado (dict) em data references ou message
xml String XML element-citation em data references ou message
jats Monta <ref-list>...</ref-list> ref_list

Entrada de referências (texto)

O campo references aceita:

  • string com uma referência por linha;
  • lista JSON ["Ref A", "Ref B"];
  • número (convertido para string) — uso raro.

Linhas vazias são ignoradas (parse_reference_list).

Cache

Referências já marcadas (mesmo texto normalizado → mesmo checksum SHA-256) são reutilizadas da base Reference / ElementCitation, sem nova chamada ao Llama.

Códigos HTTP frequentes

Código Quando
200 Sucesso
400 Validação / sem referências / DOCX inválido
401 / 403 Sem autenticação ou token inválido
405 Método não permitido (ex.: GET em /reference/ sem list)
503 Llama indisponível / desligado / mal configurado

Autenticação

POST /api/v1/auth/token/

Obtém o par JWT.

curl -s -X POST "${BASE_URL}/api/v1/auth/token/" \
  -H "Content-Type: application/json" \
  -d '{"username":"editor","password":"segredo"}'

Body

Campo Tipo Obrigatório
username string sim
password string sim

200

{
  "access": "<jwt>",
  "refresh": "<jwt>"
}

POST /api/v1/auth/token/refresh/

curl -s -X POST "${BASE_URL}/api/v1/auth/token/refresh/" \
  -H "Content-Type: application/json" \
  -d '{"refresh":"<refresh_jwt>"}'

200

{
  "access": "<novo_access_jwt>"
}

Mais exemplos: autenticacao.md.


Marcação por texto

POST /api/v1/reference/

ViewSet createapi_reference.
Permissão: IsAuthenticated.
Content-Type: application/json ou form.

Campos (ReferenceMarkRequestSerializer)

Campo Tipo Default Descrição
references string | lista | número Texto a marcar
type json | xml | jats json Formato de saída

Exemplo A — uma referência (string) → resposta message

Quando a entrada é string e resulta em uma referência marcada, a API responde com message (comportamento atual do ViewSet):

curl -s -X POST "${BASE_URL}/api/v1/reference/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -H "Content-Type: application/json" \
  -d '{
    "references": "Smith J. Example title. Nature. 2024;600:1-10.",
    "type": "json"
  }'

200 (forma típica)

{
  "message": "reference: {'reftype': 'journal', 'title': '...', ...}"
}

Exemplo B — várias referências (lista JSON) → references[]

curl -s -X POST "${BASE_URL}/api/v1/reference/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -H "Content-Type: application/json" \
  -d '{
    "references": [
      "Smith J. Example title. Nature. 2024;600:1-10.",
      "Doe A, Roe B. Another paper. Science. 2023;380:100-105. https://doi.org/10.1126/science.xxxx"
    ],
    "type": "json"
  }'

200

{
  "references": [
    {
      "mixed_citation": "Smith J. Example title. Nature. 2024;600:1-10.",
      "data": {
        "reftype": "journal",
        "title": "Example title",
        "authors": [ ... ],
        "source": "Nature",
        "year": "2024",
        "vol": 600,
        "doi": null
      }
    },
    {
      "mixed_citation": "Doe A, Roe B. Another paper. Science. 2023;380:100-105. https://doi.org/10.1126/science.xxxx",
      "data": { "...": "..." }
    }
  ]
}

Os campos dentro de data dependem do modelo e do enriquecimento; o exemplo acima ilustra a forma, não um schema rígido OpenAPI.

Exemplo C — várias linhas numa única string

curl -s -X POST "${BASE_URL}/api/v1/reference/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'EOF'
{
  "references": "Smith J. Nature. 2024;600:1-10.\nDoe A. Science. 2023;380:100-105.",
  "type": "json"
}
EOF

Como a entrada é string mas há duas linhas → resposta com chave references (array).

Exemplo D — saída XML (element-citation)

curl -s -X POST "${BASE_URL}/api/v1/reference/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -H "Content-Type: application/json" \
  -d '{
    "references": [
      "Smith J. Example title. Nature. 2024;600:1-10."
    ],
    "type": "xml"
  }'

200 (trecho)

{
  "references": [
    {
      "mixed_citation": "Smith J. Example title. Nature. 2024;600:1-10.",
      "data": "<element-citation publication-type=\"journal\">...</element-citation>"
    }
  ]
}

Exemplo E — saída JATS (ref-list)

Usado pelos scripts de acurácia e por integrações que precisam do bloco SPS pronto.

curl -s -X POST "${BASE_URL}/api/v1/reference/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -H "Content-Type: application/json" \
  -d '{
    "references": [
      "Smith J. Example title. Nature. 2024;600:1-10.",
      "Doe A. Another paper. Science. 2023;380:100-105."
    ],
    "type": "jats"
  }'

200

{
  "ref_list": "<ref-list><title>References</title><ref id=\"B1\">...</ref><ref id=\"B2\">...</ref></ref-list>"
}

Internamente a view marca como xml e chama build_ref_list.

Exemplo F — form-urlencoded (Browsable / curl)

curl -s -X POST "${BASE_URL}/api/v1/reference/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "references=Smith J. Nature. 2024." \
  --data-urlencode "type=json"

Erros — texto

Sem referências úteis

curl -s -X POST "${BASE_URL}/api/v1/reference/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -H "Content-Type: application/json" \
  -d '{"references":"","type":"json"}'
{"error": "No references provided"}

Body inválido / serializer

{"references": ["Este campo é obrigatório."]}

(ou mensagens equivalentes do DRF)

Llama indisponível

{"error": "Llama model is not available: ..."}

HTTP 503.

Não autenticado

curl -s -o /dev/null -w "%{http_code}\n" \
  -X POST "${BASE_URL}/api/v1/reference/" \
  -H "Content-Type: application/json" \
  -d '{"references":["Ref A"],"type":"json"}'

Marcação a partir de DOCX

GET /api/v1/reference/docx/

Devolve {} (200) para o formulário da Browsable API.

curl -s -X GET "${BASE_URL}/api/v1/reference/docx/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -H "Accept: application/json"
{}

Útil também como probe de token (como em scripts/reference_accuracy.py): se HTTP ≠ 401, o token ainda é aceite.


POST /api/v1/reference/docx/

Parsers: MultiPartParser, FormParser.
Extrai texto do .docx, isola a secção de referências e reutiliza o mesmo pipeline de marcação.

Campos (ReferenceDocxRequestSerializer)

Campo Tipo Default Descrição
file ficheiro .docx Obrigatório; rejeita outros extensões e ficheiro vazio
type json | xml | jats json Formato de saída

Headings reconhecidos

Regex (case-insensitive), linha isolada, com número opcional:

  • References / Reference
  • Referências / Referência / Referencias / Referencia
  • Bibliography / Bibliografia

Exemplos válidos: References, 5. Referências, Bibliografia.

Cada parágrafo após o heading vira uma referência.

Exemplo G — DOCX → JSON

curl -s -X POST "${BASE_URL}/api/v1/reference/docx/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -F "file=@/caminho/para/artigo.docx" \
  -F "type=json"

200

{
  "references": [
    {
      "mixed_citation": "Smith J. Nature. 2024.",
      "data": { "reftype": "journal", "title": "..." }
    }
  ]
}

Exemplo H — DOCX → JATS (homologação / accuracy)

curl -s -X POST "${BASE_URL}/api/v1/reference/docx/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -F "file=@fixtures/bn-2025-1828/bn-2025-1828.docx" \
  -F "type=jats" \
  -o /tmp/ref_list_response.json

python3 -c 'import json; print(json.load(open("/tmp/ref_list_response.json"))["ref_list"][:500])'

Exemplo I — DOCX → XML

curl -s -X POST "${BASE_URL}/api/v1/reference/docx/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -F "file=@artigo.docx" \
  -F "type=xml" | python3 -m json.tool

Exemplo J — Content-Type explícito no ficheiro

curl -s -X POST "${BASE_URL}/api/v1/reference/docx/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -F "file=@artigo.docx;type=application/vnd.openxmlformats-officedocument.wordprocessingml.document" \
  -F "type=jats"

Erros — DOCX

Extensão inválida

curl -s -X POST "${BASE_URL}/api/v1/reference/docx/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -F "file=@notas.txt" \
  -F "type=json"
{"file": ["Only .docx files are accepted."]}

Sem secção de referências

{"error": "No references section found in DOCX"}

Ficheiro ilegível

{"error": "Could not read DOCX file"}

Sem autenticação

HTTP 401 ou 403.


Fluxos curl ponta a ponta

Homologação: login → marcar texto → refrescar → DOCX

#!/usr/bin/env bash
set -euo pipefail

BASE_URL="https://tools-hml.scielo.org"
USER="${JWT_USERNAME}"
PASS="${JWT_PASSWORD}"
DOCX_PATH="${1:-artigo.docx}"

TOKENS=$(curl -s -X POST "${BASE_URL}/api/v1/auth/token/" \
  -H "Content-Type: application/json" \
  -d "{\"username\":\"${USER}\",\"password\":\"${PASS}\"}")
ACCESS=$(echo "$TOKENS" | python3 -c 'import sys,json; print(json.load(sys.stdin)["access"])')
REFRESH=$(echo "$TOKENS" | python3 -c 'import sys,json; print(json.load(sys.stdin)["refresh"])')

echo "== texto / json =="
curl -s -X POST "${BASE_URL}/api/v1/reference/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -H "Content-Type: application/json" \
  -d '{"references":["Smith J. Nature. 2024;600:1-10."],"type":"json"}' \
  | python3 -m json.tool

echo "== refresh =="
ACCESS=$(curl -s -X POST "${BASE_URL}/api/v1/auth/token/refresh/" \
  -H "Content-Type: application/json" \
  -d "{\"refresh\":\"${REFRESH}\"}" \
  | python3 -c 'import sys,json; print(json.load(sys.stdin)["access"])')

echo "== docx / jats =="
curl -s -X POST "${BASE_URL}/api/v1/reference/docx/" \
  -H "Authorization: Bearer ${ACCESS}" \
  -F "file=@${DOCX_PATH}" \
  -F "type=jats" \
  | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d.get("ref_list","")[:800] or d)'

Local: criar utilizador e testar

# num terminal com Compose já no ar
docker compose -f local.yml run --rm django python manage.py createsuperuser

export BASE_URL="http://localhost:8000"
# ... mesmo fluxo de token + POST acima

Python (requests) — espelho do cliente HML

import requests

BASE = "https://tools-hml.scielo.org"

r = requests.post(
    f"{BASE}/api/v1/auth/token/",
    json={"username": "editor", "password": "segredo"},
    timeout=60,
)
r.raise_for_status()
access = r.json()["access"]

headers = {"Authorization": f"Bearer {access}"}

# texto
resp = requests.post(
    f"{BASE}/api/v1/reference/",
    headers=headers,
    json={
        "references": ["Smith J. Nature. 2024;600:1-10."],
        "type": "json",
    },
    timeout=600,
)
print(resp.status_code, resp.json())

# docx
with open("artigo.docx", "rb") as fh:
    resp = requests.post(
        f"{BASE}/api/v1/reference/docx/",
        headers=headers,
        files={
            "file": (
                "artigo.docx",
                fh,
                "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
            )
        },
        data={"type": "jats"},
        timeout=600,
    )
print(resp.status_code, list(resp.json().keys()))

Resumo das formas de resposta

Condição Corpo
type=jats { "ref_list": "<ref-list>...</ref-list>" }
Entrada string + 1 resultado + type ≠ jats { "message": "reference: ..." }
Lista / multilinha / vários resultados { "references": [ { "mixed_citation", "data" }, ... ] }
Erro de negócio { "error": "..." }
Erro de serializer { "<campo>": ["..."] }