Ayuda — tiro de precisión
API e integración del tiro de precisión
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.
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í
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.