Saltar al contenido

Ayuda — tiro de precisión

API e integración del tiro de precisión

← Todas las guías

La API pública del tiro de precisión permite que el sistema de tu club cree Matches, inscriba atletas y lea el resultado sin que nadie vuelva a digitar nada.

La clave

Es la misma clave de los otros módulos. El dueño del club la crea en Entidad → Claves de API; el secret aparece una única vez, al crearla. Guárdala con el mismo cuidado que una contraseña.

Authorization: Bearer <access_key>.<secret>
  • El alcance "lectura" permite solo GET; "lectura y escritura" habilita el resto.
  • Todo está limitado a tu club. No existe petición que alcance datos de otra entidad.
  • Si el módulo no está habilitado para el club, la respuesta es 404 — la clave es válida, lo que no existe para ti es el recurso.

Los tres ejes del Match

Entender esto antes de integrar ahorra la mayor parte del retrabajo:

  • Modalidad — el recorrido de tiro. En el catálogo del club es reutilizable; dentro del Match es una COPIA. Editar el catálogo después no cambia un Match ya montado — es lo que garantiza que el resultado de un Match cerrado nunca cambie. Es a ella que apunta la inscripción y por ella que el ranking agrupa.
  • Serie — el eje de tiempo: la ronda.
  • Turno — el eje de espacio: quién dispara junto, con límite de cupos.
Una inscripción por modalidad. El mismo atleta puede tener dos inscripciones en el mismo Match. Repetir la misma modalidad es lo que devuelve conflicto.

Un día de Match, en cuatro llamadas

BASE=https://seu-dominio/api/v1
AUTH="Authorization: Bearer $ACCESS.$SECRET"

# 1. crear el Match ya con las modalidades del catálogo del club
curl -s -X POST $BASE/precisao/provas -H "$AUTH" \
  -H 'Content-Type: application/json' \
  -d '{"nome":"1ª Etapa 2026","data_prova":"2026-03-14",
       "modalidades":["<uuid-da-modalidade>"],
       "external_id":"etapa-1-2026"}'

# 2. inscribir un atleta en una modalidad y en un turno
curl -s -X POST $BASE/precisao/provas/$prova/inscricoes -H "$AUTH" \
  -H 'Content-Type: application/json' \
  -d '{"prova_modalidade_uuid":"<uuid>","turno_uuid":"<uuid>",
       "nome":"Fulano","email":"[email protected]",
       "sexo":"M","data_nascimento":"1988-04-02",
       "external_id":"insc-4471"}'

# 3. abrir el Match y publicar los resultados
curl -s -X PATCH $BASE/precisao/provas/$prova -H "$AUTH" \
  -H 'Content-Type: application/json' \
  -d '{"status":"aberta","resultados_publicos":true}'

# 4. leer el ranking (agrupado por modalidad, con el desempate abierto)
curl -s $BASE/precisao/provas/$prova/resultados -H "$AUTH"

external_id: el id de TU sistema

Todo recurso de Match y de inscripción acepta un external_id. Guarda en él el id del registro de tu lado y reencuentras todo sin necesidad de guardar nuestros uuid:

curl -s "$BASE/precisao/provas?external_id=etapa-1-2026" -H "$AUTH"

Es único en el alcance (club para Matches, Match para inscripciones), lo que lo convierte también en una clave de idempotencia: reenviar el mismo POST devuelve conflicto en vez de crear un duplicado silencioso. Enviar null desvincula; omitir el campo no toca lo que está guardado.

El Score no se escribe por aquí

La planilla nace firmada en el campo — HMAC del juez, encadenado con el PIN del atleta cuando el Match lo exige. Un POST de Score crearía un resultado sin esa cadena, que es justamente lo que el módulo existe para impedir. La API lee el resultado; quien lo produce es el juez en la pantalla de registro.

Por el mismo motivo, la API nunca emite ni devuelve el PIN de un atleta. Solo existe el camino de borrarlo, para que el atleta cree otro — el PIN es su secreto, y un integrador que lo conociera vaciaría de sentido la firma del atleta.

Qué se bloquea, y por qué

Estas reglas valen igual en la pantalla y en la API. Todas devuelven 409:

Intento Por qué
Cambiar el desempate o la exigencia de PIN con Score registrado Las dos forman parte de lo que fue firmado; cambiarlas reordenaría el ranking sin que nadie dispare.
Cambiar el recorrido de la modalidad con Score registrado La planilla firmada apunta a aquellos blancos.
Renumerar una serie con Score registrado El desempate por serie final lee las series por el orden.
Cambiar la modalidad de una inscripción con Score Movería una planilla firmada a otro recorrido de tiro.
Eliminar una inscripción con Score Quedaría una planilla firmada sin dueño. Usa el estado "cancelada".
Publicar un Match en borrador La estructura todavía va a cambiar; el enlace mostraría algo que no se confirma.
Alterar la estructura de un Match cerrado El resultado ya circuló como oficial.
Pasar del límite de cupos del turno Es el mismo límite que respeta la pantalla.

Eliminar un Match exige, además, su nombre exacto en ?confirmacao= — la misma zona de peligro de la interfaz.

Paginación, límites y errores

  • Los listados aceptan ?page (a partir de 1) y ?per_page (por defecto 25, máximo 100; en las inscripciones, por defecto 50 y máximo 200) y devuelven page, per_page y total.
  • Rate limit por clave, con los headers X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset. Al excederlo devuelve 429 con Retry-After — respétalo en vez de repetir en bucle.
  • El error siempre es JSON con el mismo formato: {"error": {"code": "not_found", "message": "Prueba no encontrada."}}. El mensaje está escrito para que lo lea quien está integrando, no solo para quedar registrado.

Verificar lo que hizo la integración

Cada Match expone su propia pista de auditoría, y las acciones hechas por clave aparecen en ella junto con las hechas en la pantalla. Es así como se reconcilia lo que hizo el robot con lo que hizo la secretaría:

curl -s "$BASE/precisao/provas/$prova/auditoria?acao=precisao.prova_update" -H "$AUTH"

Referencia interactiva

Explora y prueba los endpoints abajo (Swagger UI). El JSON de la especificación OpenAPI está en openapi.json.

Esta guía cubre los Matches de tiro de precisión (fuego circular y bullseye), según los moldes de los reglamentos SCTSL y CBTT.