Referencia: POST /runs/ingest
Endpoint para registrar en Qably los resultados de una ejecución en JSON: autenticación, ejemplos, campos y respuestas.
Registra los resultados de ejecución de una suite de pruebas. Requiere autenticación mediante el encabezado Authorization: Bearer <API key del proyecto>. El proyecto y la organización se determinan a partir de la clave.
Ejemplo de petición
curl --fail --silent \
--request POST \
"https://api.qably.dev/runs/ingest" \
--header "Authorization: Bearer $QABLY_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"externalId": "gh-run-482913",
"source": "github_actions",
"suiteId": "suite_123",
"name": "Checkout regression - main",
"startedAt": "2026-09-01T10:00:00Z",
"finishedAt": "2026-09-01T10:04:12Z",
"commitSha": "a1b2c3d",
"commitMessage": "fix: checkout rounding",
"commitAuthor": "Ada Lovelace",
"cases": [
{ "name": "Adds an item to the cart", "status": "pass" },
{
"name": "Applies a discount code",
"steps": ["open cart", "apply code SAVE10"],
"expectedResult": "total is reduced by 10%",
"status": "fail"
}
]
}'const response = await fetch('https://api.qably.dev/runs/ingest', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.QABLY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
externalId: 'gh-run-482913',
source: 'github_actions',
suiteId: 'suite_123',
name: 'Checkout regression - main',
startedAt: '2026-09-01T10:00:00Z',
finishedAt: '2026-09-01T10:04:12Z',
commitSha: 'a1b2c3d',
commitMessage: 'fix: checkout rounding',
commitAuthor: 'Ada Lovelace',
cases: [
{ name: 'Adds an item to the cart', status: 'pass' },
{
name: 'Applies a discount code',
steps: ['open cart', 'apply code SAVE10'],
expectedResult: 'total is reduced by 10%',
status: 'fail',
},
],
}),
});import os
import requests
response = requests.post(
"https://api.qably.dev/runs/ingest",
headers={"Authorization": f"Bearer {os.environ['QABLY_API_KEY']}"},
json={
"externalId": "gh-run-482913",
"source": "github_actions",
"suiteId": "suite_123",
"name": "Checkout regression - main",
"startedAt": "2026-09-01T10:00:00Z",
"finishedAt": "2026-09-01T10:04:12Z",
"commitSha": "a1b2c3d",
"commitMessage": "fix: checkout rounding",
"commitAuthor": "Ada Lovelace",
"cases": [
{"name": "Adds an item to the cart", "status": "pass"},
{
"name": "Applies a discount code",
"steps": ["open cart", "apply code SAVE10"],
"expectedResult": "total is reduced by 10%",
"status": "fail",
},
],
},
)
response.raise_for_status()Campos de la petición
| Campo | Obligatorio | Notas |
|---|---|---|
externalId | sí | Cadena no vacía. Clave de idempotencia para actualizar ejecuciones existentes en lugar de duplicarlas. |
source | no | "api" (valor por defecto) o "github_actions". |
suiteId / suiteName | exactamente uno | Un suiteId inexistente devuelve 404. Un suiteName inexistente crea la suite automáticamente. |
name | sí | Nombre descriptivo de la ejecución, hasta 200 caracteres. |
startedAt / finishedAt | no | Marcas temporales ISO 8601 con zona horaria explícita. |
commitSha / commitMessage / commitAuthor | no | Metadatos opcionales del commit, hasta 64, 2000 y 200 caracteres respectivamente. |
cases | sí | Arreglo con al menos un caso de prueba. |
Campos de cada caso
| Campo del caso | Obligatorio | Notas |
|---|---|---|
name | sí | Hasta 372 caracteres. |
suiteName | no | Hereda el nombre de la suite resuelta; permite conservar etiquetas adicionales (como proyectos de Playwright) para trazabilidad. |
steps | no | Arreglo de texto de hasta 50 elementos (máximo 500 caracteres por elemento). JUnit XML no incluye este campo, por lo que llega vacío por defecto salvo cuando se envía JSON directamente. |
expectedResult | no | Hasta 1000 caracteres. Llega vacío por defecto al importar desde JUnit XML. |
status | sí | Valores permitidos: pending, running, pass, fail, skip, blocked. |
recordedAt | no | Marca temporal ISO 8601 con zona horaria explícita. |
Estado de la ejecución
El estado general de la ejecución se evalúa en el servidor y no depende de valores calculados por el cliente. Si un caso de prueba falla, la ejecución se marca como fallida. Si existen casos pendientes o en progreso sin fallos, la ejecución permanece en estado de ejecución. La ejecución finaliza como exitosa cuando al menos un caso concluye en pass o skip. Una ejecución donde todos los casos están bloqueados se califica como fallida, ya que ninguna validación fue completada.
Reenvíos e idempotencia
Reutilizar la combinación de proyecto, origen y externalId actualiza los datos existentes sin crear duplicados: la lista de casos se reemplaza íntegramente y los metadatos opcionales se actualizan si se incluyen en la nueva petición. El endpoint responde 200 OK tanto en la creación inicial como en actualizaciones.