{"info":{"name":"Skalia Partner API v1","description":"Colección generada de la spec OpenAPI de la Skalia Partner API v1 (contrato 1.3.0).\n\n1. En Variables, pegá tu key en `apiKey` (`sk_live_…` contra producción, `sk_test_…` contra el sandbox) y elegí `baseUrl` según el ambiente.\n2. Empezá por `GET /me`: si responde 200, la integración, el club, los scopes y las cuotas que ves son los que rigen.\n3. Todo error viaja como `ErrorEnvelope` (`{ error, code, details?, requestId }`): ramificá por `code`. Las respuestas guardadas de cada request muestran los codes posibles.\n\nEsta colección se descargó con `baseUrl` = https://skalia-server.vercel.app/api/partner/v1. La misma colección para el otro ambiente: `https://api-test.skaliasports.com/api/partner/v1/postman.json`.\n\nDocumentación: https://www.skaliasports.com/desarrolladores · OpenAPI: `{{baseUrl}}/openapi.json` · Credenciales: https://www.skaliasports.com/admin/api","schema":"https://schema.getpostman.com/json/collection/v2.1.0/collection.json","version":"1.3.0"},"auth":{"type":"bearer","bearer":[{"key":"token","value":"{{apiKey}}","type":"string"}]},"variable":[{"key":"baseUrl","value":"https://skalia-server.vercel.app/api/partner/v1","type":"string","description":"Server del ambiente (https://skalia-server.vercel.app/api/partner/v1 o https://api-test.skaliasports.com/api/partner/v1)."},{"key":"apiKey","value":"sk_live_…","type":"string","description":"Tu API key de club (se ve una sola vez al emitirla en el panel)."}],"item":[{"name":"Cuenta","description":"Quién soy: integración, key, clubes, cuotas.","item":[{"name":"Quién soy (getMe)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/me","host":["{{baseUrl}}"],"path":["me"]},"description":"Smoke test del onboarding: integración, key, clubes con scopes efectivos y horario informativo, cuotas y hora del server. Sin scope: basta una key válida. Nunca devuelve ids de usuarios ni datos de personas.\n\nScope: ninguno (basta una key válida)."},"response":[{"name":"200 · Integración, key, clubes, cuotas y hora del server.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/me","host":["{{baseUrl}}"],"path":["me"]},"description":"Smoke test del onboarding: integración, key, clubes con scopes efectivos y horario informativo, cuotas y hora del server. Sin scope: basta una key válida. Nunca devuelve ids de usuarios ni datos de personas.\n\nScope: ninguno (basta una key válida)."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"integration\": {\n    \"id\": \"7f8e9d0c-1b2a-4c3d-9e8f-7a6b5c4d3e2f\",\n    \"kind\": \"CLUB\",\n    \"name\": \"Mi web\",\n    \"linkPlayersByPhone\": false,\n    \"canManageAllBookings\": false,\n    \"notifyStaff\": true,\n    \"mirrorToQj\": false\n  },\n  \"key\": {\n    \"prefix\": \"sk_live_a1b2\",\n    \"env\": \"live\",\n    \"scopes\": [\n      \"courts:read\",\n      \"bookings:read\"\n    ],\n    \"expiresAt\": null\n  },\n  \"clubs\": [\n    {\n      \"id\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n      \"name\": \"Club Norte\",\n      \"timezone\": \"America/Montevideo\",\n      \"countryCode\": \"598\",\n      \"currency\": \"UYU\",\n      \"hours\": [\n        {\n          \"dayOfWeek\": 1,\n          \"open\": \"08:00\",\n          \"close\": \"23:00\"\n        }\n      ],\n      \"scopes\": [\n        \"courts:read\",\n        \"bookings:read\"\n      ],\n      \"autoConfirm\": true\n    }\n  ],\n  \"rateLimit\": {\n    \"perMinute\": 120,\n    \"perDay\": 10000,\n    \"writesPerMinute\": 20,\n    \"writesPerDay\": 500,\n    \"maxFutureBookings\": 2000\n  },\n  \"server\": {\n    \"now\": \"2026-09-14T12:00:00.000Z\"\n  }\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/me","host":["{{baseUrl}}"],"path":["me"]},"description":"Smoke test del onboarding: integración, key, clubes con scopes efectivos y horario informativo, cuotas y hora del server. Sin scope: basta una key válida. Nunca devuelve ids de usuarios ni datos de personas.\n\nScope: ninguno (basta una key válida)."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/me","host":["{{baseUrl}}"],"path":["me"]},"description":"Smoke test del onboarding: integración, key, clubes con scopes efectivos y horario informativo, cuotas y hora del server. Sin scope: basta una key válida. Nunca devuelve ids de usuarios ni datos de personas.\n\nScope: ninguno (basta una key válida)."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/me","host":["{{baseUrl}}"],"path":["me"]},"description":"Smoke test del onboarding: integración, key, clubes con scopes efectivos y horario informativo, cuotas y hora del server. Sin scope: basta una key válida. Nunca devuelve ids de usuarios ni datos de personas.\n\nScope: ninguno (basta una key válida)."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/me","host":["{{baseUrl}}"],"path":["me"]},"description":"Smoke test del onboarding: integración, key, clubes con scopes efectivos y horario informativo, cuotas y hora del server. Sin scope: basta una key válida. Nunca devuelve ids de usuarios ni datos de personas.\n\nScope: ninguno (basta una key válida)."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/me","host":["{{baseUrl}}"],"path":["me"]},"description":"Smoke test del onboarding: integración, key, clubes con scopes efectivos y horario informativo, cuotas y hora del server. Sin scope: basta una key válida. Nunca devuelve ids de usuarios ni datos de personas.\n\nScope: ninguno (basta una key válida)."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/me","host":["{{baseUrl}}"],"path":["me"]},"description":"Smoke test del onboarding: integración, key, clubes con scopes efectivos y horario informativo, cuotas y hora del server. Sin scope: basta una key válida. Nunca devuelve ids de usuarios ni datos de personas.\n\nScope: ninguno (basta una key válida)."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]}]},{"name":"Agenda","description":"Canchas, qué se puede vender y qué está ocupado.","item":[{"name":"Qué se puede vender (getAvailability)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/availability?date=2026-09-15","host":["{{baseUrl}}"],"path":["availability"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"date","value":"2026-09-15","description":"`YYYY-MM-DD`, naive en la zona del club (`clubs[].timezone` de `/me`). Un ISO con offset es VALIDATION.","disabled":false},{"key":"sport","value":"PADEL","description":"Filtra las canchas por deporte (`courts.sports`, p.ej. `PADEL`).","disabled":true},{"key":"durationMinutes","value":"90","description":"Restringe el cálculo a esa duración (si no, se calculan las cuatro).","disabled":true}]},"description":"Comienzos vendibles por cancha (grilla :00/:30 dentro de las franjas de la cancha y del horario del club), con duraciones y precio. Sólo canchas habilitadas de kind COURT; descuenta las 4 fuentes de ocupación; oculta los comienzos ya pasados si `date` es hoy en el club. Hasta 180 días de anticipación. No es autoritativo: el POST revalida.\n\nScope: `availability:read`."},"response":[{"name":"200 · Comienzos por cancha. `courts: []` si el club no abre ese día.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/availability?date=2026-09-15","host":["{{baseUrl}}"],"path":["availability"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"date","value":"2026-09-15","description":"`YYYY-MM-DD`, naive en la zona del club (`clubs[].timezone` de `/me`). Un ISO con offset es VALIDATION.","disabled":false},{"key":"sport","value":"PADEL","description":"Filtra las canchas por deporte (`courts.sports`, p.ej. `PADEL`).","disabled":true},{"key":"durationMinutes","value":"90","description":"Restringe el cálculo a esa duración (si no, se calculan las cuatro).","disabled":true}]},"description":"Comienzos vendibles por cancha (grilla :00/:30 dentro de las franjas de la cancha y del horario del club), con duraciones y precio. Sólo canchas habilitadas de kind COURT; descuenta las 4 fuentes de ocupación; oculta los comienzos ya pasados si `date` es hoy en el club. Hasta 180 días de anticipación. No es autoritativo: el POST revalida.\n\nScope: `availability:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n  \"date\": \"2026-09-15\",\n  \"timezone\": \"America/Montevideo\",\n  \"durations\": [\n    30,\n    60,\n    90,\n    120\n  ],\n  \"courts\": [\n    {\n      \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n      \"name\": \"Cancha 1\",\n      \"kind\": \"COURT\",\n      \"categoryId\": null,\n      \"resourceNoun\": \"COURT\",\n      \"starts\": [\n        {\n          \"startTime\": \"10:00\",\n          \"availableDurations\": [\n            30,\n            60,\n            90,\n            120\n          ],\n          \"prices\": {\n            \"30\": 500,\n            \"60\": 1000,\n            \"90\": 1400,\n            \"120\": 2000\n          }\n        }\n      ]\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED / DATE_IN_PAST / MAX_ADVANCE_EXCEEDED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/availability?date=2026-09-15","host":["{{baseUrl}}"],"path":["availability"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"date","value":"2026-09-15","description":"`YYYY-MM-DD`, naive en la zona del club (`clubs[].timezone` de `/me`). Un ISO con offset es VALIDATION.","disabled":false},{"key":"sport","value":"PADEL","description":"Filtra las canchas por deporte (`courts.sports`, p.ej. `PADEL`).","disabled":true},{"key":"durationMinutes","value":"90","description":"Restringe el cálculo a esa duración (si no, se calculan las cuatro).","disabled":true}]},"description":"Comienzos vendibles por cancha (grilla :00/:30 dentro de las franjas de la cancha y del horario del club), con duraciones y precio. Sólo canchas habilitadas de kind COURT; descuenta las 4 fuentes de ocupación; oculta los comienzos ya pasados si `date` es hoy en el club. Hasta 180 días de anticipación. No es autoritativo: el POST revalida.\n\nScope: `availability:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/availability?date=2026-09-15","host":["{{baseUrl}}"],"path":["availability"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"date","value":"2026-09-15","description":"`YYYY-MM-DD`, naive en la zona del club (`clubs[].timezone` de `/me`). Un ISO con offset es VALIDATION.","disabled":false},{"key":"sport","value":"PADEL","description":"Filtra las canchas por deporte (`courts.sports`, p.ej. `PADEL`).","disabled":true},{"key":"durationMinutes","value":"90","description":"Restringe el cálculo a esa duración (si no, se calculan las cuatro).","disabled":true}]},"description":"Comienzos vendibles por cancha (grilla :00/:30 dentro de las franjas de la cancha y del horario del club), con duraciones y precio. Sólo canchas habilitadas de kind COURT; descuenta las 4 fuentes de ocupación; oculta los comienzos ya pasados si `date` es hoy en el club. Hasta 180 días de anticipación. No es autoritativo: el POST revalida.\n\nScope: `availability:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/availability?date=2026-09-15","host":["{{baseUrl}}"],"path":["availability"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"date","value":"2026-09-15","description":"`YYYY-MM-DD`, naive en la zona del club (`clubs[].timezone` de `/me`). Un ISO con offset es VALIDATION.","disabled":false},{"key":"sport","value":"PADEL","description":"Filtra las canchas por deporte (`courts.sports`, p.ej. `PADEL`).","disabled":true},{"key":"durationMinutes","value":"90","description":"Restringe el cálculo a esa duración (si no, se calculan las cuatro).","disabled":true}]},"description":"Comienzos vendibles por cancha (grilla :00/:30 dentro de las franjas de la cancha y del horario del club), con duraciones y precio. Sólo canchas habilitadas de kind COURT; descuenta las 4 fuentes de ocupación; oculta los comienzos ya pasados si `date` es hoy en el club. Hasta 180 días de anticipación. No es autoritativo: el POST revalida.\n\nScope: `availability:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/availability?date=2026-09-15","host":["{{baseUrl}}"],"path":["availability"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"date","value":"2026-09-15","description":"`YYYY-MM-DD`, naive en la zona del club (`clubs[].timezone` de `/me`). Un ISO con offset es VALIDATION.","disabled":false},{"key":"sport","value":"PADEL","description":"Filtra las canchas por deporte (`courts.sports`, p.ej. `PADEL`).","disabled":true},{"key":"durationMinutes","value":"90","description":"Restringe el cálculo a esa duración (si no, se calculan las cuatro).","disabled":true}]},"description":"Comienzos vendibles por cancha (grilla :00/:30 dentro de las franjas de la cancha y del horario del club), con duraciones y precio. Sólo canchas habilitadas de kind COURT; descuenta las 4 fuentes de ocupación; oculta los comienzos ya pasados si `date` es hoy en el club. Hasta 180 días de anticipación. No es autoritativo: el POST revalida.\n\nScope: `availability:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/availability?date=2026-09-15","host":["{{baseUrl}}"],"path":["availability"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"date","value":"2026-09-15","description":"`YYYY-MM-DD`, naive en la zona del club (`clubs[].timezone` de `/me`). Un ISO con offset es VALIDATION.","disabled":false},{"key":"sport","value":"PADEL","description":"Filtra las canchas por deporte (`courts.sports`, p.ej. `PADEL`).","disabled":true},{"key":"durationMinutes","value":"90","description":"Restringe el cálculo a esa duración (si no, se calculan las cuatro).","disabled":true}]},"description":"Comienzos vendibles por cancha (grilla :00/:30 dentro de las franjas de la cancha y del horario del club), con duraciones y precio. Sólo canchas habilitadas de kind COURT; descuenta las 4 fuentes de ocupación; oculta los comienzos ya pasados si `date` es hoy en el club. Hasta 180 días de anticipación. No es autoritativo: el POST revalida.\n\nScope: `availability:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/availability?date=2026-09-15","host":["{{baseUrl}}"],"path":["availability"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"date","value":"2026-09-15","description":"`YYYY-MM-DD`, naive en la zona del club (`clubs[].timezone` de `/me`). Un ISO con offset es VALIDATION.","disabled":false},{"key":"sport","value":"PADEL","description":"Filtra las canchas por deporte (`courts.sports`, p.ej. `PADEL`).","disabled":true},{"key":"durationMinutes","value":"90","description":"Restringe el cálculo a esa duración (si no, se calculan las cuatro).","disabled":true}]},"description":"Comienzos vendibles por cancha (grilla :00/:30 dentro de las franjas de la cancha y del horario del club), con duraciones y precio. Sólo canchas habilitadas de kind COURT; descuenta las 4 fuentes de ocupación; oculta los comienzos ya pasados si `date` es hoy en el club. Hasta 180 días de anticipación. No es autoritativo: el POST revalida.\n\nScope: `availability:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Canchas del club (listCourts)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Para mapear ids del lado del partner. Lista también las deshabilitadas (`enabled: false`) y los recursos que no son cancha con su `kind`. Nunca claves ni ingest de streaming.\n\nScope: `courts:read`."},"response":[{"name":"200 · Canchas (y demás recursos) del club con su tarifario.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Para mapear ids del lado del partner. Lista también las deshabilitadas (`enabled: false`) y los recursos que no son cancha con su `kind`. Nunca claves ni ingest de streaming.\n\nScope: `courts:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n  \"courts\": [\n    {\n      \"id\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n      \"name\": \"Cancha 1\",\n      \"kind\": \"COURT\",\n      \"categoryId\": null,\n      \"resourceNoun\": \"COURT\",\n      \"sports\": [\n        \"PADEL\"\n      ],\n      \"enabled\": true,\n      \"isIndoor\": false,\n      \"pricing\": [\n        {\n          \"pricePerHour\": 1000,\n          \"price60\": null,\n          \"price90\": 1400,\n          \"price120\": null,\n          \"ranges\": [\n            {\n              \"start\": \"08:00\",\n              \"end\": \"23:00\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Para mapear ids del lado del partner. Lista también las deshabilitadas (`enabled: false`) y los recursos que no son cancha con su `kind`. Nunca claves ni ingest de streaming.\n\nScope: `courts:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Para mapear ids del lado del partner. Lista también las deshabilitadas (`enabled: false`) y los recursos que no son cancha con su `kind`. Nunca claves ni ingest de streaming.\n\nScope: `courts:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Para mapear ids del lado del partner. Lista también las deshabilitadas (`enabled: false`) y los recursos que no son cancha con su `kind`. Nunca claves ni ingest de streaming.\n\nScope: `courts:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Para mapear ids del lado del partner. Lista también las deshabilitadas (`enabled: false`) y los recursos que no son cancha con su `kind`. Nunca claves ni ingest de streaming.\n\nScope: `courts:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Para mapear ids del lado del partner. Lista también las deshabilitadas (`enabled: false`) y los recursos que no son cancha con su `kind`. Nunca claves ni ingest de streaming.\n\nScope: `courts:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Para mapear ids del lado del partner. Lista también las deshabilitadas (`enabled: false`) y los recursos que no son cancha con su `kind`. Nunca claves ni ingest de streaming.\n\nScope: `courts:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Fuente de verdad de \"ocupado\" (getOccupancy)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/occupancy?from=2026-09-15&to=2026-09-21","host":["{{baseUrl}}"],"path":["occupancy"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango, `YYYY-MM-DD` naive del club.","disabled":false},{"key":"to","value":"2026-09-21","description":"Último día del rango (inclusive), `YYYY-MM-DD` naive del club.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true}]},"description":"Reservas de cualquier origen (app, panel, API, fijas materializadas), fijas no materializadas, bloqueos menos huecos y partidos con cancha sin reserva, por día y recurso, sin PII. Rango de 1 a 31 días (`to >= from`). `bookingId` sólo en los rangos que son reservas de ESTA integración. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue: el 304 es un ahorro, no un permiso para cachear).\n\nScope: `availability:read`."},"response":[{"name":"200 · Ocupación por día y cancha.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/occupancy?from=2026-09-15&to=2026-09-21","host":["{{baseUrl}}"],"path":["occupancy"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango, `YYYY-MM-DD` naive del club.","disabled":false},{"key":"to","value":"2026-09-21","description":"Último día del rango (inclusive), `YYYY-MM-DD` naive del club.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true}]},"description":"Reservas de cualquier origen (app, panel, API, fijas materializadas), fijas no materializadas, bloqueos menos huecos y partidos con cancha sin reserva, por día y recurso, sin PII. Rango de 1 a 31 días (`to >= from`). `bookingId` sólo en los rangos que son reservas de ESTA integración. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue: el 304 es un ahorro, no un permiso para cachear).\n\nScope: `availability:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n  \"from\": \"2026-09-15\",\n  \"to\": \"2026-09-16\",\n  \"timezone\": \"America/Montevideo\",\n  \"days\": [\n    {\n      \"date\": \"2026-09-15\",\n      \"courts\": [\n        {\n          \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n          \"kind\": \"COURT\",\n          \"categoryId\": null,\n          \"resourceNoun\": \"COURT\",\n          \"busy\": [\n            {\n              \"startTime\": \"10:00\",\n              \"endTime\": \"11:30\"\n            },\n            {\n              \"startTime\": \"12:00\",\n              \"endTime\": \"13:00\",\n              \"bookingId\": \"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"},{"name":"304 · Nada cambió (ETag)","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/occupancy?from=2026-09-15&to=2026-09-21","host":["{{baseUrl}}"],"path":["occupancy"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango, `YYYY-MM-DD` naive del club.","disabled":false},{"key":"to","value":"2026-09-21","description":"Último día del rango (inclusive), `YYYY-MM-DD` naive del club.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true}]},"description":"Reservas de cualquier origen (app, panel, API, fijas materializadas), fijas no materializadas, bloqueos menos huecos y partidos con cancha sin reserva, por día y recurso, sin PII. Rango de 1 a 31 días (`to >= from`). `bookingId` sólo en los rangos que son reservas de ESTA integración. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue: el 304 es un ahorro, no un permiso para cachear).\n\nScope: `availability:read`."},"status":"Not Modified","code":304,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":""},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/occupancy?from=2026-09-15&to=2026-09-21","host":["{{baseUrl}}"],"path":["occupancy"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango, `YYYY-MM-DD` naive del club.","disabled":false},{"key":"to","value":"2026-09-21","description":"Último día del rango (inclusive), `YYYY-MM-DD` naive del club.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true}]},"description":"Reservas de cualquier origen (app, panel, API, fijas materializadas), fijas no materializadas, bloqueos menos huecos y partidos con cancha sin reserva, por día y recurso, sin PII. Rango de 1 a 31 días (`to >= from`). `bookingId` sólo en los rangos que son reservas de ESTA integración. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue: el 304 es un ahorro, no un permiso para cachear).\n\nScope: `availability:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/occupancy?from=2026-09-15&to=2026-09-21","host":["{{baseUrl}}"],"path":["occupancy"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango, `YYYY-MM-DD` naive del club.","disabled":false},{"key":"to","value":"2026-09-21","description":"Último día del rango (inclusive), `YYYY-MM-DD` naive del club.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true}]},"description":"Reservas de cualquier origen (app, panel, API, fijas materializadas), fijas no materializadas, bloqueos menos huecos y partidos con cancha sin reserva, por día y recurso, sin PII. Rango de 1 a 31 días (`to >= from`). `bookingId` sólo en los rangos que son reservas de ESTA integración. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue: el 304 es un ahorro, no un permiso para cachear).\n\nScope: `availability:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/occupancy?from=2026-09-15&to=2026-09-21","host":["{{baseUrl}}"],"path":["occupancy"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango, `YYYY-MM-DD` naive del club.","disabled":false},{"key":"to","value":"2026-09-21","description":"Último día del rango (inclusive), `YYYY-MM-DD` naive del club.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true}]},"description":"Reservas de cualquier origen (app, panel, API, fijas materializadas), fijas no materializadas, bloqueos menos huecos y partidos con cancha sin reserva, por día y recurso, sin PII. Rango de 1 a 31 días (`to >= from`). `bookingId` sólo en los rangos que son reservas de ESTA integración. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue: el 304 es un ahorro, no un permiso para cachear).\n\nScope: `availability:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/occupancy?from=2026-09-15&to=2026-09-21","host":["{{baseUrl}}"],"path":["occupancy"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango, `YYYY-MM-DD` naive del club.","disabled":false},{"key":"to","value":"2026-09-21","description":"Último día del rango (inclusive), `YYYY-MM-DD` naive del club.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true}]},"description":"Reservas de cualquier origen (app, panel, API, fijas materializadas), fijas no materializadas, bloqueos menos huecos y partidos con cancha sin reserva, por día y recurso, sin PII. Rango de 1 a 31 días (`to >= from`). `bookingId` sólo en los rangos que son reservas de ESTA integración. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue: el 304 es un ahorro, no un permiso para cachear).\n\nScope: `availability:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/occupancy?from=2026-09-15&to=2026-09-21","host":["{{baseUrl}}"],"path":["occupancy"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango, `YYYY-MM-DD` naive del club.","disabled":false},{"key":"to","value":"2026-09-21","description":"Último día del rango (inclusive), `YYYY-MM-DD` naive del club.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true}]},"description":"Reservas de cualquier origen (app, panel, API, fijas materializadas), fijas no materializadas, bloqueos menos huecos y partidos con cancha sin reserva, por día y recurso, sin PII. Rango de 1 a 31 días (`to >= from`). `bookingId` sólo en los rangos que son reservas de ESTA integración. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue: el 304 es un ahorro, no un permiso para cachear).\n\nScope: `availability:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/occupancy?from=2026-09-15&to=2026-09-21","host":["{{baseUrl}}"],"path":["occupancy"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango, `YYYY-MM-DD` naive del club.","disabled":false},{"key":"to","value":"2026-09-21","description":"Último día del rango (inclusive), `YYYY-MM-DD` naive del club.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true}]},"description":"Reservas de cualquier origen (app, panel, API, fijas materializadas), fijas no materializadas, bloqueos menos huecos y partidos con cancha sin reserva, por día y recurso, sin PII. Rango de 1 a 31 días (`to >= from`). `bookingId` sólo en los rangos que son reservas de ESTA integración. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue: el 304 es un ahorro, no un permiso para cachear).\n\nScope: `availability:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Demanda insatisfecha por franja (getWaitlistDemand)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/waitlists/demand","host":["{{baseUrl}}"],"path":["waitlists","demand"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-14","description":"Primer día (`YYYY-MM-DD` naive del club). Default: hoy del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Último día (inclusive). Default: `from` + 7 días. Rango de 1 a 14 días inclusive (`to >= from` y `to <= from + 13`).","disabled":true},{"key":"categoryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Categoría de recurso (F6) cuya demanda mirar. Ausente = canchas.","disabled":true}]},"description":"Cuántos jugadores DISTINTOS esperan que se libere cada franja del club (lista de espera de turnos: día, comienzo, duración, deporte, categoría), en `[from, to]` (1 a 14 días). Es el dato para abrir una cancha más, mover una fija o decidir tarifas; no es operativo (cuando un turno se libera Skalia avisa sola). Nunca quiénes esperan ni qué ocupaba el turno. Con la lista de espera apagada en la plataforma responde `items: []`. Sin ETag.\n\nScope: `availability:read`."},"response":[{"name":"200 · Demanda por franja.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/waitlists/demand","host":["{{baseUrl}}"],"path":["waitlists","demand"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-14","description":"Primer día (`YYYY-MM-DD` naive del club). Default: hoy del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Último día (inclusive). Default: `from` + 7 días. Rango de 1 a 14 días inclusive (`to >= from` y `to <= from + 13`).","disabled":true},{"key":"categoryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Categoría de recurso (F6) cuya demanda mirar. Ausente = canchas.","disabled":true}]},"description":"Cuántos jugadores DISTINTOS esperan que se libere cada franja del club (lista de espera de turnos: día, comienzo, duración, deporte, categoría), en `[from, to]` (1 a 14 días). Es el dato para abrir una cancha más, mover una fija o decidir tarifas; no es operativo (cuando un turno se libera Skalia avisa sola). Nunca quiénes esperan ni qué ocupaba el turno. Con la lista de espera apagada en la plataforma responde `items: []`. Sin ETag.\n\nScope: `availability:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"items\": [\n    {\n      \"date\": \"2026-09-15\",\n      \"startTime\": \"20:00\",\n      \"durationMinutes\": 90,\n      \"sport\": \"PADEL\",\n      \"categoryId\": null,\n      \"waiting\": 3\n    }\n  ],\n  \"from\": \"2026-09-14\",\n  \"to\": \"2026-09-21\"\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/waitlists/demand","host":["{{baseUrl}}"],"path":["waitlists","demand"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-14","description":"Primer día (`YYYY-MM-DD` naive del club). Default: hoy del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Último día (inclusive). Default: `from` + 7 días. Rango de 1 a 14 días inclusive (`to >= from` y `to <= from + 13`).","disabled":true},{"key":"categoryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Categoría de recurso (F6) cuya demanda mirar. Ausente = canchas.","disabled":true}]},"description":"Cuántos jugadores DISTINTOS esperan que se libere cada franja del club (lista de espera de turnos: día, comienzo, duración, deporte, categoría), en `[from, to]` (1 a 14 días). Es el dato para abrir una cancha más, mover una fija o decidir tarifas; no es operativo (cuando un turno se libera Skalia avisa sola). Nunca quiénes esperan ni qué ocupaba el turno. Con la lista de espera apagada en la plataforma responde `items: []`. Sin ETag.\n\nScope: `availability:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/waitlists/demand","host":["{{baseUrl}}"],"path":["waitlists","demand"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-14","description":"Primer día (`YYYY-MM-DD` naive del club). Default: hoy del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Último día (inclusive). Default: `from` + 7 días. Rango de 1 a 14 días inclusive (`to >= from` y `to <= from + 13`).","disabled":true},{"key":"categoryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Categoría de recurso (F6) cuya demanda mirar. Ausente = canchas.","disabled":true}]},"description":"Cuántos jugadores DISTINTOS esperan que se libere cada franja del club (lista de espera de turnos: día, comienzo, duración, deporte, categoría), en `[from, to]` (1 a 14 días). Es el dato para abrir una cancha más, mover una fija o decidir tarifas; no es operativo (cuando un turno se libera Skalia avisa sola). Nunca quiénes esperan ni qué ocupaba el turno. Con la lista de espera apagada en la plataforma responde `items: []`. Sin ETag.\n\nScope: `availability:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/waitlists/demand","host":["{{baseUrl}}"],"path":["waitlists","demand"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-14","description":"Primer día (`YYYY-MM-DD` naive del club). Default: hoy del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Último día (inclusive). Default: `from` + 7 días. Rango de 1 a 14 días inclusive (`to >= from` y `to <= from + 13`).","disabled":true},{"key":"categoryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Categoría de recurso (F6) cuya demanda mirar. Ausente = canchas.","disabled":true}]},"description":"Cuántos jugadores DISTINTOS esperan que se libere cada franja del club (lista de espera de turnos: día, comienzo, duración, deporte, categoría), en `[from, to]` (1 a 14 días). Es el dato para abrir una cancha más, mover una fija o decidir tarifas; no es operativo (cuando un turno se libera Skalia avisa sola). Nunca quiénes esperan ni qué ocupaba el turno. Con la lista de espera apagada en la plataforma responde `items: []`. Sin ETag.\n\nScope: `availability:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/waitlists/demand","host":["{{baseUrl}}"],"path":["waitlists","demand"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-14","description":"Primer día (`YYYY-MM-DD` naive del club). Default: hoy del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Último día (inclusive). Default: `from` + 7 días. Rango de 1 a 14 días inclusive (`to >= from` y `to <= from + 13`).","disabled":true},{"key":"categoryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Categoría de recurso (F6) cuya demanda mirar. Ausente = canchas.","disabled":true}]},"description":"Cuántos jugadores DISTINTOS esperan que se libere cada franja del club (lista de espera de turnos: día, comienzo, duración, deporte, categoría), en `[from, to]` (1 a 14 días). Es el dato para abrir una cancha más, mover una fija o decidir tarifas; no es operativo (cuando un turno se libera Skalia avisa sola). Nunca quiénes esperan ni qué ocupaba el turno. Con la lista de espera apagada en la plataforma responde `items: []`. Sin ETag.\n\nScope: `availability:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/waitlists/demand","host":["{{baseUrl}}"],"path":["waitlists","demand"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-14","description":"Primer día (`YYYY-MM-DD` naive del club). Default: hoy del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Último día (inclusive). Default: `from` + 7 días. Rango de 1 a 14 días inclusive (`to >= from` y `to <= from + 13`).","disabled":true},{"key":"categoryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Categoría de recurso (F6) cuya demanda mirar. Ausente = canchas.","disabled":true}]},"description":"Cuántos jugadores DISTINTOS esperan que se libere cada franja del club (lista de espera de turnos: día, comienzo, duración, deporte, categoría), en `[from, to]` (1 a 14 días). Es el dato para abrir una cancha más, mover una fija o decidir tarifas; no es operativo (cuando un turno se libera Skalia avisa sola). Nunca quiénes esperan ni qué ocupaba el turno. Con la lista de espera apagada en la plataforma responde `items: []`. Sin ETag.\n\nScope: `availability:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/waitlists/demand","host":["{{baseUrl}}"],"path":["waitlists","demand"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-14","description":"Primer día (`YYYY-MM-DD` naive del club). Default: hoy del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Último día (inclusive). Default: `from` + 7 días. Rango de 1 a 14 días inclusive (`to >= from` y `to <= from + 13`).","disabled":true},{"key":"categoryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Categoría de recurso (F6) cuya demanda mirar. Ausente = canchas.","disabled":true}]},"description":"Cuántos jugadores DISTINTOS esperan que se libere cada franja del club (lista de espera de turnos: día, comienzo, duración, deporte, categoría), en `[from, to]` (1 a 14 días). Es el dato para abrir una cancha más, mover una fija o decidir tarifas; no es operativo (cuando un turno se libera Skalia avisa sola). Nunca quiénes esperan ni qué ocupaba el turno. Con la lista de espera apagada en la plataforma responde `items: []`. Sin ETag.\n\nScope: `availability:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]}]},{"name":"Reservas","description":"ABML de reservas propias (idempotente, con cuota de escritura).","item":[{"name":"Listar reservas (listBookings)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true},{"key":"status","value":"PENDING","description":"Filtra por status de la reserva.","disabled":true},{"key":"externalRef","value":"ORD-123","description":"Filtra por tu ref (sólo propias).","disabled":true},{"key":"updatedSince","value":"2026-09-14T12:00:00Z","description":"ISO 8601 con zona; como mucho 7 días hacia atrás. Filtra por `COALESCE(updated_at, created_at)`.","disabled":true},{"key":"all","value":"true","description":"`true` suma las reservas del club que NO creó esta integración, anónimas (`SlotDto`). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"paymentStatus","value":"PAID","description":"Filtra por estado de pago. Ojo: sólo la Partner API escribe `payment_status` (la app y el panel dejan `PENDING`): sirve si tu sistema es el que registra el cobro con `PATCH`. \"Pendientes de cobro de hoy\" = `?all=true&from=D&to=D&paymentStatus=PENDING&status=CONFIRMED`.","disabled":true}]},"description":"Reservas creadas por ESTA integración (`BookingDto`). Con `all=true` suma las demás del club anónimas: `ManagedSlotDto` (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`, `SlotDto` si no. Orden: fecha, hora, id. `limit` ≤ 200 (default 100). `updatedSince` como mucho 7 días hacia atrás.\n\nScope: `bookings:read`."},"response":[{"name":"200 · Página de reservas.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true},{"key":"status","value":"PENDING","description":"Filtra por status de la reserva.","disabled":true},{"key":"externalRef","value":"ORD-123","description":"Filtra por tu ref (sólo propias).","disabled":true},{"key":"updatedSince","value":"2026-09-14T12:00:00Z","description":"ISO 8601 con zona; como mucho 7 días hacia atrás. Filtra por `COALESCE(updated_at, created_at)`.","disabled":true},{"key":"all","value":"true","description":"`true` suma las reservas del club que NO creó esta integración, anónimas (`SlotDto`). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"paymentStatus","value":"PAID","description":"Filtra por estado de pago. Ojo: sólo la Partner API escribe `payment_status` (la app y el panel dejan `PENDING`): sirve si tu sistema es el que registra el cobro con `PATCH`. \"Pendientes de cobro de hoy\" = `?all=true&from=D&to=D&paymentStatus=PENDING&status=CONFIRMED`.","disabled":true}]},"description":"Reservas creadas por ESTA integración (`BookingDto`). Con `all=true` suma las demás del club anónimas: `ManagedSlotDto` (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`, `SlotDto` si no. Orden: fecha, hora, id. `limit` ≤ 200 (default 100). `updatedSince` como mucho 7 días hacia atrás.\n\nScope: `bookings:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"bookings\": [\n    {\n      \"id\": \"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d\",\n      \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n      \"externalRef\": \"ORD-123\",\n      \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n      \"courtName\": \"Cancha 1\",\n      \"kind\": \"COURT\",\n      \"categoryId\": null,\n      \"resourceNoun\": \"COURT\",\n      \"date\": \"2026-09-15\",\n      \"startTime\": \"10:00\",\n      \"endTime\": \"11:30\",\n      \"durationMinutes\": 90,\n      \"timezone\": \"America/Montevideo\",\n      \"status\": \"CONFIRMED\",\n      \"type\": \"normal\",\n      \"price\": 1400,\n      \"paymentStatus\": \"PAID\",\n      \"source\": \"api\",\n      \"origin\": \"API\",\n      \"customer\": {\n        \"name\": \"Juan Pérez\",\n        \"phone\": \"+59891234567\",\n        \"email\": null\n      },\n      \"linked\": false,\n      \"owned\": true,\n      \"matchCount\": 0,\n      \"recording\": null,\n      \"createdAt\": \"2026-09-14T12:00:00.000Z\",\n      \"updatedAt\": \"2026-09-14T12:00:00.000Z\",\n      \"recurringId\": null\n    }\n  ],\n  \"total\": 1,\n  \"limit\": 100,\n  \"offset\": 0\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true},{"key":"status","value":"PENDING","description":"Filtra por status de la reserva.","disabled":true},{"key":"externalRef","value":"ORD-123","description":"Filtra por tu ref (sólo propias).","disabled":true},{"key":"updatedSince","value":"2026-09-14T12:00:00Z","description":"ISO 8601 con zona; como mucho 7 días hacia atrás. Filtra por `COALESCE(updated_at, created_at)`.","disabled":true},{"key":"all","value":"true","description":"`true` suma las reservas del club que NO creó esta integración, anónimas (`SlotDto`). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"paymentStatus","value":"PAID","description":"Filtra por estado de pago. Ojo: sólo la Partner API escribe `payment_status` (la app y el panel dejan `PENDING`): sirve si tu sistema es el que registra el cobro con `PATCH`. \"Pendientes de cobro de hoy\" = `?all=true&from=D&to=D&paymentStatus=PENDING&status=CONFIRMED`.","disabled":true}]},"description":"Reservas creadas por ESTA integración (`BookingDto`). Con `all=true` suma las demás del club anónimas: `ManagedSlotDto` (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`, `SlotDto` si no. Orden: fecha, hora, id. `limit` ≤ 200 (default 100). `updatedSince` como mucho 7 días hacia atrás.\n\nScope: `bookings:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true},{"key":"status","value":"PENDING","description":"Filtra por status de la reserva.","disabled":true},{"key":"externalRef","value":"ORD-123","description":"Filtra por tu ref (sólo propias).","disabled":true},{"key":"updatedSince","value":"2026-09-14T12:00:00Z","description":"ISO 8601 con zona; como mucho 7 días hacia atrás. Filtra por `COALESCE(updated_at, created_at)`.","disabled":true},{"key":"all","value":"true","description":"`true` suma las reservas del club que NO creó esta integración, anónimas (`SlotDto`). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"paymentStatus","value":"PAID","description":"Filtra por estado de pago. Ojo: sólo la Partner API escribe `payment_status` (la app y el panel dejan `PENDING`): sirve si tu sistema es el que registra el cobro con `PATCH`. \"Pendientes de cobro de hoy\" = `?all=true&from=D&to=D&paymentStatus=PENDING&status=CONFIRMED`.","disabled":true}]},"description":"Reservas creadas por ESTA integración (`BookingDto`). Con `all=true` suma las demás del club anónimas: `ManagedSlotDto` (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`, `SlotDto` si no. Orden: fecha, hora, id. `limit` ≤ 200 (default 100). `updatedSince` como mucho 7 días hacia atrás.\n\nScope: `bookings:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true},{"key":"status","value":"PENDING","description":"Filtra por status de la reserva.","disabled":true},{"key":"externalRef","value":"ORD-123","description":"Filtra por tu ref (sólo propias).","disabled":true},{"key":"updatedSince","value":"2026-09-14T12:00:00Z","description":"ISO 8601 con zona; como mucho 7 días hacia atrás. Filtra por `COALESCE(updated_at, created_at)`.","disabled":true},{"key":"all","value":"true","description":"`true` suma las reservas del club que NO creó esta integración, anónimas (`SlotDto`). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"paymentStatus","value":"PAID","description":"Filtra por estado de pago. Ojo: sólo la Partner API escribe `payment_status` (la app y el panel dejan `PENDING`): sirve si tu sistema es el que registra el cobro con `PATCH`. \"Pendientes de cobro de hoy\" = `?all=true&from=D&to=D&paymentStatus=PENDING&status=CONFIRMED`.","disabled":true}]},"description":"Reservas creadas por ESTA integración (`BookingDto`). Con `all=true` suma las demás del club anónimas: `ManagedSlotDto` (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`, `SlotDto` si no. Orden: fecha, hora, id. `limit` ≤ 200 (default 100). `updatedSince` como mucho 7 días hacia atrás.\n\nScope: `bookings:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true},{"key":"status","value":"PENDING","description":"Filtra por status de la reserva.","disabled":true},{"key":"externalRef","value":"ORD-123","description":"Filtra por tu ref (sólo propias).","disabled":true},{"key":"updatedSince","value":"2026-09-14T12:00:00Z","description":"ISO 8601 con zona; como mucho 7 días hacia atrás. Filtra por `COALESCE(updated_at, created_at)`.","disabled":true},{"key":"all","value":"true","description":"`true` suma las reservas del club que NO creó esta integración, anónimas (`SlotDto`). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"paymentStatus","value":"PAID","description":"Filtra por estado de pago. Ojo: sólo la Partner API escribe `payment_status` (la app y el panel dejan `PENDING`): sirve si tu sistema es el que registra el cobro con `PATCH`. \"Pendientes de cobro de hoy\" = `?all=true&from=D&to=D&paymentStatus=PENDING&status=CONFIRMED`.","disabled":true}]},"description":"Reservas creadas por ESTA integración (`BookingDto`). Con `all=true` suma las demás del club anónimas: `ManagedSlotDto` (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`, `SlotDto` si no. Orden: fecha, hora, id. `limit` ≤ 200 (default 100). `updatedSince` como mucho 7 días hacia atrás.\n\nScope: `bookings:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true},{"key":"status","value":"PENDING","description":"Filtra por status de la reserva.","disabled":true},{"key":"externalRef","value":"ORD-123","description":"Filtra por tu ref (sólo propias).","disabled":true},{"key":"updatedSince","value":"2026-09-14T12:00:00Z","description":"ISO 8601 con zona; como mucho 7 días hacia atrás. Filtra por `COALESCE(updated_at, created_at)`.","disabled":true},{"key":"all","value":"true","description":"`true` suma las reservas del club que NO creó esta integración, anónimas (`SlotDto`). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"paymentStatus","value":"PAID","description":"Filtra por estado de pago. Ojo: sólo la Partner API escribe `payment_status` (la app y el panel dejan `PENDING`): sirve si tu sistema es el que registra el cobro con `PATCH`. \"Pendientes de cobro de hoy\" = `?all=true&from=D&to=D&paymentStatus=PENDING&status=CONFIRMED`.","disabled":true}]},"description":"Reservas creadas por ESTA integración (`BookingDto`). Con `all=true` suma las demás del club anónimas: `ManagedSlotDto` (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`, `SlotDto` si no. Orden: fecha, hora, id. `limit` ≤ 200 (default 100). `updatedSince` como mucho 7 días hacia atrás.\n\nScope: `bookings:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-21","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`).","disabled":true},{"key":"status","value":"PENDING","description":"Filtra por status de la reserva.","disabled":true},{"key":"externalRef","value":"ORD-123","description":"Filtra por tu ref (sólo propias).","disabled":true},{"key":"updatedSince","value":"2026-09-14T12:00:00Z","description":"ISO 8601 con zona; como mucho 7 días hacia atrás. Filtra por `COALESCE(updated_at, created_at)`.","disabled":true},{"key":"all","value":"true","description":"`true` suma las reservas del club que NO creó esta integración, anónimas (`SlotDto`). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"paymentStatus","value":"PAID","description":"Filtra por estado de pago. Ojo: sólo la Partner API escribe `payment_status` (la app y el panel dejan `PENDING`): sirve si tu sistema es el que registra el cobro con `PATCH`. \"Pendientes de cobro de hoy\" = `?all=true&from=D&to=D&paymentStatus=PENDING&status=CONFIRMED`.","disabled":true}]},"description":"Reservas creadas por ESTA integración (`BookingDto`). Con `all=true` suma las demás del club anónimas: `ManagedSlotDto` (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`, `SlotDto` si no. Orden: fecha, hora, id. `limit` ≤ 200 (default 100). `updatedSince` como mucho 7 días hacia atrás.\n\nScope: `bookings:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Crear una reserva (idempotente) (createBooking)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"]},"description":"Alta de una reserva puntual. Nace `CONFIRMED` (el club es el autor), `source = api`, a nombre del usuario de servicio del club (o del jugador vinculado si la integración tiene `linkPlayersByPhone` y el teléfono matchea exactamente un usuario verificado). Validaciones en orden: turno → cancha → fecha/hora en la zona del club → horario → idempotencia → tope de futuras → precio → INSERT atómico contra las 4 fuentes de ocupación. Mandá SIEMPRE `externalRef`: repetir el mismo POST devuelve 200 + `Idempotent-Replay: true` (dos POST idénticos en paralelo → uno 201 y otro 200, una sola fila). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"date\": \"2026-09-15\",\n  \"startTime\": \"10:00\",\n  \"durationMinutes\": 90,\n  \"externalRef\": \"ORD-123\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"paymentStatus\": \"PAID\"\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · Replay: el `externalRef` ya existía vivo con el MISMO turno; se devuelve esa reserva.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"]},"description":"Alta de una reserva puntual. Nace `CONFIRMED` (el club es el autor), `source = api`, a nombre del usuario de servicio del club (o del jugador vinculado si la integración tiene `linkPlayersByPhone` y el teléfono matchea exactamente un usuario verificado). Validaciones en orden: turno → cancha → fecha/hora en la zona del club → horario → idempotencia → tope de futuras → precio → INSERT atómico contra las 4 fuentes de ocupación. Mandá SIEMPRE `externalRef`: repetir el mismo POST devuelve 200 + `Idempotent-Replay: true` (dos POST idénticos en paralelo → uno 201 y otro 200, una sola fila). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"date\": \"2026-09-15\",\n  \"startTime\": \"10:00\",\n  \"durationMinutes\": 90,\n  \"externalRef\": \"ORD-123\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"paymentStatus\": \"PAID\"\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"booking\": {\n    \"id\": \"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"externalRef\": \"ORD-123\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"date\": \"2026-09-15\",\n    \"startTime\": \"10:00\",\n    \"endTime\": \"11:30\",\n    \"durationMinutes\": 90,\n    \"timezone\": \"America/Montevideo\",\n    \"status\": \"CONFIRMED\",\n    \"type\": \"normal\",\n    \"price\": 1400,\n    \"paymentStatus\": \"PAID\",\n    \"source\": \"api\",\n    \"origin\": \"API\",\n    \"customer\": {\n      \"name\": \"Juan Pérez\",\n      \"phone\": \"+59891234567\",\n      \"email\": null\n    },\n    \"linked\": false,\n    \"owned\": true,\n    \"matchCount\": 0,\n    \"recording\": null,\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\",\n    \"updatedAt\": \"2026-09-14T12:00:00.000Z\",\n    \"recurringId\": null\n  }\n}"},{"name":"201 · Creada.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"]},"description":"Alta de una reserva puntual. Nace `CONFIRMED` (el club es el autor), `source = api`, a nombre del usuario de servicio del club (o del jugador vinculado si la integración tiene `linkPlayersByPhone` y el teléfono matchea exactamente un usuario verificado). Validaciones en orden: turno → cancha → fecha/hora en la zona del club → horario → idempotencia → tope de futuras → precio → INSERT atómico contra las 4 fuentes de ocupación. Mandá SIEMPRE `externalRef`: repetir el mismo POST devuelve 200 + `Idempotent-Replay: true` (dos POST idénticos en paralelo → uno 201 y otro 200, una sola fila). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"date\": \"2026-09-15\",\n  \"startTime\": \"10:00\",\n  \"durationMinutes\": 90,\n  \"externalRef\": \"ORD-123\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"paymentStatus\": \"PAID\"\n}","options":{"raw":{"language":"json"}}}},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"booking\": {\n    \"id\": \"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"externalRef\": \"ORD-123\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"date\": \"2026-09-15\",\n    \"startTime\": \"10:00\",\n    \"endTime\": \"11:30\",\n    \"durationMinutes\": 90,\n    \"timezone\": \"America/Montevideo\",\n    \"status\": \"CONFIRMED\",\n    \"type\": \"normal\",\n    \"price\": 1400,\n    \"paymentStatus\": \"PAID\",\n    \"source\": \"api\",\n    \"origin\": \"API\",\n    \"customer\": {\n      \"name\": \"Juan Pérez\",\n      \"phone\": \"+59891234567\",\n      \"email\": null\n    },\n    \"linked\": false,\n    \"owned\": true,\n    \"matchCount\": 0,\n    \"recording\": null,\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\",\n    \"updatedAt\": \"2026-09-14T12:00:00.000Z\",\n    \"recurringId\": null\n  }\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED / INVALID_DURATION / DATE_IN_PAST / MAX_ADVANCE_EXCEEDED / OUTSIDE_OPENING_HOURS / PRICE_UNAVAILABLE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"]},"description":"Alta de una reserva puntual. Nace `CONFIRMED` (el club es el autor), `source = api`, a nombre del usuario de servicio del club (o del jugador vinculado si la integración tiene `linkPlayersByPhone` y el teléfono matchea exactamente un usuario verificado). Validaciones en orden: turno → cancha → fecha/hora en la zona del club → horario → idempotencia → tope de futuras → precio → INSERT atómico contra las 4 fuentes de ocupación. Mandá SIEMPRE `externalRef`: repetir el mismo POST devuelve 200 + `Idempotent-Replay: true` (dos POST idénticos en paralelo → uno 201 y otro 200, una sola fila). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"date\": \"2026-09-15\",\n  \"startTime\": \"10:00\",\n  \"durationMinutes\": 90,\n  \"externalRef\": \"ORD-123\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"paymentStatus\": \"PAID\"\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"]},"description":"Alta de una reserva puntual. Nace `CONFIRMED` (el club es el autor), `source = api`, a nombre del usuario de servicio del club (o del jugador vinculado si la integración tiene `linkPlayersByPhone` y el teléfono matchea exactamente un usuario verificado). Validaciones en orden: turno → cancha → fecha/hora en la zona del club → horario → idempotencia → tope de futuras → precio → INSERT atómico contra las 4 fuentes de ocupación. Mandá SIEMPRE `externalRef`: repetir el mismo POST devuelve 200 + `Idempotent-Replay: true` (dos POST idénticos en paralelo → uno 201 y otro 200, una sola fila). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"date\": \"2026-09-15\",\n  \"startTime\": \"10:00\",\n  \"durationMinutes\": 90,\n  \"externalRef\": \"ORD-123\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"paymentStatus\": \"PAID\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"]},"description":"Alta de una reserva puntual. Nace `CONFIRMED` (el club es el autor), `source = api`, a nombre del usuario de servicio del club (o del jugador vinculado si la integración tiene `linkPlayersByPhone` y el teléfono matchea exactamente un usuario verificado). Validaciones en orden: turno → cancha → fecha/hora en la zona del club → horario → idempotencia → tope de futuras → precio → INSERT atómico contra las 4 fuentes de ocupación. Mandá SIEMPRE `externalRef`: repetir el mismo POST devuelve 200 + `Idempotent-Replay: true` (dos POST idénticos en paralelo → uno 201 y otro 200, una sola fila). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"date\": \"2026-09-15\",\n  \"startTime\": \"10:00\",\n  \"durationMinutes\": 90,\n  \"externalRef\": \"ORD-123\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"paymentStatus\": \"PAID\"\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · COURT_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"]},"description":"Alta de una reserva puntual. Nace `CONFIRMED` (el club es el autor), `source = api`, a nombre del usuario de servicio del club (o del jugador vinculado si la integración tiene `linkPlayersByPhone` y el teléfono matchea exactamente un usuario verificado). Validaciones en orden: turno → cancha → fecha/hora en la zona del club → horario → idempotencia → tope de futuras → precio → INSERT atómico contra las 4 fuentes de ocupación. Mandá SIEMPRE `externalRef`: repetir el mismo POST devuelve 200 + `Idempotent-Replay: true` (dos POST idénticos en paralelo → uno 201 y otro 200, una sola fila). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"date\": \"2026-09-15\",\n  \"startTime\": \"10:00\",\n  \"durationMinutes\": 90,\n  \"externalRef\": \"ORD-123\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"paymentStatus\": \"PAID\"\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La cancha no existe o no es de este club.\",\n  \"code\": \"COURT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · EXTERNAL_REF_USED / EXTERNAL_REF_CONFLICT / BOOKING_CONFLICT / RESOURCE_NOT_COURT","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"]},"description":"Alta de una reserva puntual. Nace `CONFIRMED` (el club es el autor), `source = api`, a nombre del usuario de servicio del club (o del jugador vinculado si la integración tiene `linkPlayersByPhone` y el teléfono matchea exactamente un usuario verificado). Validaciones en orden: turno → cancha → fecha/hora en la zona del club → horario → idempotencia → tope de futuras → precio → INSERT atómico contra las 4 fuentes de ocupación. Mandá SIEMPRE `externalRef`: repetir el mismo POST devuelve 200 + `Idempotent-Replay: true` (dos POST idénticos en paralelo → uno 201 y otro 200, una sola fila). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"date\": \"2026-09-15\",\n  \"startTime\": \"10:00\",\n  \"durationMinutes\": 90,\n  \"externalRef\": \"ORD-123\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"paymentStatus\": \"PAID\"\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ese externalRef ya se usó en una reserva cancelada: mandá otro.\",\n  \"code\": \"EXTERNAL_REF_USED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"]},"description":"Alta de una reserva puntual. Nace `CONFIRMED` (el club es el autor), `source = api`, a nombre del usuario de servicio del club (o del jugador vinculado si la integración tiene `linkPlayersByPhone` y el teléfono matchea exactamente un usuario verificado). Validaciones en orden: turno → cancha → fecha/hora en la zona del club → horario → idempotencia → tope de futuras → precio → INSERT atómico contra las 4 fuentes de ocupación. Mandá SIEMPRE `externalRef`: repetir el mismo POST devuelve 200 + `Idempotent-Replay: true` (dos POST idénticos en paralelo → uno 201 y otro 200, una sola fila). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"date\": \"2026-09-15\",\n  \"startTime\": \"10:00\",\n  \"durationMinutes\": 90,\n  \"externalRef\": \"ORD-123\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"paymentStatus\": \"PAID\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"]},"description":"Alta de una reserva puntual. Nace `CONFIRMED` (el club es el autor), `source = api`, a nombre del usuario de servicio del club (o del jugador vinculado si la integración tiene `linkPlayersByPhone` y el teléfono matchea exactamente un usuario verificado). Validaciones en orden: turno → cancha → fecha/hora en la zona del club → horario → idempotencia → tope de futuras → precio → INSERT atómico contra las 4 fuentes de ocupación. Mandá SIEMPRE `externalRef`: repetir el mismo POST devuelve 200 + `Idempotent-Replay: true` (dos POST idénticos en paralelo → uno 201 y otro 200, una sola fila). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"date\": \"2026-09-15\",\n  \"startTime\": \"10:00\",\n  \"durationMinutes\": 90,\n  \"externalRef\": \"ORD-123\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"paymentStatus\": \"PAID\"\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"]},"description":"Alta de una reserva puntual. Nace `CONFIRMED` (el club es el autor), `source = api`, a nombre del usuario de servicio del club (o del jugador vinculado si la integración tiene `linkPlayersByPhone` y el teléfono matchea exactamente un usuario verificado). Validaciones en orden: turno → cancha → fecha/hora en la zona del club → horario → idempotencia → tope de futuras → precio → INSERT atómico contra las 4 fuentes de ocupación. Mandá SIEMPRE `externalRef`: repetir el mismo POST devuelve 200 + `Idempotent-Replay: true` (dos POST idénticos en paralelo → uno 201 y otro 200, una sola fila). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"date\": \"2026-09-15\",\n  \"startTime\": \"10:00\",\n  \"durationMinutes\": 90,\n  \"externalRef\": \"ORD-123\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"paymentStatus\": \"PAID\"\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/bookings","host":["{{baseUrl}}"],"path":["bookings"]},"description":"Alta de una reserva puntual. Nace `CONFIRMED` (el club es el autor), `source = api`, a nombre del usuario de servicio del club (o del jugador vinculado si la integración tiene `linkPlayersByPhone` y el teléfono matchea exactamente un usuario verificado). Validaciones en orden: turno → cancha → fecha/hora en la zona del club → horario → idempotencia → tope de futuras → precio → INSERT atómico contra las 4 fuentes de ocupación. Mandá SIEMPRE `externalRef`: repetir el mismo POST devuelve 200 + `Idempotent-Replay: true` (dos POST idénticos en paralelo → uno 201 y otro 200, una sola fila). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"date\": \"2026-09-15\",\n  \"startTime\": \"10:00\",\n  \"durationMinutes\": 90,\n  \"externalRef\": \"ORD-123\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"paymentStatus\": \"PAID\"\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Detalle de una reserva (getBooking)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Propia → `BookingDto`. De otro origen / otra integración → 403 BOOKING_NOT_OWNED_BY_CLIENT, o `ManagedSlotDto` anónimo (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`.\n\nScope: `bookings:read`."},"response":[{"name":"200 · La reserva.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Propia → `BookingDto`. De otro origen / otra integración → 403 BOOKING_NOT_OWNED_BY_CLIENT, o `ManagedSlotDto` anónimo (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`.\n\nScope: `bookings:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"booking\": {\n    \"id\": \"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"externalRef\": \"ORD-123\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"date\": \"2026-09-15\",\n    \"startTime\": \"10:00\",\n    \"endTime\": \"11:30\",\n    \"durationMinutes\": 90,\n    \"timezone\": \"America/Montevideo\",\n    \"status\": \"CONFIRMED\",\n    \"type\": \"normal\",\n    \"price\": 1400,\n    \"paymentStatus\": \"PAID\",\n    \"source\": \"api\",\n    \"origin\": \"API\",\n    \"customer\": {\n      \"name\": \"Juan Pérez\",\n      \"phone\": \"+59891234567\",\n      \"email\": null\n    },\n    \"linked\": false,\n    \"owned\": true,\n    \"matchCount\": 0,\n    \"recording\": null,\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\",\n    \"updatedAt\": \"2026-09-14T12:00:00.000Z\",\n    \"recurringId\": null\n  }\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Propia → `BookingDto`. De otro origen / otra integración → 403 BOOKING_NOT_OWNED_BY_CLIENT, o `ManagedSlotDto` anónimo (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`.\n\nScope: `bookings:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Propia → `BookingDto`. De otro origen / otra integración → 403 BOOKING_NOT_OWNED_BY_CLIENT, o `ManagedSlotDto` anónimo (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`.\n\nScope: `bookings:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED / BOOKING_NOT_OWNED_BY_CLIENT","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Propia → `BookingDto`. De otro origen / otra integración → 403 BOOKING_NOT_OWNED_BY_CLIENT, o `ManagedSlotDto` anónimo (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`.\n\nScope: `bookings:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · BOOKING_NOT_FOUND","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Propia → `BookingDto`. De otro origen / otra integración → 403 BOOKING_NOT_OWNED_BY_CLIENT, o `ManagedSlotDto` anónimo (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`.\n\nScope: `bookings:read`."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva no existe o no es de este club.\",\n  \"code\": \"BOOKING_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Propia → `BookingDto`. De otro origen / otra integración → 403 BOOKING_NOT_OWNED_BY_CLIENT, o `ManagedSlotDto` anónimo (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`.\n\nScope: `bookings:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Propia → `BookingDto`. De otro origen / otra integración → 403 BOOKING_NOT_OWNED_BY_CLIENT, o `ManagedSlotDto` anónimo (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`.\n\nScope: `bookings:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Propia → `BookingDto`. De otro origen / otra integración → 403 BOOKING_NOT_OWNED_BY_CLIENT, o `ManagedSlotDto` anónimo (con `price` / `paymentStatus`) si la integración tiene `canManageAllBookings`.\n\nScope: `bookings:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Modificar una reserva (updateBooking)","request":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Mover cancha/fecha/horario, corregir el cliente, cambiar precio o estado de pago. Sólo propias (o `canManageAllBookings`, en cuyo caso la respuesta es `ManagedSlotDto`). Mover aplica las validaciones del alta sobre el destino con un UPDATE atómico contra las 4 fuentes; mover sin `price` recalcula con el tarifario del destino y conserva el override. `customer` reemplaza los tres campos; `customer: null` los borra. Una ocurrencia de fija sólo admite customer / price / paymentStatus (mover = DELETE + POST). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"startTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · La reserva actualizada.","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Mover cancha/fecha/horario, corregir el cliente, cambiar precio o estado de pago. Sólo propias (o `canManageAllBookings`, en cuyo caso la respuesta es `ManagedSlotDto`). Mover aplica las validaciones del alta sobre el destino con un UPDATE atómico contra las 4 fuentes; mover sin `price` recalcula con el tarifario del destino y conserva el override. `customer` reemplaza los tres campos; `customer: null` los borra. Una ocurrencia de fija sólo admite customer / price / paymentStatus (mover = DELETE + POST). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"startTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"booking\": {\n    \"id\": \"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"externalRef\": \"ORD-123\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"date\": \"2026-09-15\",\n    \"startTime\": \"10:00\",\n    \"endTime\": \"11:30\",\n    \"durationMinutes\": 90,\n    \"timezone\": \"America/Montevideo\",\n    \"status\": \"CONFIRMED\",\n    \"type\": \"normal\",\n    \"price\": 1400,\n    \"paymentStatus\": \"PAID\",\n    \"source\": \"api\",\n    \"origin\": \"API\",\n    \"customer\": {\n      \"name\": \"Juan Pérez\",\n      \"phone\": \"+59891234567\",\n      \"email\": null\n    },\n    \"linked\": false,\n    \"owned\": true,\n    \"matchCount\": 0,\n    \"recording\": null,\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\",\n    \"updatedAt\": \"2026-09-14T12:00:00.000Z\",\n    \"recurringId\": null\n  }\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / BOOKING_IN_PAST / INVALID_DURATION / DATE_IN_PAST / MAX_ADVANCE_EXCEEDED / OUTSIDE_OPENING_HOURS / PRICE_UNAVAILABLE","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Mover cancha/fecha/horario, corregir el cliente, cambiar precio o estado de pago. Sólo propias (o `canManageAllBookings`, en cuyo caso la respuesta es `ManagedSlotDto`). Mover aplica las validaciones del alta sobre el destino con un UPDATE atómico contra las 4 fuentes; mover sin `price` recalcula con el tarifario del destino y conserva el override. `customer` reemplaza los tres campos; `customer: null` los borra. Una ocurrencia de fija sólo admite customer / price / paymentStatus (mover = DELETE + POST). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"startTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Mover cancha/fecha/horario, corregir el cliente, cambiar precio o estado de pago. Sólo propias (o `canManageAllBookings`, en cuyo caso la respuesta es `ManagedSlotDto`). Mover aplica las validaciones del alta sobre el destino con un UPDATE atómico contra las 4 fuentes; mover sin `price` recalcula con el tarifario del destino y conserva el override. `customer` reemplaza los tres campos; `customer: null` los borra. Una ocurrencia de fija sólo admite customer / price / paymentStatus (mover = DELETE + POST). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"startTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED / BOOKING_NOT_OWNED_BY_CLIENT","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Mover cancha/fecha/horario, corregir el cliente, cambiar precio o estado de pago. Sólo propias (o `canManageAllBookings`, en cuyo caso la respuesta es `ManagedSlotDto`). Mover aplica las validaciones del alta sobre el destino con un UPDATE atómico contra las 4 fuentes; mover sin `price` recalcula con el tarifario del destino y conserva el override. `customer` reemplaza los tres campos; `customer: null` los borra. Una ocurrencia de fija sólo admite customer / price / paymentStatus (mover = DELETE + POST). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"startTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · BOOKING_NOT_FOUND / COURT_NOT_FOUND","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Mover cancha/fecha/horario, corregir el cliente, cambiar precio o estado de pago. Sólo propias (o `canManageAllBookings`, en cuyo caso la respuesta es `ManagedSlotDto`). Mover aplica las validaciones del alta sobre el destino con un UPDATE atómico contra las 4 fuentes; mover sin `price` recalcula con el tarifario del destino y conserva el override. `customer` reemplaza los tres campos; `customer: null` los borra. Una ocurrencia de fija sólo admite customer / price / paymentStatus (mover = DELETE + POST). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"startTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva no existe o no es de este club.\",\n  \"code\": \"BOOKING_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · BOOKING_CONFLICT / BOOKING_HAS_MATCH_ATTACHED / BOOKING_ALREADY_CANCELLED / BOOKING_NOT_MODIFIABLE / RESOURCE_NOT_COURT","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Mover cancha/fecha/horario, corregir el cliente, cambiar precio o estado de pago. Sólo propias (o `canManageAllBookings`, en cuyo caso la respuesta es `ManagedSlotDto`). Mover aplica las validaciones del alta sobre el destino con un UPDATE atómico contra las 4 fuentes; mover sin `price` recalcula con el tarifario del destino y conserva el override. `customer` reemplaza los tres campos; `customer: null` los borra. Una ocurrencia de fija sólo admite customer / price / paymentStatus (mover = DELETE + POST). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"startTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El turno ya está ocupado.\",\n  \"code\": \"BOOKING_CONFLICT\",\n  \"details\": {\n    \"busy\": [\n      {\n        \"startTime\": \"10:00\",\n        \"endTime\": \"11:30\"\n      }\n    ]\n  },\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Mover cancha/fecha/horario, corregir el cliente, cambiar precio o estado de pago. Sólo propias (o `canManageAllBookings`, en cuyo caso la respuesta es `ManagedSlotDto`). Mover aplica las validaciones del alta sobre el destino con un UPDATE atómico contra las 4 fuentes; mover sin `price` recalcula con el tarifario del destino y conserva el override. `customer` reemplaza los tres campos; `customer: null` los borra. Una ocurrencia de fija sólo admite customer / price / paymentStatus (mover = DELETE + POST). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"startTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Mover cancha/fecha/horario, corregir el cliente, cambiar precio o estado de pago. Sólo propias (o `canManageAllBookings`, en cuyo caso la respuesta es `ManagedSlotDto`). Mover aplica las validaciones del alta sobre el destino con un UPDATE atómico contra las 4 fuentes; mover sin `price` recalcula con el tarifario del destino y conserva el override. `customer` reemplaza los tres campos; `customer: null` los borra. Una ocurrencia de fija sólo admite customer / price / paymentStatus (mover = DELETE + POST). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"startTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Mover cancha/fecha/horario, corregir el cliente, cambiar precio o estado de pago. Sólo propias (o `canManageAllBookings`, en cuyo caso la respuesta es `ManagedSlotDto`). Mover aplica las validaciones del alta sobre el destino con un UPDATE atómico contra las 4 fuentes; mover sin `price` recalcula con el tarifario del destino y conserva el override. `customer` reemplaza los tres campos; `customer: null` los borra. Una ocurrencia de fija sólo admite customer / price / paymentStatus (mover = DELETE + POST). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"startTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Mover cancha/fecha/horario, corregir el cliente, cambiar precio o estado de pago. Sólo propias (o `canManageAllBookings`, en cuyo caso la respuesta es `ManagedSlotDto`). Mover aplica las validaciones del alta sobre el destino con un UPDATE atómico contra las 4 fuentes; mover sin `price` recalcula con el tarifario del destino y conserva el override. `customer` reemplaza los tres campos; `customer: null` los borra. Una ocurrencia de fija sólo admite customer / price / paymentStatus (mover = DELETE + POST). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"startTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Cancelar una reserva (cancelBooking)","request":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"query":[{"key":"force","value":"true","description":"`true` desliga los partidos vivos del turno en vez de responder 409 BOOKING_HAS_MATCH_ATTACHED (nunca los cancela). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo de la cancelación; va al audit del club.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Baja = cancelación por status, idempotente, nunca borrado físico. Sólo propias (o `canManageAllBookings`). Con partidos vivos en el turno responde 409 salvo `force=true`, que los desliga como lo haría el panel (nunca los cancela). El `externalRef` queda de un solo uso. `cancel_reason = API`, salvo sobre un pedido `PENDING` ajeno que esperaba al club (política MANUAL): ahí es el rechazo del club (`CLUB_REJECTED`, push \"rechazada\" al titular). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"response":[{"name":"200 · Cancelada, o ya lo estaba (`alreadyCancelled: true`).","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"query":[{"key":"force","value":"true","description":"`true` desliga los partidos vivos del turno en vez de responder 409 BOOKING_HAS_MATCH_ATTACHED (nunca los cancela). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo de la cancelación; va al audit del club.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Baja = cancelación por status, idempotente, nunca borrado físico. Sólo propias (o `canManageAllBookings`). Con partidos vivos en el turno responde 409 salvo `force=true`, que los desliga como lo haría el panel (nunca los cancela). El `externalRef` queda de un solo uso. `cancel_reason = API`, salvo sobre un pedido `PENDING` ajeno que esperaba al club (política MANUAL): ahí es el rechazo del club (`CLUB_REJECTED`, push \"rechazada\" al titular). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"booking\": {\n    \"id\": \"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"externalRef\": \"ORD-123\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"date\": \"2026-09-15\",\n    \"startTime\": \"10:00\",\n    \"endTime\": \"11:30\",\n    \"durationMinutes\": 90,\n    \"timezone\": \"America/Montevideo\",\n    \"status\": \"CANCELLED\",\n    \"type\": \"normal\",\n    \"price\": 1400,\n    \"paymentStatus\": \"PAID\",\n    \"source\": \"api\",\n    \"origin\": \"API\",\n    \"customer\": {\n      \"name\": \"Juan Pérez\",\n      \"phone\": \"+59891234567\",\n      \"email\": null\n    },\n    \"linked\": false,\n    \"owned\": true,\n    \"matchCount\": 0,\n    \"recording\": null,\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\",\n    \"updatedAt\": \"2026-09-14T12:00:00.000Z\",\n    \"recurringId\": null\n  },\n  \"detachedMatches\": 0,\n  \"alreadyCancelled\": false\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / BOOKING_IN_PAST","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"query":[{"key":"force","value":"true","description":"`true` desliga los partidos vivos del turno en vez de responder 409 BOOKING_HAS_MATCH_ATTACHED (nunca los cancela). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo de la cancelación; va al audit del club.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Baja = cancelación por status, idempotente, nunca borrado físico. Sólo propias (o `canManageAllBookings`). Con partidos vivos en el turno responde 409 salvo `force=true`, que los desliga como lo haría el panel (nunca los cancela). El `externalRef` queda de un solo uso. `cancel_reason = API`, salvo sobre un pedido `PENDING` ajeno que esperaba al club (política MANUAL): ahí es el rechazo del club (`CLUB_REJECTED`, push \"rechazada\" al titular). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"query":[{"key":"force","value":"true","description":"`true` desliga los partidos vivos del turno en vez de responder 409 BOOKING_HAS_MATCH_ATTACHED (nunca los cancela). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo de la cancelación; va al audit del club.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Baja = cancelación por status, idempotente, nunca borrado físico. Sólo propias (o `canManageAllBookings`). Con partidos vivos en el turno responde 409 salvo `force=true`, que los desliga como lo haría el panel (nunca los cancela). El `externalRef` queda de un solo uso. `cancel_reason = API`, salvo sobre un pedido `PENDING` ajeno que esperaba al club (política MANUAL): ahí es el rechazo del club (`CLUB_REJECTED`, push \"rechazada\" al titular). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED / BOOKING_NOT_OWNED_BY_CLIENT","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"query":[{"key":"force","value":"true","description":"`true` desliga los partidos vivos del turno en vez de responder 409 BOOKING_HAS_MATCH_ATTACHED (nunca los cancela). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo de la cancelación; va al audit del club.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Baja = cancelación por status, idempotente, nunca borrado físico. Sólo propias (o `canManageAllBookings`). Con partidos vivos en el turno responde 409 salvo `force=true`, que los desliga como lo haría el panel (nunca los cancela). El `externalRef` queda de un solo uso. `cancel_reason = API`, salvo sobre un pedido `PENDING` ajeno que esperaba al club (política MANUAL): ahí es el rechazo del club (`CLUB_REJECTED`, push \"rechazada\" al titular). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · BOOKING_NOT_FOUND","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"query":[{"key":"force","value":"true","description":"`true` desliga los partidos vivos del turno en vez de responder 409 BOOKING_HAS_MATCH_ATTACHED (nunca los cancela). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo de la cancelación; va al audit del club.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Baja = cancelación por status, idempotente, nunca borrado físico. Sólo propias (o `canManageAllBookings`). Con partidos vivos en el turno responde 409 salvo `force=true`, que los desliga como lo haría el panel (nunca los cancela). El `externalRef` queda de un solo uso. `cancel_reason = API`, salvo sobre un pedido `PENDING` ajeno que esperaba al club (política MANUAL): ahí es el rechazo del club (`CLUB_REJECTED`, push \"rechazada\" al titular). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva no existe o no es de este club.\",\n  \"code\": \"BOOKING_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · BOOKING_HAS_MATCH_ATTACHED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"query":[{"key":"force","value":"true","description":"`true` desliga los partidos vivos del turno en vez de responder 409 BOOKING_HAS_MATCH_ATTACHED (nunca los cancela). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo de la cancelación; va al audit del club.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Baja = cancelación por status, idempotente, nunca borrado físico. Sólo propias (o `canManageAllBookings`). Con partidos vivos en el turno responde 409 salvo `force=true`, que los desliga como lo haría el panel (nunca los cancela). El `externalRef` queda de un solo uso. `cancel_reason = API`, salvo sobre un pedido `PENDING` ajeno que esperaba al club (política MANUAL): ahí es el rechazo del club (`CLUB_REJECTED`, push \"rechazada\" al titular). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva tiene partidos armados. Repetí con force=true para desligarlos.\",\n  \"code\": \"BOOKING_HAS_MATCH_ATTACHED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"query":[{"key":"force","value":"true","description":"`true` desliga los partidos vivos del turno en vez de responder 409 BOOKING_HAS_MATCH_ATTACHED (nunca los cancela). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo de la cancelación; va al audit del club.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Baja = cancelación por status, idempotente, nunca borrado físico. Sólo propias (o `canManageAllBookings`). Con partidos vivos en el turno responde 409 salvo `force=true`, que los desliga como lo haría el panel (nunca los cancela). El `externalRef` queda de un solo uso. `cancel_reason = API`, salvo sobre un pedido `PENDING` ajeno que esperaba al club (política MANUAL): ahí es el rechazo del club (`CLUB_REJECTED`, push \"rechazada\" al titular). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"query":[{"key":"force","value":"true","description":"`true` desliga los partidos vivos del turno en vez de responder 409 BOOKING_HAS_MATCH_ATTACHED (nunca los cancela). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo de la cancelación; va al audit del club.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Baja = cancelación por status, idempotente, nunca borrado físico. Sólo propias (o `canManageAllBookings`). Con partidos vivos en el turno responde 409 salvo `force=true`, que los desliga como lo haría el panel (nunca los cancela). El `externalRef` queda de un solo uso. `cancel_reason = API`, salvo sobre un pedido `PENDING` ajeno que esperaba al club (política MANUAL): ahí es el rechazo del club (`CLUB_REJECTED`, push \"rechazada\" al titular). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id","host":["{{baseUrl}}"],"path":["bookings",":id"],"query":[{"key":"force","value":"true","description":"`true` desliga los partidos vivos del turno en vez de responder 409 BOOKING_HAS_MATCH_ATTACHED (nunca los cancela). Booleano. En query también se aceptan los strings \"true\" / \"false\" / \"1\" / \"0\".","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo de la cancelación; va al audit del club.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Baja = cancelación por status, idempotente, nunca borrado físico. Sólo propias (o `canManageAllBookings`). Con partidos vivos en el turno responde 409 salvo `force=true`, que los desliga como lo haría el panel (nunca los cancela). El `externalRef` queda de un solo uso. `cancel_reason = API`, salvo sobre un pedido `PENDING` ajeno que esperaba al club (política MANUAL): ahí es el rechazo del club (`CLUB_REJECTED`, push \"rechazada\" al titular). Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Confirmar un pedido pendiente (confirmBooking)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id/confirm","host":["{{baseUrl}}"],"path":["bookings",":id","confirm"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Aprueba un pedido `PENDING` de la app (categoría con política de confirmación MANUAL) como lo haría el panel. Sin body. Sólo integraciones con `canManageAllBookings` (la API crea `CONFIRMED`: una `PENDING` nunca es propia). El UPDATE está condicionado a `PENDING` y a que ninguna otra `CONFIRMED` pise el turno; si el pedido venció (cron), el jugador lo retiró u otro operador lo resolvió en el medio, se responde por el estado final. Efectos: grabación del turno si la cancha tiene cámara, audit `BOOKING_CONFIRMED`, `booking.confirmed` en `/events` y webhooks, push `BOOKING_CONFIRMED` al titular. Respuesta anónima (`SlotDto`). Idempotente: sobre una ya `CONFIRMED` responde 200 con `alreadyConfirmed: true`. Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"response":[{"name":"200 · Confirmada, o ya lo estaba (`alreadyConfirmed: true`).","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id/confirm","host":["{{baseUrl}}"],"path":["bookings",":id","confirm"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Aprueba un pedido `PENDING` de la app (categoría con política de confirmación MANUAL) como lo haría el panel. Sin body. Sólo integraciones con `canManageAllBookings` (la API crea `CONFIRMED`: una `PENDING` nunca es propia). El UPDATE está condicionado a `PENDING` y a que ninguna otra `CONFIRMED` pise el turno; si el pedido venció (cron), el jugador lo retiró u otro operador lo resolvió en el medio, se responde por el estado final. Efectos: grabación del turno si la cancha tiene cámara, audit `BOOKING_CONFIRMED`, `booking.confirmed` en `/events` y webhooks, push `BOOKING_CONFIRMED` al titular. Respuesta anónima (`SlotDto`). Idempotente: sobre una ya `CONFIRMED` responde 200 con `alreadyConfirmed: true`. Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"booking\": {\n    \"id\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"date\": \"2026-09-15\",\n    \"startTime\": \"16:00\",\n    \"endTime\": \"17:00\",\n    \"status\": \"CONFIRMED\",\n    \"origin\": \"APP\",\n    \"owned\": false,\n    \"matchCount\": 1,\n    \"recurringId\": null\n  },\n  \"alreadyConfirmed\": false\n}"},{"name":"400 · MALFORMED_API_KEY / BOOKING_IN_PAST","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id/confirm","host":["{{baseUrl}}"],"path":["bookings",":id","confirm"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Aprueba un pedido `PENDING` de la app (categoría con política de confirmación MANUAL) como lo haría el panel. Sin body. Sólo integraciones con `canManageAllBookings` (la API crea `CONFIRMED`: una `PENDING` nunca es propia). El UPDATE está condicionado a `PENDING` y a que ninguna otra `CONFIRMED` pise el turno; si el pedido venció (cron), el jugador lo retiró u otro operador lo resolvió en el medio, se responde por el estado final. Efectos: grabación del turno si la cancha tiene cámara, audit `BOOKING_CONFIRMED`, `booking.confirmed` en `/events` y webhooks, push `BOOKING_CONFIRMED` al titular. Respuesta anónima (`SlotDto`). Idempotente: sobre una ya `CONFIRMED` responde 200 con `alreadyConfirmed: true`. Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id/confirm","host":["{{baseUrl}}"],"path":["bookings",":id","confirm"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Aprueba un pedido `PENDING` de la app (categoría con política de confirmación MANUAL) como lo haría el panel. Sin body. Sólo integraciones con `canManageAllBookings` (la API crea `CONFIRMED`: una `PENDING` nunca es propia). El UPDATE está condicionado a `PENDING` y a que ninguna otra `CONFIRMED` pise el turno; si el pedido venció (cron), el jugador lo retiró u otro operador lo resolvió en el medio, se responde por el estado final. Efectos: grabación del turno si la cancha tiene cámara, audit `BOOKING_CONFIRMED`, `booking.confirmed` en `/events` y webhooks, push `BOOKING_CONFIRMED` al titular. Respuesta anónima (`SlotDto`). Idempotente: sobre una ya `CONFIRMED` responde 200 con `alreadyConfirmed: true`. Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED / BOOKING_NOT_OWNED_BY_CLIENT","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id/confirm","host":["{{baseUrl}}"],"path":["bookings",":id","confirm"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Aprueba un pedido `PENDING` de la app (categoría con política de confirmación MANUAL) como lo haría el panel. Sin body. Sólo integraciones con `canManageAllBookings` (la API crea `CONFIRMED`: una `PENDING` nunca es propia). El UPDATE está condicionado a `PENDING` y a que ninguna otra `CONFIRMED` pise el turno; si el pedido venció (cron), el jugador lo retiró u otro operador lo resolvió en el medio, se responde por el estado final. Efectos: grabación del turno si la cancha tiene cámara, audit `BOOKING_CONFIRMED`, `booking.confirmed` en `/events` y webhooks, push `BOOKING_CONFIRMED` al titular. Respuesta anónima (`SlotDto`). Idempotente: sobre una ya `CONFIRMED` responde 200 con `alreadyConfirmed: true`. Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · BOOKING_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id/confirm","host":["{{baseUrl}}"],"path":["bookings",":id","confirm"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Aprueba un pedido `PENDING` de la app (categoría con política de confirmación MANUAL) como lo haría el panel. Sin body. Sólo integraciones con `canManageAllBookings` (la API crea `CONFIRMED`: una `PENDING` nunca es propia). El UPDATE está condicionado a `PENDING` y a que ninguna otra `CONFIRMED` pise el turno; si el pedido venció (cron), el jugador lo retiró u otro operador lo resolvió en el medio, se responde por el estado final. Efectos: grabación del turno si la cancha tiene cámara, audit `BOOKING_CONFIRMED`, `booking.confirmed` en `/events` y webhooks, push `BOOKING_CONFIRMED` al titular. Respuesta anónima (`SlotDto`). Idempotente: sobre una ya `CONFIRMED` responde 200 con `alreadyConfirmed: true`. Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva no existe o no es de este club.\",\n  \"code\": \"BOOKING_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · BOOKING_ALREADY_CANCELLED / BOOKING_NOT_PENDING / BOOKING_CONFLICT","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id/confirm","host":["{{baseUrl}}"],"path":["bookings",":id","confirm"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Aprueba un pedido `PENDING` de la app (categoría con política de confirmación MANUAL) como lo haría el panel. Sin body. Sólo integraciones con `canManageAllBookings` (la API crea `CONFIRMED`: una `PENDING` nunca es propia). El UPDATE está condicionado a `PENDING` y a que ninguna otra `CONFIRMED` pise el turno; si el pedido venció (cron), el jugador lo retiró u otro operador lo resolvió en el medio, se responde por el estado final. Efectos: grabación del turno si la cancha tiene cámara, audit `BOOKING_CONFIRMED`, `booking.confirmed` en `/events` y webhooks, push `BOOKING_CONFIRMED` al titular. Respuesta anónima (`SlotDto`). Idempotente: sobre una ya `CONFIRMED` responde 200 con `alreadyConfirmed: true`. Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva ya está cancelada.\",\n  \"code\": \"BOOKING_ALREADY_CANCELLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id/confirm","host":["{{baseUrl}}"],"path":["bookings",":id","confirm"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Aprueba un pedido `PENDING` de la app (categoría con política de confirmación MANUAL) como lo haría el panel. Sin body. Sólo integraciones con `canManageAllBookings` (la API crea `CONFIRMED`: una `PENDING` nunca es propia). El UPDATE está condicionado a `PENDING` y a que ninguna otra `CONFIRMED` pise el turno; si el pedido venció (cron), el jugador lo retiró u otro operador lo resolvió en el medio, se responde por el estado final. Efectos: grabación del turno si la cancha tiene cámara, audit `BOOKING_CONFIRMED`, `booking.confirmed` en `/events` y webhooks, push `BOOKING_CONFIRMED` al titular. Respuesta anónima (`SlotDto`). Idempotente: sobre una ya `CONFIRMED` responde 200 con `alreadyConfirmed: true`. Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id/confirm","host":["{{baseUrl}}"],"path":["bookings",":id","confirm"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Aprueba un pedido `PENDING` de la app (categoría con política de confirmación MANUAL) como lo haría el panel. Sin body. Sólo integraciones con `canManageAllBookings` (la API crea `CONFIRMED`: una `PENDING` nunca es propia). El UPDATE está condicionado a `PENDING` y a que ninguna otra `CONFIRMED` pise el turno; si el pedido venció (cron), el jugador lo retiró u otro operador lo resolvió en el medio, se responde por el estado final. Efectos: grabación del turno si la cancha tiene cámara, audit `BOOKING_CONFIRMED`, `booking.confirmed` en `/events` y webhooks, push `BOOKING_CONFIRMED` al titular. Respuesta anónima (`SlotDto`). Idempotente: sobre una ya `CONFIRMED` responde 200 con `alreadyConfirmed: true`. Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/bookings/:id/confirm","host":["{{baseUrl}}"],"path":["bookings",":id","confirm"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Aprueba un pedido `PENDING` de la app (categoría con política de confirmación MANUAL) como lo haría el panel. Sin body. Sólo integraciones con `canManageAllBookings` (la API crea `CONFIRMED`: una `PENDING` nunca es propia). El UPDATE está condicionado a `PENDING` y a que ninguna otra `CONFIRMED` pise el turno; si el pedido venció (cron), el jugador lo retiró u otro operador lo resolvió en el medio, se responde por el estado final. Efectos: grabación del turno si la cancha tiene cámara, audit `BOOKING_CONFIRMED`, `booking.confirmed` en `/events` y webhooks, push `BOOKING_CONFIRMED` al titular. Respuesta anónima (`SlotDto`). Idempotente: sobre una ya `CONFIRMED` responde 200 con `alreadyConfirmed: true`. Consume cuota de escritura.\n\nScope: `bookings:write`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]}]},{"name":"Eventos","description":"Outbox de todo cambio de agenda, por polling.","item":[{"name":"Qué cambió en la agenda (listEvents)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/events","host":["{{baseUrl}}"],"path":["events"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"since","value":"1042","description":"Último `id` de evento procesado: se devuelven `id > since`. Sin `since` no se listan eventos, sólo el cursor actual (`nextSince`).","disabled":true},{"key":"limit","value":"1","description":"Eventos por página, 1..200 (default y máximo 200).","disabled":true}]},"description":"Polling de TODO lo que cambió en la agenda del club, venga de donde venga (tus reservas, las de otras integraciones, la app, el panel, QuieroJugar, torneos, crons, bloqueos / huecos / series de fijas). Proyección por lector: lo propio viaja como `BookingDto` hidratado desde la fila actual; lo ajeno como `SlotDto` anónimo. Cursor: `since` = último `id` procesado; sin `since` no se listan eventos (arranque: guardá `nextSince`). Garantías: at-least-once y orden por `id` dentro del club; procesá cada evento idempotentemente. No consume cuota de escritura.\n\nScope: `events:read`."},"response":[{"name":"200 · Eventos `id > since` en orden ascendente, y el cursor para el próximo poll.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/events","host":["{{baseUrl}}"],"path":["events"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"since","value":"1042","description":"Último `id` de evento procesado: se devuelven `id > since`. Sin `since` no se listan eventos, sólo el cursor actual (`nextSince`).","disabled":true},{"key":"limit","value":"1","description":"Eventos por página, 1..200 (default y máximo 200).","disabled":true}]},"description":"Polling de TODO lo que cambió en la agenda del club, venga de donde venga (tus reservas, las de otras integraciones, la app, el panel, QuieroJugar, torneos, crons, bloqueos / huecos / series de fijas). Proyección por lector: lo propio viaja como `BookingDto` hidratado desde la fila actual; lo ajeno como `SlotDto` anónimo. Cursor: `since` = último `id` procesado; sin `since` no se listan eventos (arranque: guardá `nextSince`). Garantías: at-least-once y orden por `id` dentro del club; procesá cada evento idempotentemente. No consume cuota de escritura.\n\nScope: `events:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"events\": [\n    {\n      \"id\": 1042,\n      \"type\": \"booking.cancelled\",\n      \"createdAt\": \"2026-09-14T15:02:11.000Z\",\n      \"actor\": \"admin\",\n      \"reason\": \"club\",\n      \"booking\": {\n        \"id\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n        \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n        \"kind\": \"COURT\",\n        \"categoryId\": null,\n        \"resourceNoun\": \"COURT\",\n        \"date\": \"2026-09-15\",\n        \"startTime\": \"16:00\",\n        \"endTime\": \"17:00\",\n        \"status\": \"CONFIRMED\",\n        \"origin\": \"APP\",\n        \"owned\": false,\n        \"matchCount\": 1,\n        \"recurringId\": null\n      }\n    },\n    {\n      \"id\": 1043,\n      \"type\": \"occupancy.changed\",\n      \"createdAt\": \"2026-09-14T15:04:00.000Z\",\n      \"actor\": \"admin\",\n      \"reason\": \"court_block\",\n      \"occupancy\": {\n        \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n        \"from\": \"2026-09-20\",\n        \"to\": \"2026-09-22\"\n      }\n    }\n  ],\n  \"nextSince\": 1043\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/events","host":["{{baseUrl}}"],"path":["events"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"since","value":"1042","description":"Último `id` de evento procesado: se devuelven `id > since`. Sin `since` no se listan eventos, sólo el cursor actual (`nextSince`).","disabled":true},{"key":"limit","value":"1","description":"Eventos por página, 1..200 (default y máximo 200).","disabled":true}]},"description":"Polling de TODO lo que cambió en la agenda del club, venga de donde venga (tus reservas, las de otras integraciones, la app, el panel, QuieroJugar, torneos, crons, bloqueos / huecos / series de fijas). Proyección por lector: lo propio viaja como `BookingDto` hidratado desde la fila actual; lo ajeno como `SlotDto` anónimo. Cursor: `since` = último `id` procesado; sin `since` no se listan eventos (arranque: guardá `nextSince`). Garantías: at-least-once y orden por `id` dentro del club; procesá cada evento idempotentemente. No consume cuota de escritura.\n\nScope: `events:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/events","host":["{{baseUrl}}"],"path":["events"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"since","value":"1042","description":"Último `id` de evento procesado: se devuelven `id > since`. Sin `since` no se listan eventos, sólo el cursor actual (`nextSince`).","disabled":true},{"key":"limit","value":"1","description":"Eventos por página, 1..200 (default y máximo 200).","disabled":true}]},"description":"Polling de TODO lo que cambió en la agenda del club, venga de donde venga (tus reservas, las de otras integraciones, la app, el panel, QuieroJugar, torneos, crons, bloqueos / huecos / series de fijas). Proyección por lector: lo propio viaja como `BookingDto` hidratado desde la fila actual; lo ajeno como `SlotDto` anónimo. Cursor: `since` = último `id` procesado; sin `since` no se listan eventos (arranque: guardá `nextSince`). Garantías: at-least-once y orden por `id` dentro del club; procesá cada evento idempotentemente. No consume cuota de escritura.\n\nScope: `events:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/events","host":["{{baseUrl}}"],"path":["events"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"since","value":"1042","description":"Último `id` de evento procesado: se devuelven `id > since`. Sin `since` no se listan eventos, sólo el cursor actual (`nextSince`).","disabled":true},{"key":"limit","value":"1","description":"Eventos por página, 1..200 (default y máximo 200).","disabled":true}]},"description":"Polling de TODO lo que cambió en la agenda del club, venga de donde venga (tus reservas, las de otras integraciones, la app, el panel, QuieroJugar, torneos, crons, bloqueos / huecos / series de fijas). Proyección por lector: lo propio viaja como `BookingDto` hidratado desde la fila actual; lo ajeno como `SlotDto` anónimo. Cursor: `since` = último `id` procesado; sin `since` no se listan eventos (arranque: guardá `nextSince`). Garantías: at-least-once y orden por `id` dentro del club; procesá cada evento idempotentemente. No consume cuota de escritura.\n\nScope: `events:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"410 · EVENTS_CURSOR_EXPIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/events","host":["{{baseUrl}}"],"path":["events"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"since","value":"1042","description":"Último `id` de evento procesado: se devuelven `id > since`. Sin `since` no se listan eventos, sólo el cursor actual (`nextSince`).","disabled":true},{"key":"limit","value":"1","description":"Eventos por página, 1..200 (default y máximo 200).","disabled":true}]},"description":"Polling de TODO lo que cambió en la agenda del club, venga de donde venga (tus reservas, las de otras integraciones, la app, el panel, QuieroJugar, torneos, crons, bloqueos / huecos / series de fijas). Proyección por lector: lo propio viaja como `BookingDto` hidratado desde la fila actual; lo ajeno como `SlotDto` anónimo. Cursor: `since` = último `id` procesado; sin `since` no se listan eventos (arranque: guardá `nextSince`). Garantías: at-least-once y orden por `id` dentro del club; procesá cada evento idempotentemente. No consume cuota de escritura.\n\nScope: `events:read`."},"status":"Gone","code":410,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cursor es demasiado viejo: resincronizá por /bookings y /occupancy.\",\n  \"code\": \"EVENTS_CURSOR_EXPIRED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/events","host":["{{baseUrl}}"],"path":["events"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"since","value":"1042","description":"Último `id` de evento procesado: se devuelven `id > since`. Sin `since` no se listan eventos, sólo el cursor actual (`nextSince`).","disabled":true},{"key":"limit","value":"1","description":"Eventos por página, 1..200 (default y máximo 200).","disabled":true}]},"description":"Polling de TODO lo que cambió en la agenda del club, venga de donde venga (tus reservas, las de otras integraciones, la app, el panel, QuieroJugar, torneos, crons, bloqueos / huecos / series de fijas). Proyección por lector: lo propio viaja como `BookingDto` hidratado desde la fila actual; lo ajeno como `SlotDto` anónimo. Cursor: `since` = último `id` procesado; sin `since` no se listan eventos (arranque: guardá `nextSince`). Garantías: at-least-once y orden por `id` dentro del club; procesá cada evento idempotentemente. No consume cuota de escritura.\n\nScope: `events:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/events","host":["{{baseUrl}}"],"path":["events"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"since","value":"1042","description":"Último `id` de evento procesado: se devuelven `id > since`. Sin `since` no se listan eventos, sólo el cursor actual (`nextSince`).","disabled":true},{"key":"limit","value":"1","description":"Eventos por página, 1..200 (default y máximo 200).","disabled":true}]},"description":"Polling de TODO lo que cambió en la agenda del club, venga de donde venga (tus reservas, las de otras integraciones, la app, el panel, QuieroJugar, torneos, crons, bloqueos / huecos / series de fijas). Proyección por lector: lo propio viaja como `BookingDto` hidratado desde la fila actual; lo ajeno como `SlotDto` anónimo. Cursor: `since` = último `id` procesado; sin `since` no se listan eventos (arranque: guardá `nextSince`). Garantías: at-least-once y orden por `id` dentro del club; procesá cada evento idempotentemente. No consume cuota de escritura.\n\nScope: `events:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/events","host":["{{baseUrl}}"],"path":["events"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"since","value":"1042","description":"Último `id` de evento procesado: se devuelven `id > since`. Sin `since` no se listan eventos, sólo el cursor actual (`nextSince`).","disabled":true},{"key":"limit","value":"1","description":"Eventos por página, 1..200 (default y máximo 200).","disabled":true}]},"description":"Polling de TODO lo que cambió en la agenda del club, venga de donde venga (tus reservas, las de otras integraciones, la app, el panel, QuieroJugar, torneos, crons, bloqueos / huecos / series de fijas). Proyección por lector: lo propio viaja como `BookingDto` hidratado desde la fila actual; lo ajeno como `SlotDto` anónimo. Cursor: `since` = último `id` procesado; sin `since` no se listan eventos (arranque: guardá `nextSince`). Garantías: at-least-once y orden por `id` dentro del club; procesá cada evento idempotentemente. No consume cuota de escritura.\n\nScope: `events:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]}]},{"name":"Canchas, precios y horarios","description":"Configuración del club por API: alta / edición / baja de canchas, tarifario por franja y duración, defaults y horario semanal. Scopes de escritura sensibles (sólo el OWNER emite la key).","item":[{"name":"Crear una cancha (createCourt)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"]},"description":"Alta de una cancha (o de un recurso de otra categoría, F6) con las mismas reglas que el panel: nace habilitada, con `pricePerHour` propio o el default del club y con las franjas del horario por defecto del club (si el club no tiene horario por defecto nace sin franjas: cargalas con `PUT /courts/{id}/pricing`). Devuelve el MISMO `Court` de `GET /courts`. Nunca cámara ni ingest de streaming. Emite `occupancy.changed` si nació con franjas. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 5\",\n  \"sports\": [\n    \"PADEL\"\n  ],\n  \"isIndoor\": false,\n  \"surface\": \"Césped sintético\"\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"201 · Creada.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"]},"description":"Alta de una cancha (o de un recurso de otra categoría, F6) con las mismas reglas que el panel: nace habilitada, con `pricePerHour` propio o el default del club y con las franjas del horario por defecto del club (si el club no tiene horario por defecto nace sin franjas: cargalas con `PUT /courts/{id}/pricing`). Devuelve el MISMO `Court` de `GET /courts`. Nunca cámara ni ingest de streaming. Emite `occupancy.changed` si nació con franjas. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 5\",\n  \"sports\": [\n    \"PADEL\"\n  ],\n  \"isIndoor\": false,\n  \"surface\": \"Césped sintético\"\n}","options":{"raw":{"language":"json"}}}},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"court\": {\n    \"id\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"name\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"sports\": [\n      \"PADEL\"\n    ],\n    \"enabled\": true,\n    \"isIndoor\": false,\n    \"pricing\": [\n      {\n        \"pricePerHour\": 1000,\n        \"price60\": null,\n        \"price90\": 1400,\n        \"price120\": null,\n        \"ranges\": [\n          {\n            \"start\": \"08:00\",\n            \"end\": \"23:00\"\n          }\n        ]\n      }\n    ]\n  },\n  \"features\": [\n    {\n      \"id\": \"feat-cancha-exterior\",\n      \"name\": \"Cancha Exterior\"\n    },\n    {\n      \"id\": \"feat-paredes-cristal\",\n      \"name\": \"Paredes de Cristal\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED / CATEGORY_REQUIRED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"]},"description":"Alta de una cancha (o de un recurso de otra categoría, F6) con las mismas reglas que el panel: nace habilitada, con `pricePerHour` propio o el default del club y con las franjas del horario por defecto del club (si el club no tiene horario por defecto nace sin franjas: cargalas con `PUT /courts/{id}/pricing`). Devuelve el MISMO `Court` de `GET /courts`. Nunca cámara ni ingest de streaming. Emite `occupancy.changed` si nació con franjas. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 5\",\n  \"sports\": [\n    \"PADEL\"\n  ],\n  \"isIndoor\": false,\n  \"surface\": \"Césped sintético\"\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"]},"description":"Alta de una cancha (o de un recurso de otra categoría, F6) con las mismas reglas que el panel: nace habilitada, con `pricePerHour` propio o el default del club y con las franjas del horario por defecto del club (si el club no tiene horario por defecto nace sin franjas: cargalas con `PUT /courts/{id}/pricing`). Devuelve el MISMO `Court` de `GET /courts`. Nunca cámara ni ingest de streaming. Emite `occupancy.changed` si nació con franjas. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 5\",\n  \"sports\": [\n    \"PADEL\"\n  ],\n  \"isIndoor\": false,\n  \"surface\": \"Césped sintético\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"]},"description":"Alta de una cancha (o de un recurso de otra categoría, F6) con las mismas reglas que el panel: nace habilitada, con `pricePerHour` propio o el default del club y con las franjas del horario por defecto del club (si el club no tiene horario por defecto nace sin franjas: cargalas con `PUT /courts/{id}/pricing`). Devuelve el MISMO `Court` de `GET /courts`. Nunca cámara ni ingest de streaming. Emite `occupancy.changed` si nació con franjas. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 5\",\n  \"sports\": [\n    \"PADEL\"\n  ],\n  \"isIndoor\": false,\n  \"surface\": \"Césped sintético\"\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · CATEGORY_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"]},"description":"Alta de una cancha (o de un recurso de otra categoría, F6) con las mismas reglas que el panel: nace habilitada, con `pricePerHour` propio o el default del club y con las franjas del horario por defecto del club (si el club no tiene horario por defecto nace sin franjas: cargalas con `PUT /courts/{id}/pricing`). Devuelve el MISMO `Court` de `GET /courts`. Nunca cámara ni ingest de streaming. Emite `occupancy.changed` si nació con franjas. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 5\",\n  \"sports\": [\n    \"PADEL\"\n  ],\n  \"isIndoor\": false,\n  \"surface\": \"Césped sintético\"\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La categoría no existe o no es de este club.\",\n  \"code\": \"CATEGORY_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"]},"description":"Alta de una cancha (o de un recurso de otra categoría, F6) con las mismas reglas que el panel: nace habilitada, con `pricePerHour` propio o el default del club y con las franjas del horario por defecto del club (si el club no tiene horario por defecto nace sin franjas: cargalas con `PUT /courts/{id}/pricing`). Devuelve el MISMO `Court` de `GET /courts`. Nunca cámara ni ingest de streaming. Emite `occupancy.changed` si nació con franjas. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 5\",\n  \"sports\": [\n    \"PADEL\"\n  ],\n  \"isIndoor\": false,\n  \"surface\": \"Césped sintético\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"]},"description":"Alta de una cancha (o de un recurso de otra categoría, F6) con las mismas reglas que el panel: nace habilitada, con `pricePerHour` propio o el default del club y con las franjas del horario por defecto del club (si el club no tiene horario por defecto nace sin franjas: cargalas con `PUT /courts/{id}/pricing`). Devuelve el MISMO `Court` de `GET /courts`. Nunca cámara ni ingest de streaming. Emite `occupancy.changed` si nació con franjas. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 5\",\n  \"sports\": [\n    \"PADEL\"\n  ],\n  \"isIndoor\": false,\n  \"surface\": \"Césped sintético\"\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"]},"description":"Alta de una cancha (o de un recurso de otra categoría, F6) con las mismas reglas que el panel: nace habilitada, con `pricePerHour` propio o el default del club y con las franjas del horario por defecto del club (si el club no tiene horario por defecto nace sin franjas: cargalas con `PUT /courts/{id}/pricing`). Devuelve el MISMO `Court` de `GET /courts`. Nunca cámara ni ingest de streaming. Emite `occupancy.changed` si nació con franjas. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 5\",\n  \"sports\": [\n    \"PADEL\"\n  ],\n  \"isIndoor\": false,\n  \"surface\": \"Césped sintético\"\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts","host":["{{baseUrl}}"],"path":["courts"]},"description":"Alta de una cancha (o de un recurso de otra categoría, F6) con las mismas reglas que el panel: nace habilitada, con `pricePerHour` propio o el default del club y con las franjas del horario por defecto del club (si el club no tiene horario por defecto nace sin franjas: cargalas con `PUT /courts/{id}/pricing`). Devuelve el MISMO `Court` de `GET /courts`. Nunca cámara ni ingest de streaming. Emite `occupancy.changed` si nació con franjas. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 5\",\n  \"sports\": [\n    \"PADEL\"\n  ],\n  \"isIndoor\": false,\n  \"surface\": \"Césped sintético\"\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Una cancha (getCourt)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"El MISMO `Court` de `GET /courts` para una cancha (habilitada o no) más sus features. Es adonde apunta el `Location` de `POST /courts`. Scope `courts:read` sobre el club de la cancha.\n\nScope: `courts:read`."},"response":[{"name":"200 · La cancha.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"El MISMO `Court` de `GET /courts` para una cancha (habilitada o no) más sus features. Es adonde apunta el `Location` de `POST /courts`. Scope `courts:read` sobre el club de la cancha.\n\nScope: `courts:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"court\": {\n    \"id\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"name\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"sports\": [\n      \"PADEL\"\n    ],\n    \"enabled\": true,\n    \"isIndoor\": false,\n    \"pricing\": [\n      {\n        \"pricePerHour\": 1000,\n        \"price60\": null,\n        \"price90\": 1400,\n        \"price120\": null,\n        \"ranges\": [\n          {\n            \"start\": \"08:00\",\n            \"end\": \"23:00\"\n          }\n        ]\n      }\n    ]\n  },\n  \"features\": [\n    {\n      \"id\": \"feat-cancha-exterior\",\n      \"name\": \"Cancha Exterior\"\n    },\n    {\n      \"id\": \"feat-paredes-cristal\",\n      \"name\": \"Paredes de Cristal\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"El MISMO `Court` de `GET /courts` para una cancha (habilitada o no) más sus features. Es adonde apunta el `Location` de `POST /courts`. Scope `courts:read` sobre el club de la cancha.\n\nScope: `courts:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"El MISMO `Court` de `GET /courts` para una cancha (habilitada o no) más sus features. Es adonde apunta el `Location` de `POST /courts`. Scope `courts:read` sobre el club de la cancha.\n\nScope: `courts:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"El MISMO `Court` de `GET /courts` para una cancha (habilitada o no) más sus features. Es adonde apunta el `Location` de `POST /courts`. Scope `courts:read` sobre el club de la cancha.\n\nScope: `courts:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · COURT_NOT_FOUND","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"El MISMO `Court` de `GET /courts` para una cancha (habilitada o no) más sus features. Es adonde apunta el `Location` de `POST /courts`. Scope `courts:read` sobre el club de la cancha.\n\nScope: `courts:read`."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La cancha no existe o no es de este club.\",\n  \"code\": \"COURT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"El MISMO `Court` de `GET /courts` para una cancha (habilitada o no) más sus features. Es adonde apunta el `Location` de `POST /courts`. Scope `courts:read` sobre el club de la cancha.\n\nScope: `courts:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"El MISMO `Court` de `GET /courts` para una cancha (habilitada o no) más sus features. Es adonde apunta el `Location` de `POST /courts`. Scope `courts:read` sobre el club de la cancha.\n\nScope: `courts:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"El MISMO `Court` de `GET /courts` para una cancha (habilitada o no) más sus features. Es adonde apunta el `Location` de `POST /courts`. Scope `courts:read` sobre el club de la cancha.\n\nScope: `courts:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Editar / deshabilitar una cancha (updateCourt)","request":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"query":[{"key":"force","value":"true","description":"Con `enabled: false` y reservas vivas cuyo turno no terminó: cancelarlas (status CANCELLED, `cancel_reason = API`, partidos desligados —nunca cancelados—, aviso al titular real, evento `booking.cancelled` con `reason = court_disabled`). Un turno de hoy ya terminado o ya marcado (ATTENDED / NO_SHOW) nunca se toca. Sin `force` nunca se toca una reserva.","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo (≤ 140) que queda en el audit y en el aviso a los titulares.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Parcial. Nombre, deportes, superficie, techado, orden, precio/hora base, categoría (F6; `null` = sin categoría), `enabled` y `features` (reemplaza el set; `feat-cancha-interior` / `feat-cancha-exterior` derivan `isIndoor`, como en el panel). Deshabilitar es la baja lógica del panel: la cancha deja de venderse y se sigue listando con `enabled: false`; con reservas vivas (PENDING / CONFIRMED) cuyo turno todavía no terminó responde 409 COURT_HAS_FUTURE_BOOKINGS (`details.bookings`, `from`, `to`) salvo `?force=true`; los turnos de hoy ya terminados o marcados son historial y no cuentan. Las series de fijas quedan activas pero el cron no materializa ocurrencias sobre una cancha deshabilitada. Cambiar `enabled` emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 1 (cristal)\",\n  \"features\": [\n    \"feat-cancha-exterior\",\n    \"feat-paredes-cristal\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · La cancha actualizada.","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"query":[{"key":"force","value":"true","description":"Con `enabled: false` y reservas vivas cuyo turno no terminó: cancelarlas (status CANCELLED, `cancel_reason = API`, partidos desligados —nunca cancelados—, aviso al titular real, evento `booking.cancelled` con `reason = court_disabled`). Un turno de hoy ya terminado o ya marcado (ATTENDED / NO_SHOW) nunca se toca. Sin `force` nunca se toca una reserva.","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo (≤ 140) que queda en el audit y en el aviso a los titulares.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Parcial. Nombre, deportes, superficie, techado, orden, precio/hora base, categoría (F6; `null` = sin categoría), `enabled` y `features` (reemplaza el set; `feat-cancha-interior` / `feat-cancha-exterior` derivan `isIndoor`, como en el panel). Deshabilitar es la baja lógica del panel: la cancha deja de venderse y se sigue listando con `enabled: false`; con reservas vivas (PENDING / CONFIRMED) cuyo turno todavía no terminó responde 409 COURT_HAS_FUTURE_BOOKINGS (`details.bookings`, `from`, `to`) salvo `?force=true`; los turnos de hoy ya terminados o marcados son historial y no cuentan. Las series de fijas quedan activas pero el cron no materializa ocurrencias sobre una cancha deshabilitada. Cambiar `enabled` emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 1 (cristal)\",\n  \"features\": [\n    \"feat-cancha-exterior\",\n    \"feat-paredes-cristal\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"court\": {\n    \"id\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"name\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"sports\": [\n      \"PADEL\"\n    ],\n    \"enabled\": false,\n    \"isIndoor\": false,\n    \"pricing\": [\n      {\n        \"pricePerHour\": 1000,\n        \"price60\": null,\n        \"price90\": 1400,\n        \"price120\": null,\n        \"ranges\": [\n          {\n            \"start\": \"08:00\",\n            \"end\": \"23:00\"\n          }\n        ]\n      }\n    ]\n  },\n  \"features\": [\n    {\n      \"id\": \"feat-cancha-exterior\",\n      \"name\": \"Cancha Exterior\"\n    },\n    {\n      \"id\": \"feat-paredes-cristal\",\n      \"name\": \"Paredes de Cristal\"\n    }\n  ],\n  \"cancelledBookings\": 2\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CATEGORY_REQUIRED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"query":[{"key":"force","value":"true","description":"Con `enabled: false` y reservas vivas cuyo turno no terminó: cancelarlas (status CANCELLED, `cancel_reason = API`, partidos desligados —nunca cancelados—, aviso al titular real, evento `booking.cancelled` con `reason = court_disabled`). Un turno de hoy ya terminado o ya marcado (ATTENDED / NO_SHOW) nunca se toca. Sin `force` nunca se toca una reserva.","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo (≤ 140) que queda en el audit y en el aviso a los titulares.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Parcial. Nombre, deportes, superficie, techado, orden, precio/hora base, categoría (F6; `null` = sin categoría), `enabled` y `features` (reemplaza el set; `feat-cancha-interior` / `feat-cancha-exterior` derivan `isIndoor`, como en el panel). Deshabilitar es la baja lógica del panel: la cancha deja de venderse y se sigue listando con `enabled: false`; con reservas vivas (PENDING / CONFIRMED) cuyo turno todavía no terminó responde 409 COURT_HAS_FUTURE_BOOKINGS (`details.bookings`, `from`, `to`) salvo `?force=true`; los turnos de hoy ya terminados o marcados son historial y no cuentan. Las series de fijas quedan activas pero el cron no materializa ocurrencias sobre una cancha deshabilitada. Cambiar `enabled` emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 1 (cristal)\",\n  \"features\": [\n    \"feat-cancha-exterior\",\n    \"feat-paredes-cristal\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"query":[{"key":"force","value":"true","description":"Con `enabled: false` y reservas vivas cuyo turno no terminó: cancelarlas (status CANCELLED, `cancel_reason = API`, partidos desligados —nunca cancelados—, aviso al titular real, evento `booking.cancelled` con `reason = court_disabled`). Un turno de hoy ya terminado o ya marcado (ATTENDED / NO_SHOW) nunca se toca. Sin `force` nunca se toca una reserva.","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo (≤ 140) que queda en el audit y en el aviso a los titulares.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Parcial. Nombre, deportes, superficie, techado, orden, precio/hora base, categoría (F6; `null` = sin categoría), `enabled` y `features` (reemplaza el set; `feat-cancha-interior` / `feat-cancha-exterior` derivan `isIndoor`, como en el panel). Deshabilitar es la baja lógica del panel: la cancha deja de venderse y se sigue listando con `enabled: false`; con reservas vivas (PENDING / CONFIRMED) cuyo turno todavía no terminó responde 409 COURT_HAS_FUTURE_BOOKINGS (`details.bookings`, `from`, `to`) salvo `?force=true`; los turnos de hoy ya terminados o marcados son historial y no cuentan. Las series de fijas quedan activas pero el cron no materializa ocurrencias sobre una cancha deshabilitada. Cambiar `enabled` emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 1 (cristal)\",\n  \"features\": [\n    \"feat-cancha-exterior\",\n    \"feat-paredes-cristal\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"query":[{"key":"force","value":"true","description":"Con `enabled: false` y reservas vivas cuyo turno no terminó: cancelarlas (status CANCELLED, `cancel_reason = API`, partidos desligados —nunca cancelados—, aviso al titular real, evento `booking.cancelled` con `reason = court_disabled`). Un turno de hoy ya terminado o ya marcado (ATTENDED / NO_SHOW) nunca se toca. Sin `force` nunca se toca una reserva.","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo (≤ 140) que queda en el audit y en el aviso a los titulares.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Parcial. Nombre, deportes, superficie, techado, orden, precio/hora base, categoría (F6; `null` = sin categoría), `enabled` y `features` (reemplaza el set; `feat-cancha-interior` / `feat-cancha-exterior` derivan `isIndoor`, como en el panel). Deshabilitar es la baja lógica del panel: la cancha deja de venderse y se sigue listando con `enabled: false`; con reservas vivas (PENDING / CONFIRMED) cuyo turno todavía no terminó responde 409 COURT_HAS_FUTURE_BOOKINGS (`details.bookings`, `from`, `to`) salvo `?force=true`; los turnos de hoy ya terminados o marcados son historial y no cuentan. Las series de fijas quedan activas pero el cron no materializa ocurrencias sobre una cancha deshabilitada. Cambiar `enabled` emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 1 (cristal)\",\n  \"features\": [\n    \"feat-cancha-exterior\",\n    \"feat-paredes-cristal\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · COURT_NOT_FOUND / CATEGORY_NOT_FOUND / FEATURE_NOT_FOUND","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"query":[{"key":"force","value":"true","description":"Con `enabled: false` y reservas vivas cuyo turno no terminó: cancelarlas (status CANCELLED, `cancel_reason = API`, partidos desligados —nunca cancelados—, aviso al titular real, evento `booking.cancelled` con `reason = court_disabled`). Un turno de hoy ya terminado o ya marcado (ATTENDED / NO_SHOW) nunca se toca. Sin `force` nunca se toca una reserva.","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo (≤ 140) que queda en el audit y en el aviso a los titulares.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Parcial. Nombre, deportes, superficie, techado, orden, precio/hora base, categoría (F6; `null` = sin categoría), `enabled` y `features` (reemplaza el set; `feat-cancha-interior` / `feat-cancha-exterior` derivan `isIndoor`, como en el panel). Deshabilitar es la baja lógica del panel: la cancha deja de venderse y se sigue listando con `enabled: false`; con reservas vivas (PENDING / CONFIRMED) cuyo turno todavía no terminó responde 409 COURT_HAS_FUTURE_BOOKINGS (`details.bookings`, `from`, `to`) salvo `?force=true`; los turnos de hoy ya terminados o marcados son historial y no cuentan. Las series de fijas quedan activas pero el cron no materializa ocurrencias sobre una cancha deshabilitada. Cambiar `enabled` emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 1 (cristal)\",\n  \"features\": [\n    \"feat-cancha-exterior\",\n    \"feat-paredes-cristal\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La cancha no existe o no es de este club.\",\n  \"code\": \"COURT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · COURT_HAS_FUTURE_BOOKINGS / RESOURCE_KIND_CHANGE_NOT_ALLOWED / RESOURCE_NOT_COURT","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"query":[{"key":"force","value":"true","description":"Con `enabled: false` y reservas vivas cuyo turno no terminó: cancelarlas (status CANCELLED, `cancel_reason = API`, partidos desligados —nunca cancelados—, aviso al titular real, evento `booking.cancelled` con `reason = court_disabled`). Un turno de hoy ya terminado o ya marcado (ATTENDED / NO_SHOW) nunca se toca. Sin `force` nunca se toca una reserva.","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo (≤ 140) que queda en el audit y en el aviso a los titulares.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Parcial. Nombre, deportes, superficie, techado, orden, precio/hora base, categoría (F6; `null` = sin categoría), `enabled` y `features` (reemplaza el set; `feat-cancha-interior` / `feat-cancha-exterior` derivan `isIndoor`, como en el panel). Deshabilitar es la baja lógica del panel: la cancha deja de venderse y se sigue listando con `enabled: false`; con reservas vivas (PENDING / CONFIRMED) cuyo turno todavía no terminó responde 409 COURT_HAS_FUTURE_BOOKINGS (`details.bookings`, `from`, `to`) salvo `?force=true`; los turnos de hoy ya terminados o marcados son historial y no cuentan. Las series de fijas quedan activas pero el cron no materializa ocurrencias sobre una cancha deshabilitada. Cambiar `enabled` emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 1 (cristal)\",\n  \"features\": [\n    \"feat-cancha-exterior\",\n    \"feat-paredes-cristal\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La cancha tiene reservas futuras. Repetí con force=true para cancelarlas y deshabilitarla.\",\n  \"code\": \"COURT_HAS_FUTURE_BOOKINGS\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"query":[{"key":"force","value":"true","description":"Con `enabled: false` y reservas vivas cuyo turno no terminó: cancelarlas (status CANCELLED, `cancel_reason = API`, partidos desligados —nunca cancelados—, aviso al titular real, evento `booking.cancelled` con `reason = court_disabled`). Un turno de hoy ya terminado o ya marcado (ATTENDED / NO_SHOW) nunca se toca. Sin `force` nunca se toca una reserva.","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo (≤ 140) que queda en el audit y en el aviso a los titulares.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Parcial. Nombre, deportes, superficie, techado, orden, precio/hora base, categoría (F6; `null` = sin categoría), `enabled` y `features` (reemplaza el set; `feat-cancha-interior` / `feat-cancha-exterior` derivan `isIndoor`, como en el panel). Deshabilitar es la baja lógica del panel: la cancha deja de venderse y se sigue listando con `enabled: false`; con reservas vivas (PENDING / CONFIRMED) cuyo turno todavía no terminó responde 409 COURT_HAS_FUTURE_BOOKINGS (`details.bookings`, `from`, `to`) salvo `?force=true`; los turnos de hoy ya terminados o marcados son historial y no cuentan. Las series de fijas quedan activas pero el cron no materializa ocurrencias sobre una cancha deshabilitada. Cambiar `enabled` emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 1 (cristal)\",\n  \"features\": [\n    \"feat-cancha-exterior\",\n    \"feat-paredes-cristal\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"query":[{"key":"force","value":"true","description":"Con `enabled: false` y reservas vivas cuyo turno no terminó: cancelarlas (status CANCELLED, `cancel_reason = API`, partidos desligados —nunca cancelados—, aviso al titular real, evento `booking.cancelled` con `reason = court_disabled`). Un turno de hoy ya terminado o ya marcado (ATTENDED / NO_SHOW) nunca se toca. Sin `force` nunca se toca una reserva.","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo (≤ 140) que queda en el audit y en el aviso a los titulares.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Parcial. Nombre, deportes, superficie, techado, orden, precio/hora base, categoría (F6; `null` = sin categoría), `enabled` y `features` (reemplaza el set; `feat-cancha-interior` / `feat-cancha-exterior` derivan `isIndoor`, como en el panel). Deshabilitar es la baja lógica del panel: la cancha deja de venderse y se sigue listando con `enabled: false`; con reservas vivas (PENDING / CONFIRMED) cuyo turno todavía no terminó responde 409 COURT_HAS_FUTURE_BOOKINGS (`details.bookings`, `from`, `to`) salvo `?force=true`; los turnos de hoy ya terminados o marcados son historial y no cuentan. Las series de fijas quedan activas pero el cron no materializa ocurrencias sobre una cancha deshabilitada. Cambiar `enabled` emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 1 (cristal)\",\n  \"features\": [\n    \"feat-cancha-exterior\",\n    \"feat-paredes-cristal\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"query":[{"key":"force","value":"true","description":"Con `enabled: false` y reservas vivas cuyo turno no terminó: cancelarlas (status CANCELLED, `cancel_reason = API`, partidos desligados —nunca cancelados—, aviso al titular real, evento `booking.cancelled` con `reason = court_disabled`). Un turno de hoy ya terminado o ya marcado (ATTENDED / NO_SHOW) nunca se toca. Sin `force` nunca se toca una reserva.","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo (≤ 140) que queda en el audit y en el aviso a los titulares.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Parcial. Nombre, deportes, superficie, techado, orden, precio/hora base, categoría (F6; `null` = sin categoría), `enabled` y `features` (reemplaza el set; `feat-cancha-interior` / `feat-cancha-exterior` derivan `isIndoor`, como en el panel). Deshabilitar es la baja lógica del panel: la cancha deja de venderse y se sigue listando con `enabled: false`; con reservas vivas (PENDING / CONFIRMED) cuyo turno todavía no terminó responde 409 COURT_HAS_FUTURE_BOOKINGS (`details.bookings`, `from`, `to`) salvo `?force=true`; los turnos de hoy ya terminados o marcados son historial y no cuentan. Las series de fijas quedan activas pero el cron no materializa ocurrencias sobre una cancha deshabilitada. Cambiar `enabled` emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 1 (cristal)\",\n  \"features\": [\n    \"feat-cancha-exterior\",\n    \"feat-paredes-cristal\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"query":[{"key":"force","value":"true","description":"Con `enabled: false` y reservas vivas cuyo turno no terminó: cancelarlas (status CANCELLED, `cancel_reason = API`, partidos desligados —nunca cancelados—, aviso al titular real, evento `booking.cancelled` con `reason = court_disabled`). Un turno de hoy ya terminado o ya marcado (ATTENDED / NO_SHOW) nunca se toca. Sin `force` nunca se toca una reserva.","disabled":true},{"key":"reason","value":"el cliente canceló","description":"Motivo (≤ 140) que queda en el audit y en el aviso a los titulares.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Parcial. Nombre, deportes, superficie, techado, orden, precio/hora base, categoría (F6; `null` = sin categoría), `enabled` y `features` (reemplaza el set; `feat-cancha-interior` / `feat-cancha-exterior` derivan `isIndoor`, como en el panel). Deshabilitar es la baja lógica del panel: la cancha deja de venderse y se sigue listando con `enabled: false`; con reservas vivas (PENDING / CONFIRMED) cuyo turno todavía no terminó responde 409 COURT_HAS_FUTURE_BOOKINGS (`details.bookings`, `from`, `to`) salvo `?force=true`; los turnos de hoy ya terminados o marcados son historial y no cuentan. Las series de fijas quedan activas pero el cron no materializa ocurrencias sobre una cancha deshabilitada. Cambiar `enabled` emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Cancha 1 (cristal)\",\n  \"features\": [\n    \"feat-cancha-exterior\",\n    \"feat-paredes-cristal\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Borrar una cancha sin historial (deleteCourt)","request":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Borrado físico SÓLO de una cancha que nunca tuvo reservas, fijas, partidos (jugados o pedidos con `requestedCourtId`), partidos de torneo / americano, broadcasts ni mapeos externos (una creada por error). Con cualquiera de esos responde 409 COURT_HAS_BOOKINGS con el conteo por tabla (`details.bookings` / `recurring` / `matches` / `tournamentMatches` / `americanoMatches` / `broadcasts` / `externalMappings`): la baja es `PATCH { enabled: false }`. Los bloqueos de la cancha y sus huecos se borran con ella. Emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura."},"response":[{"name":"200 · Borrada.","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Borrado físico SÓLO de una cancha que nunca tuvo reservas, fijas, partidos (jugados o pedidos con `requestedCourtId`), partidos de torneo / americano, broadcasts ni mapeos externos (una creada por error). Con cualquiera de esos responde 409 COURT_HAS_BOOKINGS con el conteo por tabla (`details.bookings` / `recurring` / `matches` / `tournamentMatches` / `americanoMatches` / `broadcasts` / `externalMappings`): la baja es `PATCH { enabled: false }`. Los bloqueos de la cancha y sus huecos se borran con ella. Emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"deleted\": true\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Borrado físico SÓLO de una cancha que nunca tuvo reservas, fijas, partidos (jugados o pedidos con `requestedCourtId`), partidos de torneo / americano, broadcasts ni mapeos externos (una creada por error). Con cualquiera de esos responde 409 COURT_HAS_BOOKINGS con el conteo por tabla (`details.bookings` / `recurring` / `matches` / `tournamentMatches` / `americanoMatches` / `broadcasts` / `externalMappings`): la baja es `PATCH { enabled: false }`. Los bloqueos de la cancha y sus huecos se borran con ella. Emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Borrado físico SÓLO de una cancha que nunca tuvo reservas, fijas, partidos (jugados o pedidos con `requestedCourtId`), partidos de torneo / americano, broadcasts ni mapeos externos (una creada por error). Con cualquiera de esos responde 409 COURT_HAS_BOOKINGS con el conteo por tabla (`details.bookings` / `recurring` / `matches` / `tournamentMatches` / `americanoMatches` / `broadcasts` / `externalMappings`): la baja es `PATCH { enabled: false }`. Los bloqueos de la cancha y sus huecos se borran con ella. Emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Borrado físico SÓLO de una cancha que nunca tuvo reservas, fijas, partidos (jugados o pedidos con `requestedCourtId`), partidos de torneo / americano, broadcasts ni mapeos externos (una creada por error). Con cualquiera de esos responde 409 COURT_HAS_BOOKINGS con el conteo por tabla (`details.bookings` / `recurring` / `matches` / `tournamentMatches` / `americanoMatches` / `broadcasts` / `externalMappings`): la baja es `PATCH { enabled: false }`. Los bloqueos de la cancha y sus huecos se borran con ella. Emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · COURT_NOT_FOUND","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Borrado físico SÓLO de una cancha que nunca tuvo reservas, fijas, partidos (jugados o pedidos con `requestedCourtId`), partidos de torneo / americano, broadcasts ni mapeos externos (una creada por error). Con cualquiera de esos responde 409 COURT_HAS_BOOKINGS con el conteo por tabla (`details.bookings` / `recurring` / `matches` / `tournamentMatches` / `americanoMatches` / `broadcasts` / `externalMappings`): la baja es `PATCH { enabled: false }`. Los bloqueos de la cancha y sus huecos se borran con ella. Emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La cancha no existe o no es de este club.\",\n  \"code\": \"COURT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · COURT_HAS_BOOKINGS","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Borrado físico SÓLO de una cancha que nunca tuvo reservas, fijas, partidos (jugados o pedidos con `requestedCourtId`), partidos de torneo / americano, broadcasts ni mapeos externos (una creada por error). Con cualquiera de esos responde 409 COURT_HAS_BOOKINGS con el conteo por tabla (`details.bookings` / `recurring` / `matches` / `tournamentMatches` / `americanoMatches` / `broadcasts` / `externalMappings`): la baja es `PATCH { enabled: false }`. Los bloqueos de la cancha y sus huecos se borran con ella. Emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura."},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La cancha tiene reservas o partidos en su historial y no se puede borrar: deshabilitala con PATCH { enabled: false }.\",\n  \"code\": \"COURT_HAS_BOOKINGS\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Borrado físico SÓLO de una cancha que nunca tuvo reservas, fijas, partidos (jugados o pedidos con `requestedCourtId`), partidos de torneo / americano, broadcasts ni mapeos externos (una creada por error). Con cualquiera de esos responde 409 COURT_HAS_BOOKINGS con el conteo por tabla (`details.bookings` / `recurring` / `matches` / `tournamentMatches` / `americanoMatches` / `broadcasts` / `externalMappings`): la baja es `PATCH { enabled: false }`. Los bloqueos de la cancha y sus huecos se borran con ella. Emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Borrado físico SÓLO de una cancha que nunca tuvo reservas, fijas, partidos (jugados o pedidos con `requestedCourtId`), partidos de torneo / americano, broadcasts ni mapeos externos (una creada por error). Con cualquiera de esos responde 409 COURT_HAS_BOOKINGS con el conteo por tabla (`details.bookings` / `recurring` / `matches` / `tournamentMatches` / `americanoMatches` / `broadcasts` / `externalMappings`): la baja es `PATCH { enabled: false }`. Los bloqueos de la cancha y sus huecos se borran con ella. Emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id","host":["{{baseUrl}}"],"path":["courts",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Borrado físico SÓLO de una cancha que nunca tuvo reservas, fijas, partidos (jugados o pedidos con `requestedCourtId`), partidos de torneo / americano, broadcasts ni mapeos externos (una creada por error). Con cualquiera de esos responde 409 COURT_HAS_BOOKINGS con el conteo por tabla (`details.bookings` / `recurring` / `matches` / `tournamentMatches` / `americanoMatches` / `broadcasts` / `externalMappings`): la baja es `PATCH { enabled: false }`. Los bloqueos de la cancha y sus huecos se borran con ella. Emite `occupancy.changed`. Consume cuota de escritura.\n\nScope: `courts:write`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Tarifario de una cancha (getCourtPricing)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"La grilla de franjas vendibles por día de la semana con su precio/hora base y sus totales por duración (60 / 90 / 120), tal como la edita el panel en Horarios y precios. Las filas de 30' contiguas con la misma tarifa salen fundidas en una franja.\n\nScope: `pricing:read`."},"response":[{"name":"200 · El tarifario.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"La grilla de franjas vendibles por día de la semana con su precio/hora base y sus totales por duración (60 / 90 / 120), tal como la edita el panel en Horarios y precios. Las filas de 30' contiguas con la misma tarifa salen fundidas en una franja.\n\nScope: `pricing:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"pricePerHour\": 1000,\n  \"slots\": [\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"08:00\",\n      \"end\": \"18:00\",\n      \"pricePerHour\": 1000,\n      \"price60\": null,\n      \"price90\": 1400,\n      \"price120\": null\n    },\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"18:00\",\n      \"end\": \"24:00\",\n      \"pricePerHour\": 1300,\n      \"price60\": null,\n      \"price90\": 1800,\n      \"price120\": null\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"La grilla de franjas vendibles por día de la semana con su precio/hora base y sus totales por duración (60 / 90 / 120), tal como la edita el panel en Horarios y precios. Las filas de 30' contiguas con la misma tarifa salen fundidas en una franja.\n\nScope: `pricing:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"La grilla de franjas vendibles por día de la semana con su precio/hora base y sus totales por duración (60 / 90 / 120), tal como la edita el panel en Horarios y precios. Las filas de 30' contiguas con la misma tarifa salen fundidas en una franja.\n\nScope: `pricing:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"La grilla de franjas vendibles por día de la semana con su precio/hora base y sus totales por duración (60 / 90 / 120), tal como la edita el panel en Horarios y precios. Las filas de 30' contiguas con la misma tarifa salen fundidas en una franja.\n\nScope: `pricing:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · COURT_NOT_FOUND","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"La grilla de franjas vendibles por día de la semana con su precio/hora base y sus totales por duración (60 / 90 / 120), tal como la edita el panel en Horarios y precios. Las filas de 30' contiguas con la misma tarifa salen fundidas en una franja.\n\nScope: `pricing:read`."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La cancha no existe o no es de este club.\",\n  \"code\": \"COURT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"La grilla de franjas vendibles por día de la semana con su precio/hora base y sus totales por duración (60 / 90 / 120), tal como la edita el panel en Horarios y precios. Las filas de 30' contiguas con la misma tarifa salen fundidas en una franja.\n\nScope: `pricing:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"La grilla de franjas vendibles por día de la semana con su precio/hora base y sus totales por duración (60 / 90 / 120), tal como la edita el panel en Horarios y precios. Las filas de 30' contiguas con la misma tarifa salen fundidas en una franja.\n\nScope: `pricing:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"La grilla de franjas vendibles por día de la semana con su precio/hora base y sus totales por duración (60 / 90 / 120), tal como la edita el panel en Horarios y precios. Las filas de 30' contiguas con la misma tarifa salen fundidas en una franja.\n\nScope: `pricing:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Reemplazar el tarifario de una cancha (replaceCourtPricing)","request":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Reemplazo completo (espejo exacto de `PUT /club-owner/courts/:id/slots`): cada franja se materializa en filas de 30' con la misma tarifa; franjas fuera de la grilla de 30' o solapadas en un mismo día son 400 VALIDATION. Precio ausente o 0 = sin precio (nunca se persiste un 0). Devuelve la grilla resultante. Emite `occupancy.changed` sólo si cambiaron las franjas vendibles (no si cambió sólo el precio). Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"slots\": [\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"08:00\",\n      \"end\": \"18:00\",\n      \"pricePerHour\": 1000,\n      \"price60\": null,\n      \"price90\": 1400,\n      \"price120\": null\n    },\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"18:00\",\n      \"end\": \"24:00\",\n      \"pricePerHour\": 1300,\n      \"price60\": null,\n      \"price90\": 1800,\n      \"price120\": null\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · El tarifario resultante.","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Reemplazo completo (espejo exacto de `PUT /club-owner/courts/:id/slots`): cada franja se materializa en filas de 30' con la misma tarifa; franjas fuera de la grilla de 30' o solapadas en un mismo día son 400 VALIDATION. Precio ausente o 0 = sin precio (nunca se persiste un 0). Devuelve la grilla resultante. Emite `occupancy.changed` sólo si cambiaron las franjas vendibles (no si cambió sólo el precio). Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"slots\": [\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"08:00\",\n      \"end\": \"18:00\",\n      \"pricePerHour\": 1000,\n      \"price60\": null,\n      \"price90\": 1400,\n      \"price120\": null\n    },\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"18:00\",\n      \"end\": \"24:00\",\n      \"pricePerHour\": 1300,\n      \"price60\": null,\n      \"price90\": 1800,\n      \"price120\": null\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"pricePerHour\": 1000,\n  \"slots\": [\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"08:00\",\n      \"end\": \"18:00\",\n      \"pricePerHour\": 1000,\n      \"price60\": null,\n      \"price90\": 1400,\n      \"price120\": null\n    },\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"18:00\",\n      \"end\": \"24:00\",\n      \"pricePerHour\": 1300,\n      \"price60\": null,\n      \"price90\": 1800,\n      \"price120\": null\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Reemplazo completo (espejo exacto de `PUT /club-owner/courts/:id/slots`): cada franja se materializa en filas de 30' con la misma tarifa; franjas fuera de la grilla de 30' o solapadas en un mismo día son 400 VALIDATION. Precio ausente o 0 = sin precio (nunca se persiste un 0). Devuelve la grilla resultante. Emite `occupancy.changed` sólo si cambiaron las franjas vendibles (no si cambió sólo el precio). Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"slots\": [\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"08:00\",\n      \"end\": \"18:00\",\n      \"pricePerHour\": 1000,\n      \"price60\": null,\n      \"price90\": 1400,\n      \"price120\": null\n    },\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"18:00\",\n      \"end\": \"24:00\",\n      \"pricePerHour\": 1300,\n      \"price60\": null,\n      \"price90\": 1800,\n      \"price120\": null\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Reemplazo completo (espejo exacto de `PUT /club-owner/courts/:id/slots`): cada franja se materializa en filas de 30' con la misma tarifa; franjas fuera de la grilla de 30' o solapadas en un mismo día son 400 VALIDATION. Precio ausente o 0 = sin precio (nunca se persiste un 0). Devuelve la grilla resultante. Emite `occupancy.changed` sólo si cambiaron las franjas vendibles (no si cambió sólo el precio). Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"slots\": [\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"08:00\",\n      \"end\": \"18:00\",\n      \"pricePerHour\": 1000,\n      \"price60\": null,\n      \"price90\": 1400,\n      \"price120\": null\n    },\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"18:00\",\n      \"end\": \"24:00\",\n      \"pricePerHour\": 1300,\n      \"price60\": null,\n      \"price90\": 1800,\n      \"price120\": null\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Reemplazo completo (espejo exacto de `PUT /club-owner/courts/:id/slots`): cada franja se materializa en filas de 30' con la misma tarifa; franjas fuera de la grilla de 30' o solapadas en un mismo día son 400 VALIDATION. Precio ausente o 0 = sin precio (nunca se persiste un 0). Devuelve la grilla resultante. Emite `occupancy.changed` sólo si cambiaron las franjas vendibles (no si cambió sólo el precio). Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"slots\": [\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"08:00\",\n      \"end\": \"18:00\",\n      \"pricePerHour\": 1000,\n      \"price60\": null,\n      \"price90\": 1400,\n      \"price120\": null\n    },\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"18:00\",\n      \"end\": \"24:00\",\n      \"pricePerHour\": 1300,\n      \"price60\": null,\n      \"price90\": 1800,\n      \"price120\": null\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · COURT_NOT_FOUND","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Reemplazo completo (espejo exacto de `PUT /club-owner/courts/:id/slots`): cada franja se materializa en filas de 30' con la misma tarifa; franjas fuera de la grilla de 30' o solapadas en un mismo día son 400 VALIDATION. Precio ausente o 0 = sin precio (nunca se persiste un 0). Devuelve la grilla resultante. Emite `occupancy.changed` sólo si cambiaron las franjas vendibles (no si cambió sólo el precio). Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"slots\": [\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"08:00\",\n      \"end\": \"18:00\",\n      \"pricePerHour\": 1000,\n      \"price60\": null,\n      \"price90\": 1400,\n      \"price120\": null\n    },\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"18:00\",\n      \"end\": \"24:00\",\n      \"pricePerHour\": 1300,\n      \"price60\": null,\n      \"price90\": 1800,\n      \"price120\": null\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La cancha no existe o no es de este club.\",\n  \"code\": \"COURT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Reemplazo completo (espejo exacto de `PUT /club-owner/courts/:id/slots`): cada franja se materializa en filas de 30' con la misma tarifa; franjas fuera de la grilla de 30' o solapadas en un mismo día son 400 VALIDATION. Precio ausente o 0 = sin precio (nunca se persiste un 0). Devuelve la grilla resultante. Emite `occupancy.changed` sólo si cambiaron las franjas vendibles (no si cambió sólo el precio). Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"slots\": [\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"08:00\",\n      \"end\": \"18:00\",\n      \"pricePerHour\": 1000,\n      \"price60\": null,\n      \"price90\": 1400,\n      \"price120\": null\n    },\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"18:00\",\n      \"end\": \"24:00\",\n      \"pricePerHour\": 1300,\n      \"price60\": null,\n      \"price90\": 1800,\n      \"price120\": null\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Reemplazo completo (espejo exacto de `PUT /club-owner/courts/:id/slots`): cada franja se materializa en filas de 30' con la misma tarifa; franjas fuera de la grilla de 30' o solapadas en un mismo día son 400 VALIDATION. Precio ausente o 0 = sin precio (nunca se persiste un 0). Devuelve la grilla resultante. Emite `occupancy.changed` sólo si cambiaron las franjas vendibles (no si cambió sólo el precio). Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"slots\": [\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"08:00\",\n      \"end\": \"18:00\",\n      \"pricePerHour\": 1000,\n      \"price60\": null,\n      \"price90\": 1400,\n      \"price120\": null\n    },\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"18:00\",\n      \"end\": \"24:00\",\n      \"pricePerHour\": 1300,\n      \"price60\": null,\n      \"price90\": 1800,\n      \"price120\": null\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Reemplazo completo (espejo exacto de `PUT /club-owner/courts/:id/slots`): cada franja se materializa en filas de 30' con la misma tarifa; franjas fuera de la grilla de 30' o solapadas en un mismo día son 400 VALIDATION. Precio ausente o 0 = sin precio (nunca se persiste un 0). Devuelve la grilla resultante. Emite `occupancy.changed` sólo si cambiaron las franjas vendibles (no si cambió sólo el precio). Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"slots\": [\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"08:00\",\n      \"end\": \"18:00\",\n      \"pricePerHour\": 1000,\n      \"price60\": null,\n      \"price90\": 1400,\n      \"price120\": null\n    },\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"18:00\",\n      \"end\": \"24:00\",\n      \"pricePerHour\": 1300,\n      \"price60\": null,\n      \"price90\": 1800,\n      \"price120\": null\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courts/:id/pricing","host":["{{baseUrl}}"],"path":["courts",":id","pricing"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la cancha (`GET /courts`)."}]},"description":"Reemplazo completo (espejo exacto de `PUT /club-owner/courts/:id/slots`): cada franja se materializa en filas de 30' con la misma tarifa; franjas fuera de la grilla de 30' o solapadas en un mismo día son 400 VALIDATION. Precio ausente o 0 = sin precio (nunca se persiste un 0). Devuelve la grilla resultante. Emite `occupancy.changed` sólo si cambiaron las franjas vendibles (no si cambió sólo el precio). Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"slots\": [\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"08:00\",\n      \"end\": \"18:00\",\n      \"pricePerHour\": 1000,\n      \"price60\": null,\n      \"price90\": 1400,\n      \"price120\": null\n    },\n    {\n      \"dayOfWeek\": 1,\n      \"start\": \"18:00\",\n      \"end\": \"24:00\",\n      \"pricePerHour\": 1300,\n      \"price60\": null,\n      \"price90\": 1800,\n      \"price120\": null\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Horario semanal del club (getClubHours)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"`club_hours`: el techo duro de lo vendible por día (`/availability` y las altas no venden fuera de él). Un día ausente está cerrado; `[]` = sin horario cargado (mandan las franjas de cada cancha). Es lo mismo que `clubs[].hours` de `/me`.\n\nScope: `hours:read`."},"response":[{"name":"200 · El horario.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"`club_hours`: el techo duro de lo vendible por día (`/availability` y las altas no venden fuera de él). Un día ausente está cerrado; `[]` = sin horario cargado (mandan las franjas de cada cancha). Es lo mismo que `clubs[].hours` de `/me`.\n\nScope: `hours:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n  \"hours\": [\n    {\n      \"dayOfWeek\": 1,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 2,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 3,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 4,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 5,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 6,\n      \"open\": \"09:00\",\n      \"close\": \"22:00\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"`club_hours`: el techo duro de lo vendible por día (`/availability` y las altas no venden fuera de él). Un día ausente está cerrado; `[]` = sin horario cargado (mandan las franjas de cada cancha). Es lo mismo que `clubs[].hours` de `/me`.\n\nScope: `hours:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"`club_hours`: el techo duro de lo vendible por día (`/availability` y las altas no venden fuera de él). Un día ausente está cerrado; `[]` = sin horario cargado (mandan las franjas de cada cancha). Es lo mismo que `clubs[].hours` de `/me`.\n\nScope: `hours:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"`club_hours`: el techo duro de lo vendible por día (`/availability` y las altas no venden fuera de él). Un día ausente está cerrado; `[]` = sin horario cargado (mandan las franjas de cada cancha). Es lo mismo que `clubs[].hours` de `/me`.\n\nScope: `hours:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"`club_hours`: el techo duro de lo vendible por día (`/availability` y las altas no venden fuera de él). Un día ausente está cerrado; `[]` = sin horario cargado (mandan las franjas de cada cancha). Es lo mismo que `clubs[].hours` de `/me`.\n\nScope: `hours:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"`club_hours`: el techo duro de lo vendible por día (`/availability` y las altas no venden fuera de él). Un día ausente está cerrado; `[]` = sin horario cargado (mandan las franjas de cada cancha). Es lo mismo que `clubs[].hours` de `/me`.\n\nScope: `hours:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"`club_hours`: el techo duro de lo vendible por día (`/availability` y las altas no venden fuera de él). Un día ausente está cerrado; `[]` = sin horario cargado (mandan las franjas de cada cancha). Es lo mismo que `clubs[].hours` de `/me`.\n\nScope: `hours:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Reemplazar el horario semanal del club (replaceClubHours)","request":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"]},"description":"Reemplazo completo de `club_hours`. Los días que no mandás quedan CERRADOS (con horario cargado nada se vende ese día); `hours: []` borra el horario. `24:00` vale como cierre. No toca las franjas de las canchas: si el horario nuevo es más chico, las franjas fuera de él quedan invendibles hasta que las achiques con `PUT /courts/{id}/pricing`. Emite `occupancy.changed` del club si cambió. Consume cuota de escritura.\n\nScope: `hours:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"hours\": [\n    {\n      \"dayOfWeek\": 1,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 2,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 3,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 4,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 5,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 6,\n      \"open\": \"09:00\",\n      \"close\": \"22:00\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · El horario resultante.","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"]},"description":"Reemplazo completo de `club_hours`. Los días que no mandás quedan CERRADOS (con horario cargado nada se vende ese día); `hours: []` borra el horario. `24:00` vale como cierre. No toca las franjas de las canchas: si el horario nuevo es más chico, las franjas fuera de él quedan invendibles hasta que las achiques con `PUT /courts/{id}/pricing`. Emite `occupancy.changed` del club si cambió. Consume cuota de escritura.\n\nScope: `hours:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"hours\": [\n    {\n      \"dayOfWeek\": 1,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 2,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 3,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 4,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 5,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 6,\n      \"open\": \"09:00\",\n      \"close\": \"22:00\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n  \"hours\": [\n    {\n      \"dayOfWeek\": 1,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 2,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 3,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 4,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 5,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 6,\n      \"open\": \"09:00\",\n      \"close\": \"22:00\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"]},"description":"Reemplazo completo de `club_hours`. Los días que no mandás quedan CERRADOS (con horario cargado nada se vende ese día); `hours: []` borra el horario. `24:00` vale como cierre. No toca las franjas de las canchas: si el horario nuevo es más chico, las franjas fuera de él quedan invendibles hasta que las achiques con `PUT /courts/{id}/pricing`. Emite `occupancy.changed` del club si cambió. Consume cuota de escritura.\n\nScope: `hours:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"hours\": [\n    {\n      \"dayOfWeek\": 1,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 2,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 3,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 4,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 5,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 6,\n      \"open\": \"09:00\",\n      \"close\": \"22:00\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"]},"description":"Reemplazo completo de `club_hours`. Los días que no mandás quedan CERRADOS (con horario cargado nada se vende ese día); `hours: []` borra el horario. `24:00` vale como cierre. No toca las franjas de las canchas: si el horario nuevo es más chico, las franjas fuera de él quedan invendibles hasta que las achiques con `PUT /courts/{id}/pricing`. Emite `occupancy.changed` del club si cambió. Consume cuota de escritura.\n\nScope: `hours:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"hours\": [\n    {\n      \"dayOfWeek\": 1,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 2,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 3,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 4,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 5,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 6,\n      \"open\": \"09:00\",\n      \"close\": \"22:00\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"]},"description":"Reemplazo completo de `club_hours`. Los días que no mandás quedan CERRADOS (con horario cargado nada se vende ese día); `hours: []` borra el horario. `24:00` vale como cierre. No toca las franjas de las canchas: si el horario nuevo es más chico, las franjas fuera de él quedan invendibles hasta que las achiques con `PUT /courts/{id}/pricing`. Emite `occupancy.changed` del club si cambió. Consume cuota de escritura.\n\nScope: `hours:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"hours\": [\n    {\n      \"dayOfWeek\": 1,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 2,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 3,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 4,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 5,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 6,\n      \"open\": \"09:00\",\n      \"close\": \"22:00\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"]},"description":"Reemplazo completo de `club_hours`. Los días que no mandás quedan CERRADOS (con horario cargado nada se vende ese día); `hours: []` borra el horario. `24:00` vale como cierre. No toca las franjas de las canchas: si el horario nuevo es más chico, las franjas fuera de él quedan invendibles hasta que las achiques con `PUT /courts/{id}/pricing`. Emite `occupancy.changed` del club si cambió. Consume cuota de escritura.\n\nScope: `hours:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"hours\": [\n    {\n      \"dayOfWeek\": 1,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 2,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 3,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 4,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 5,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 6,\n      \"open\": \"09:00\",\n      \"close\": \"22:00\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"]},"description":"Reemplazo completo de `club_hours`. Los días que no mandás quedan CERRADOS (con horario cargado nada se vende ese día); `hours: []` borra el horario. `24:00` vale como cierre. No toca las franjas de las canchas: si el horario nuevo es más chico, las franjas fuera de él quedan invendibles hasta que las achiques con `PUT /courts/{id}/pricing`. Emite `occupancy.changed` del club si cambió. Consume cuota de escritura.\n\nScope: `hours:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"hours\": [\n    {\n      \"dayOfWeek\": 1,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 2,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 3,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 4,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 5,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 6,\n      \"open\": \"09:00\",\n      \"close\": \"22:00\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"]},"description":"Reemplazo completo de `club_hours`. Los días que no mandás quedan CERRADOS (con horario cargado nada se vende ese día); `hours: []` borra el horario. `24:00` vale como cierre. No toca las franjas de las canchas: si el horario nuevo es más chico, las franjas fuera de él quedan invendibles hasta que las achiques con `PUT /courts/{id}/pricing`. Emite `occupancy.changed` del club si cambió. Consume cuota de escritura.\n\nScope: `hours:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"hours\": [\n    {\n      \"dayOfWeek\": 1,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 2,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 3,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 4,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 5,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 6,\n      \"open\": \"09:00\",\n      \"close\": \"22:00\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hours","host":["{{baseUrl}}"],"path":["hours"]},"description":"Reemplazo completo de `club_hours`. Los días que no mandás quedan CERRADOS (con horario cargado nada se vende ese día); `hours: []` borra el horario. `24:00` vale como cierre. No toca las franjas de las canchas: si el horario nuevo es más chico, las franjas fuera de él quedan invendibles hasta que las achiques con `PUT /courts/{id}/pricing`. Emite `occupancy.changed` del club si cambió. Consume cuota de escritura.\n\nScope: `hours:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"hours\": [\n    {\n      \"dayOfWeek\": 1,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 2,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 3,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 4,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 5,\n      \"open\": \"08:00\",\n      \"close\": \"24:00\"\n    },\n    {\n      \"dayOfWeek\": 6,\n      \"open\": \"09:00\",\n      \"close\": \"22:00\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Defaults del club (precio, horario, intervalo) (getPricingDefaults)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los tres defaults del club que heredan las canchas nuevas y con los que el panel materializa las franjas: precio/hora, apertura / cierre e intervalo.\n\nScope: `pricing:read`."},"response":[{"name":"200 · Los defaults.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los tres defaults del club que heredan las canchas nuevas y con los que el panel materializa las franjas: precio/hora, apertura / cierre e intervalo.\n\nScope: `pricing:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n  \"defaultPricePerHour\": 1000,\n  \"defaultOpen\": \"08:00\",\n  \"defaultClose\": \"24:00\",\n  \"slotIntervalMinutes\": 30\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los tres defaults del club que heredan las canchas nuevas y con los que el panel materializa las franjas: precio/hora, apertura / cierre e intervalo.\n\nScope: `pricing:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los tres defaults del club que heredan las canchas nuevas y con los que el panel materializa las franjas: precio/hora, apertura / cierre e intervalo.\n\nScope: `pricing:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los tres defaults del club que heredan las canchas nuevas y con los que el panel materializa las franjas: precio/hora, apertura / cierre e intervalo.\n\nScope: `pricing:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los tres defaults del club que heredan las canchas nuevas y con los que el panel materializa las franjas: precio/hora, apertura / cierre e intervalo.\n\nScope: `pricing:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los tres defaults del club que heredan las canchas nuevas y con los que el panel materializa las franjas: precio/hora, apertura / cierre e intervalo.\n\nScope: `pricing:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los tres defaults del club que heredan las canchas nuevas y con los que el panel materializa las franjas: precio/hora, apertura / cierre e intervalo.\n\nScope: `pricing:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Cambiar los defaults del club (updatePricingDefaults)","request":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"]},"description":"Misma semántica que el PATCH del club en el panel: si cambia el horario o el intervalo se REGENERAN las franjas de TODAS las canchas del club (cada hora conserva la tarifa que tenía; las horas nuevas toman el precio resuelto; las que quedan fuera se pierden); si cambia sólo el precio, pisa `pricePerHour` de todas las canchas y el base de sus franjas sin tocar los totales por duración (`durationPriceOverrides` dice cuántas franjas siguen cobrando por duración). Emite `occupancy.changed` del club si regeneró. Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"defaultPricePerHour\": 1100,\n  \"defaultOpen\": \"08:00\",\n  \"defaultClose\": \"24:00\",\n  \"slotIntervalMinutes\": 30\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · Los defaults resultantes y qué se regeneró.","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"]},"description":"Misma semántica que el PATCH del club en el panel: si cambia el horario o el intervalo se REGENERAN las franjas de TODAS las canchas del club (cada hora conserva la tarifa que tenía; las horas nuevas toman el precio resuelto; las que quedan fuera se pierden); si cambia sólo el precio, pisa `pricePerHour` de todas las canchas y el base de sus franjas sin tocar los totales por duración (`durationPriceOverrides` dice cuántas franjas siguen cobrando por duración). Emite `occupancy.changed` del club si regeneró. Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"defaultPricePerHour\": 1100,\n  \"defaultOpen\": \"08:00\",\n  \"defaultClose\": \"24:00\",\n  \"slotIntervalMinutes\": 30\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n  \"defaultPricePerHour\": 1000,\n  \"defaultOpen\": \"08:00\",\n  \"defaultClose\": \"24:00\",\n  \"slotIntervalMinutes\": 30,\n  \"regeneratedCourts\": 4,\n  \"durationPriceOverrides\": 12\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"]},"description":"Misma semántica que el PATCH del club en el panel: si cambia el horario o el intervalo se REGENERAN las franjas de TODAS las canchas del club (cada hora conserva la tarifa que tenía; las horas nuevas toman el precio resuelto; las que quedan fuera se pierden); si cambia sólo el precio, pisa `pricePerHour` de todas las canchas y el base de sus franjas sin tocar los totales por duración (`durationPriceOverrides` dice cuántas franjas siguen cobrando por duración). Emite `occupancy.changed` del club si regeneró. Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"defaultPricePerHour\": 1100,\n  \"defaultOpen\": \"08:00\",\n  \"defaultClose\": \"24:00\",\n  \"slotIntervalMinutes\": 30\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"]},"description":"Misma semántica que el PATCH del club en el panel: si cambia el horario o el intervalo se REGENERAN las franjas de TODAS las canchas del club (cada hora conserva la tarifa que tenía; las horas nuevas toman el precio resuelto; las que quedan fuera se pierden); si cambia sólo el precio, pisa `pricePerHour` de todas las canchas y el base de sus franjas sin tocar los totales por duración (`durationPriceOverrides` dice cuántas franjas siguen cobrando por duración). Emite `occupancy.changed` del club si regeneró. Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"defaultPricePerHour\": 1100,\n  \"defaultOpen\": \"08:00\",\n  \"defaultClose\": \"24:00\",\n  \"slotIntervalMinutes\": 30\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"]},"description":"Misma semántica que el PATCH del club en el panel: si cambia el horario o el intervalo se REGENERAN las franjas de TODAS las canchas del club (cada hora conserva la tarifa que tenía; las horas nuevas toman el precio resuelto; las que quedan fuera se pierden); si cambia sólo el precio, pisa `pricePerHour` de todas las canchas y el base de sus franjas sin tocar los totales por duración (`durationPriceOverrides` dice cuántas franjas siguen cobrando por duración). Emite `occupancy.changed` del club si regeneró. Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"defaultPricePerHour\": 1100,\n  \"defaultOpen\": \"08:00\",\n  \"defaultClose\": \"24:00\",\n  \"slotIntervalMinutes\": 30\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"]},"description":"Misma semántica que el PATCH del club en el panel: si cambia el horario o el intervalo se REGENERAN las franjas de TODAS las canchas del club (cada hora conserva la tarifa que tenía; las horas nuevas toman el precio resuelto; las que quedan fuera se pierden); si cambia sólo el precio, pisa `pricePerHour` de todas las canchas y el base de sus franjas sin tocar los totales por duración (`durationPriceOverrides` dice cuántas franjas siguen cobrando por duración). Emite `occupancy.changed` del club si regeneró. Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"defaultPricePerHour\": 1100,\n  \"defaultOpen\": \"08:00\",\n  \"defaultClose\": \"24:00\",\n  \"slotIntervalMinutes\": 30\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"]},"description":"Misma semántica que el PATCH del club en el panel: si cambia el horario o el intervalo se REGENERAN las franjas de TODAS las canchas del club (cada hora conserva la tarifa que tenía; las horas nuevas toman el precio resuelto; las que quedan fuera se pierden); si cambia sólo el precio, pisa `pricePerHour` de todas las canchas y el base de sus franjas sin tocar los totales por duración (`durationPriceOverrides` dice cuántas franjas siguen cobrando por duración). Emite `occupancy.changed` del club si regeneró. Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"defaultPricePerHour\": 1100,\n  \"defaultOpen\": \"08:00\",\n  \"defaultClose\": \"24:00\",\n  \"slotIntervalMinutes\": 30\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"]},"description":"Misma semántica que el PATCH del club en el panel: si cambia el horario o el intervalo se REGENERAN las franjas de TODAS las canchas del club (cada hora conserva la tarifa que tenía; las horas nuevas toman el precio resuelto; las que quedan fuera se pierden); si cambia sólo el precio, pisa `pricePerHour` de todas las canchas y el base de sus franjas sin tocar los totales por duración (`durationPriceOverrides` dice cuántas franjas siguen cobrando por duración). Emite `occupancy.changed` del club si regeneró. Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"defaultPricePerHour\": 1100,\n  \"defaultOpen\": \"08:00\",\n  \"defaultClose\": \"24:00\",\n  \"slotIntervalMinutes\": 30\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/pricing/defaults","host":["{{baseUrl}}"],"path":["pricing","defaults"]},"description":"Misma semántica que el PATCH del club en el panel: si cambia el horario o el intervalo se REGENERAN las franjas de TODAS las canchas del club (cada hora conserva la tarifa que tenía; las horas nuevas toman el precio resuelto; las que quedan fuera se pierden); si cambia sólo el precio, pisa `pricePerHour` de todas las canchas y el base de sus franjas sin tocar los totales por duración (`durationPriceOverrides` dice cuántas franjas siguen cobrando por duración). Emite `occupancy.changed` del club si regeneró. Consume cuota de escritura.\n\nScope: `pricing:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"defaultPricePerHour\": 1100,\n  \"defaultOpen\": \"08:00\",\n  \"defaultClose\": \"24:00\",\n  \"slotIntervalMinutes\": 30\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]}]},{"name":"Bloqueos, fijas y asistencia","description":"Bloqueos de cancha, series de reservas fijas y pasar lista, con el emisor único de eventos.","item":[{"name":"Listar bloqueos (listBlocks)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks?from=2026-09-15&to=2026-09-30","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los bloqueos de esta cancha.","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango a consultar (se listan los bloqueos que lo solapan).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día del rango (inclusive); como mucho 366 días.","disabled":false}]},"description":"Bloqueos del club que solapan `[from, to]`, cada uno con los huecos que lo perforan. Todos los orígenes (panel y API): un bloqueo es del club, no de quien lo creó. Sin datos de personas.\n\nScope: `blocks:read`."},"response":[{"name":"200 · Bloqueos en el rango.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks?from=2026-09-15&to=2026-09-30","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los bloqueos de esta cancha.","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango a consultar (se listan los bloqueos que lo solapan).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día del rango (inclusive); como mucho 366 días.","disabled":false}]},"description":"Bloqueos del club que solapan `[from, to]`, cada uno con los huecos que lo perforan. Todos los orígenes (panel y API): un bloqueo es del club, no de quien lo creó. Sin datos de personas.\n\nScope: `blocks:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"blocks\": [\n    {\n      \"id\": \"3f2a1b0c-9d8e-4f7a-b6c5-d4e3f2a1b0c9\",\n      \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n      \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n      \"courtName\": \"Cancha 1\",\n      \"from\": \"2026-09-20\",\n      \"to\": \"2026-09-22\",\n      \"startTime\": \"08:00\",\n      \"endTime\": \"12:00\",\n      \"reason\": \"Mantenimiento del césped\",\n      \"holes\": [\n        {\n          \"id\": \"7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d\",\n          \"date\": \"2026-09-21\",\n          \"startTime\": \"10:00\",\n          \"endTime\": \"11:00\"\n        }\n      ],\n      \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks?from=2026-09-15&to=2026-09-30","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los bloqueos de esta cancha.","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango a consultar (se listan los bloqueos que lo solapan).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día del rango (inclusive); como mucho 366 días.","disabled":false}]},"description":"Bloqueos del club que solapan `[from, to]`, cada uno con los huecos que lo perforan. Todos los orígenes (panel y API): un bloqueo es del club, no de quien lo creó. Sin datos de personas.\n\nScope: `blocks:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks?from=2026-09-15&to=2026-09-30","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los bloqueos de esta cancha.","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango a consultar (se listan los bloqueos que lo solapan).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día del rango (inclusive); como mucho 366 días.","disabled":false}]},"description":"Bloqueos del club que solapan `[from, to]`, cada uno con los huecos que lo perforan. Todos los orígenes (panel y API): un bloqueo es del club, no de quien lo creó. Sin datos de personas.\n\nScope: `blocks:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks?from=2026-09-15&to=2026-09-30","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los bloqueos de esta cancha.","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango a consultar (se listan los bloqueos que lo solapan).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día del rango (inclusive); como mucho 366 días.","disabled":false}]},"description":"Bloqueos del club que solapan `[from, to]`, cada uno con los huecos que lo perforan. Todos los orígenes (panel y API): un bloqueo es del club, no de quien lo creó. Sin datos de personas.\n\nScope: `blocks:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks?from=2026-09-15&to=2026-09-30","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los bloqueos de esta cancha.","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango a consultar (se listan los bloqueos que lo solapan).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día del rango (inclusive); como mucho 366 días.","disabled":false}]},"description":"Bloqueos del club que solapan `[from, to]`, cada uno con los huecos que lo perforan. Todos los orígenes (panel y API): un bloqueo es del club, no de quien lo creó. Sin datos de personas.\n\nScope: `blocks:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks?from=2026-09-15&to=2026-09-30","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los bloqueos de esta cancha.","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango a consultar (se listan los bloqueos que lo solapan).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día del rango (inclusive); como mucho 366 días.","disabled":false}]},"description":"Bloqueos del club que solapan `[from, to]`, cada uno con los huecos que lo perforan. Todos los orígenes (panel y API): un bloqueo es del club, no de quien lo creó. Sin datos de personas.\n\nScope: `blocks:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks?from=2026-09-15&to=2026-09-30","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los bloqueos de esta cancha.","disabled":true},{"key":"from","value":"2026-09-15","description":"Primer día del rango a consultar (se listan los bloqueos que lo solapan).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día del rango (inclusive); como mucho 366 días.","disabled":false}]},"description":"Bloqueos del club que solapan `[from, to]`, cada uno con los huecos que lo perforan. Todos los orígenes (panel y API): un bloqueo es del club, no de quien lo creó. Sin datos de personas.\n\nScope: `blocks:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Bloquear una cancha (o todo el club) (createBlock)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"force","value":"true","description":"`true` cancela las reservas vivas que el bloqueo pisa (por el emisor único, reason `court_block`, partidos desligados) en vez de responder 409 BLOCK_CONFLICTS_WITH_BOOKINGS. Las de torneo nunca se cancelan desde acá.","disabled":true}]},"description":"Crea un bloqueo por cancha (`courtId: null` = todas las habilitadas del club) que ocupa `[startTime, endTime]` en cada día de `[from, to]` (sin horas: el día entero). Si pisa reservas vivas (PENDING / CONFIRMED de hoy en adelante, sin las de hoy que ya terminaron: ésas se pasan lista, no se cancelan) responde 409 con la lista anónima; con `?force=true` las cancela (`cancel_reason = API`, evento `booking.cancelled` con reason `court_block`, partidos desligados, push al titular real, audit por reserva). Emite `occupancy.changed` por el rango. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"from\": \"2026-09-20\",\n  \"to\": \"2026-09-22\",\n  \"startTime\": \"08:00\",\n  \"endTime\": \"12:00\",\n  \"reason\": \"Mantenimiento del césped\"\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"201 · Bloqueo(s) creado(s).","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"force","value":"true","description":"`true` cancela las reservas vivas que el bloqueo pisa (por el emisor único, reason `court_block`, partidos desligados) en vez de responder 409 BLOCK_CONFLICTS_WITH_BOOKINGS. Las de torneo nunca se cancelan desde acá.","disabled":true}]},"description":"Crea un bloqueo por cancha (`courtId: null` = todas las habilitadas del club) que ocupa `[startTime, endTime]` en cada día de `[from, to]` (sin horas: el día entero). Si pisa reservas vivas (PENDING / CONFIRMED de hoy en adelante, sin las de hoy que ya terminaron: ésas se pasan lista, no se cancelan) responde 409 con la lista anónima; con `?force=true` las cancela (`cancel_reason = API`, evento `booking.cancelled` con reason `court_block`, partidos desligados, push al titular real, audit por reserva). Emite `occupancy.changed` por el rango. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"from\": \"2026-09-20\",\n  \"to\": \"2026-09-22\",\n  \"startTime\": \"08:00\",\n  \"endTime\": \"12:00\",\n  \"reason\": \"Mantenimiento del césped\"\n}","options":{"raw":{"language":"json"}}}},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"blocks\": [\n    {\n      \"id\": \"3f2a1b0c-9d8e-4f7a-b6c5-d4e3f2a1b0c9\",\n      \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n      \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n      \"courtName\": \"Cancha 1\",\n      \"from\": \"2026-09-20\",\n      \"to\": \"2026-09-22\",\n      \"startTime\": \"08:00\",\n      \"endTime\": \"12:00\",\n      \"reason\": \"Mantenimiento del césped\",\n      \"holes\": [\n        {\n          \"id\": \"7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d\",\n          \"date\": \"2026-09-21\",\n          \"startTime\": \"10:00\",\n          \"endTime\": \"11:00\"\n        }\n      ],\n      \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n    }\n  ],\n  \"cancelledBookings\": 0,\n  \"detachedMatches\": 0\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"force","value":"true","description":"`true` cancela las reservas vivas que el bloqueo pisa (por el emisor único, reason `court_block`, partidos desligados) en vez de responder 409 BLOCK_CONFLICTS_WITH_BOOKINGS. Las de torneo nunca se cancelan desde acá.","disabled":true}]},"description":"Crea un bloqueo por cancha (`courtId: null` = todas las habilitadas del club) que ocupa `[startTime, endTime]` en cada día de `[from, to]` (sin horas: el día entero). Si pisa reservas vivas (PENDING / CONFIRMED de hoy en adelante, sin las de hoy que ya terminaron: ésas se pasan lista, no se cancelan) responde 409 con la lista anónima; con `?force=true` las cancela (`cancel_reason = API`, evento `booking.cancelled` con reason `court_block`, partidos desligados, push al titular real, audit por reserva). Emite `occupancy.changed` por el rango. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"from\": \"2026-09-20\",\n  \"to\": \"2026-09-22\",\n  \"startTime\": \"08:00\",\n  \"endTime\": \"12:00\",\n  \"reason\": \"Mantenimiento del césped\"\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"force","value":"true","description":"`true` cancela las reservas vivas que el bloqueo pisa (por el emisor único, reason `court_block`, partidos desligados) en vez de responder 409 BLOCK_CONFLICTS_WITH_BOOKINGS. Las de torneo nunca se cancelan desde acá.","disabled":true}]},"description":"Crea un bloqueo por cancha (`courtId: null` = todas las habilitadas del club) que ocupa `[startTime, endTime]` en cada día de `[from, to]` (sin horas: el día entero). Si pisa reservas vivas (PENDING / CONFIRMED de hoy en adelante, sin las de hoy que ya terminaron: ésas se pasan lista, no se cancelan) responde 409 con la lista anónima; con `?force=true` las cancela (`cancel_reason = API`, evento `booking.cancelled` con reason `court_block`, partidos desligados, push al titular real, audit por reserva). Emite `occupancy.changed` por el rango. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"from\": \"2026-09-20\",\n  \"to\": \"2026-09-22\",\n  \"startTime\": \"08:00\",\n  \"endTime\": \"12:00\",\n  \"reason\": \"Mantenimiento del césped\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"force","value":"true","description":"`true` cancela las reservas vivas que el bloqueo pisa (por el emisor único, reason `court_block`, partidos desligados) en vez de responder 409 BLOCK_CONFLICTS_WITH_BOOKINGS. Las de torneo nunca se cancelan desde acá.","disabled":true}]},"description":"Crea un bloqueo por cancha (`courtId: null` = todas las habilitadas del club) que ocupa `[startTime, endTime]` en cada día de `[from, to]` (sin horas: el día entero). Si pisa reservas vivas (PENDING / CONFIRMED de hoy en adelante, sin las de hoy que ya terminaron: ésas se pasan lista, no se cancelan) responde 409 con la lista anónima; con `?force=true` las cancela (`cancel_reason = API`, evento `booking.cancelled` con reason `court_block`, partidos desligados, push al titular real, audit por reserva). Emite `occupancy.changed` por el rango. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"from\": \"2026-09-20\",\n  \"to\": \"2026-09-22\",\n  \"startTime\": \"08:00\",\n  \"endTime\": \"12:00\",\n  \"reason\": \"Mantenimiento del césped\"\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · COURT_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"force","value":"true","description":"`true` cancela las reservas vivas que el bloqueo pisa (por el emisor único, reason `court_block`, partidos desligados) en vez de responder 409 BLOCK_CONFLICTS_WITH_BOOKINGS. Las de torneo nunca se cancelan desde acá.","disabled":true}]},"description":"Crea un bloqueo por cancha (`courtId: null` = todas las habilitadas del club) que ocupa `[startTime, endTime]` en cada día de `[from, to]` (sin horas: el día entero). Si pisa reservas vivas (PENDING / CONFIRMED de hoy en adelante, sin las de hoy que ya terminaron: ésas se pasan lista, no se cancelan) responde 409 con la lista anónima; con `?force=true` las cancela (`cancel_reason = API`, evento `booking.cancelled` con reason `court_block`, partidos desligados, push al titular real, audit por reserva). Emite `occupancy.changed` por el rango. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"from\": \"2026-09-20\",\n  \"to\": \"2026-09-22\",\n  \"startTime\": \"08:00\",\n  \"endTime\": \"12:00\",\n  \"reason\": \"Mantenimiento del césped\"\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La cancha no existe o no es de este club.\",\n  \"code\": \"COURT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · BLOCK_CONFLICTS_WITH_BOOKINGS","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"force","value":"true","description":"`true` cancela las reservas vivas que el bloqueo pisa (por el emisor único, reason `court_block`, partidos desligados) en vez de responder 409 BLOCK_CONFLICTS_WITH_BOOKINGS. Las de torneo nunca se cancelan desde acá.","disabled":true}]},"description":"Crea un bloqueo por cancha (`courtId: null` = todas las habilitadas del club) que ocupa `[startTime, endTime]` en cada día de `[from, to]` (sin horas: el día entero). Si pisa reservas vivas (PENDING / CONFIRMED de hoy en adelante, sin las de hoy que ya terminaron: ésas se pasan lista, no se cancelan) responde 409 con la lista anónima; con `?force=true` las cancela (`cancel_reason = API`, evento `booking.cancelled` con reason `court_block`, partidos desligados, push al titular real, audit por reserva). Emite `occupancy.changed` por el rango. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"from\": \"2026-09-20\",\n  \"to\": \"2026-09-22\",\n  \"startTime\": \"08:00\",\n  \"endTime\": \"12:00\",\n  \"reason\": \"Mantenimiento del césped\"\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El bloqueo pisa reservas vivas. Repetí con force=true para cancelarlas.\",\n  \"code\": \"BLOCK_CONFLICTS_WITH_BOOKINGS\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"force","value":"true","description":"`true` cancela las reservas vivas que el bloqueo pisa (por el emisor único, reason `court_block`, partidos desligados) en vez de responder 409 BLOCK_CONFLICTS_WITH_BOOKINGS. Las de torneo nunca se cancelan desde acá.","disabled":true}]},"description":"Crea un bloqueo por cancha (`courtId: null` = todas las habilitadas del club) que ocupa `[startTime, endTime]` en cada día de `[from, to]` (sin horas: el día entero). Si pisa reservas vivas (PENDING / CONFIRMED de hoy en adelante, sin las de hoy que ya terminaron: ésas se pasan lista, no se cancelan) responde 409 con la lista anónima; con `?force=true` las cancela (`cancel_reason = API`, evento `booking.cancelled` con reason `court_block`, partidos desligados, push al titular real, audit por reserva). Emite `occupancy.changed` por el rango. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"from\": \"2026-09-20\",\n  \"to\": \"2026-09-22\",\n  \"startTime\": \"08:00\",\n  \"endTime\": \"12:00\",\n  \"reason\": \"Mantenimiento del césped\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"force","value":"true","description":"`true` cancela las reservas vivas que el bloqueo pisa (por el emisor único, reason `court_block`, partidos desligados) en vez de responder 409 BLOCK_CONFLICTS_WITH_BOOKINGS. Las de torneo nunca se cancelan desde acá.","disabled":true}]},"description":"Crea un bloqueo por cancha (`courtId: null` = todas las habilitadas del club) que ocupa `[startTime, endTime]` en cada día de `[from, to]` (sin horas: el día entero). Si pisa reservas vivas (PENDING / CONFIRMED de hoy en adelante, sin las de hoy que ya terminaron: ésas se pasan lista, no se cancelan) responde 409 con la lista anónima; con `?force=true` las cancela (`cancel_reason = API`, evento `booking.cancelled` con reason `court_block`, partidos desligados, push al titular real, audit por reserva). Emite `occupancy.changed` por el rango. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"from\": \"2026-09-20\",\n  \"to\": \"2026-09-22\",\n  \"startTime\": \"08:00\",\n  \"endTime\": \"12:00\",\n  \"reason\": \"Mantenimiento del césped\"\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"force","value":"true","description":"`true` cancela las reservas vivas que el bloqueo pisa (por el emisor único, reason `court_block`, partidos desligados) en vez de responder 409 BLOCK_CONFLICTS_WITH_BOOKINGS. Las de torneo nunca se cancelan desde acá.","disabled":true}]},"description":"Crea un bloqueo por cancha (`courtId: null` = todas las habilitadas del club) que ocupa `[startTime, endTime]` en cada día de `[from, to]` (sin horas: el día entero). Si pisa reservas vivas (PENDING / CONFIRMED de hoy en adelante, sin las de hoy que ya terminaron: ésas se pasan lista, no se cancelan) responde 409 con la lista anónima; con `?force=true` las cancela (`cancel_reason = API`, evento `booking.cancelled` con reason `court_block`, partidos desligados, push al titular real, audit por reserva). Emite `occupancy.changed` por el rango. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"from\": \"2026-09-20\",\n  \"to\": \"2026-09-22\",\n  \"startTime\": \"08:00\",\n  \"endTime\": \"12:00\",\n  \"reason\": \"Mantenimiento del césped\"\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks","host":["{{baseUrl}}"],"path":["blocks"],"query":[{"key":"force","value":"true","description":"`true` cancela las reservas vivas que el bloqueo pisa (por el emisor único, reason `court_block`, partidos desligados) en vez de responder 409 BLOCK_CONFLICTS_WITH_BOOKINGS. Las de torneo nunca se cancelan desde acá.","disabled":true}]},"description":"Crea un bloqueo por cancha (`courtId: null` = todas las habilitadas del club) que ocupa `[startTime, endTime]` en cada día de `[from, to]` (sin horas: el día entero). Si pisa reservas vivas (PENDING / CONFIRMED de hoy en adelante, sin las de hoy que ya terminaron: ésas se pasan lista, no se cancelan) responde 409 con la lista anónima; con `?force=true` las cancela (`cancel_reason = API`, evento `booking.cancelled` con reason `court_block`, partidos desligados, push al titular real, audit por reserva). Emite `occupancy.changed` por el rango. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"from\": \"2026-09-20\",\n  \"to\": \"2026-09-22\",\n  \"startTime\": \"08:00\",\n  \"endTime\": \"12:00\",\n  \"reason\": \"Mantenimiento del césped\"\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Quitar un bloqueo (deleteBlock)","request":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id","host":["{{baseUrl}}"],"path":["blocks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Borra el bloqueo (los huecos de esa cancha quedan: no dependen de él). Emite `occupancy.changed` con efecto de liberar: la lista de espera del club se entera sola por el emisor. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"response":[{"name":"200 · Quitado.","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id","host":["{{baseUrl}}"],"path":["blocks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Borra el bloqueo (los huecos de esa cancha quedan: no dependen de él). Emite `occupancy.changed` con efecto de liberar: la lista de espera del club se entera sola por el emisor. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"block\": {\n    \"id\": \"3f2a1b0c-9d8e-4f7a-b6c5-d4e3f2a1b0c9\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"from\": \"2026-09-20\",\n    \"to\": \"2026-09-22\",\n    \"startTime\": \"08:00\",\n    \"endTime\": \"12:00\",\n    \"reason\": \"Mantenimiento del césped\",\n    \"holes\": [\n      {\n        \"id\": \"7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d\",\n        \"date\": \"2026-09-21\",\n        \"startTime\": \"10:00\",\n        \"endTime\": \"11:00\"\n      }\n    ],\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n  },\n  \"deleted\": true\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id","host":["{{baseUrl}}"],"path":["blocks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Borra el bloqueo (los huecos de esa cancha quedan: no dependen de él). Emite `occupancy.changed` con efecto de liberar: la lista de espera del club se entera sola por el emisor. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id","host":["{{baseUrl}}"],"path":["blocks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Borra el bloqueo (los huecos de esa cancha quedan: no dependen de él). Emite `occupancy.changed` con efecto de liberar: la lista de espera del club se entera sola por el emisor. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id","host":["{{baseUrl}}"],"path":["blocks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Borra el bloqueo (los huecos de esa cancha quedan: no dependen de él). Emite `occupancy.changed` con efecto de liberar: la lista de espera del club se entera sola por el emisor. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · BLOCK_NOT_FOUND","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id","host":["{{baseUrl}}"],"path":["blocks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Borra el bloqueo (los huecos de esa cancha quedan: no dependen de él). Emite `occupancy.changed` con efecto de liberar: la lista de espera del club se entera sola por el emisor. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El bloqueo no existe o no es de este club.\",\n  \"code\": \"BLOCK_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id","host":["{{baseUrl}}"],"path":["blocks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Borra el bloqueo (los huecos de esa cancha quedan: no dependen de él). Emite `occupancy.changed` con efecto de liberar: la lista de espera del club se entera sola por el emisor. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id","host":["{{baseUrl}}"],"path":["blocks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Borra el bloqueo (los huecos de esa cancha quedan: no dependen de él). Emite `occupancy.changed` con efecto de liberar: la lista de espera del club se entera sola por el emisor. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id","host":["{{baseUrl}}"],"path":["blocks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Borra el bloqueo (los huecos de esa cancha quedan: no dependen de él). Emite `occupancy.changed` con efecto de liberar: la lista de espera del club se entera sola por el emisor. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Abrir un hueco en un bloqueo (createBlockHole)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes","host":["{{baseUrl}}"],"path":["blocks",":id","holes"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Libera `[startTime, endTime]` de UN día dentro del bloqueo: ahí el turno se vuelve a vender aunque el bloqueo siga. La cancha sale del bloqueo; el día tiene que caer en `[from, to]` y la franja dentro de `[startTime, endTime]` del bloqueo (si no, 400 VALIDATION con `details.reason: outside_block` y `details.block`). Los huecos se guardan FUSIONADOS por cancha y día, con la misma fusión del panel: uno que toque o solape a otro existente se une con él (aunque el otro se salga del bloqueo), por eso la respuesta trae el bloqueo releído y el hueco resultante. Repetir la misma franja es inofensivo (fusión idempotente; los ids de ese día cambian). Emite `occupancy.changed` (`court_block_hole`, libera ese día): la lista de espera del club se entera sola. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-21\",\n  \"startTime\": \"10:00\",\n  \"endTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"201 · Hueco abierto (fusionado con los de ese día si tocaba alguno).","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes","host":["{{baseUrl}}"],"path":["blocks",":id","holes"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Libera `[startTime, endTime]` de UN día dentro del bloqueo: ahí el turno se vuelve a vender aunque el bloqueo siga. La cancha sale del bloqueo; el día tiene que caer en `[from, to]` y la franja dentro de `[startTime, endTime]` del bloqueo (si no, 400 VALIDATION con `details.reason: outside_block` y `details.block`). Los huecos se guardan FUSIONADOS por cancha y día, con la misma fusión del panel: uno que toque o solape a otro existente se une con él (aunque el otro se salga del bloqueo), por eso la respuesta trae el bloqueo releído y el hueco resultante. Repetir la misma franja es inofensivo (fusión idempotente; los ids de ese día cambian). Emite `occupancy.changed` (`court_block_hole`, libera ese día): la lista de espera del club se entera sola. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-21\",\n  \"startTime\": \"10:00\",\n  \"endTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"block\": {\n    \"id\": \"3f2a1b0c-9d8e-4f7a-b6c5-d4e3f2a1b0c9\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"from\": \"2026-09-20\",\n    \"to\": \"2026-09-22\",\n    \"startTime\": \"08:00\",\n    \"endTime\": \"12:00\",\n    \"reason\": \"Mantenimiento del césped\",\n    \"holes\": [\n      {\n        \"id\": \"7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d\",\n        \"date\": \"2026-09-21\",\n        \"startTime\": \"10:00\",\n        \"endTime\": \"11:00\"\n      }\n    ],\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n  },\n  \"hole\": {\n    \"id\": \"7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d\",\n    \"date\": \"2026-09-21\",\n    \"startTime\": \"10:00\",\n    \"endTime\": \"11:00\"\n  }\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes","host":["{{baseUrl}}"],"path":["blocks",":id","holes"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Libera `[startTime, endTime]` de UN día dentro del bloqueo: ahí el turno se vuelve a vender aunque el bloqueo siga. La cancha sale del bloqueo; el día tiene que caer en `[from, to]` y la franja dentro de `[startTime, endTime]` del bloqueo (si no, 400 VALIDATION con `details.reason: outside_block` y `details.block`). Los huecos se guardan FUSIONADOS por cancha y día, con la misma fusión del panel: uno que toque o solape a otro existente se une con él (aunque el otro se salga del bloqueo), por eso la respuesta trae el bloqueo releído y el hueco resultante. Repetir la misma franja es inofensivo (fusión idempotente; los ids de ese día cambian). Emite `occupancy.changed` (`court_block_hole`, libera ese día): la lista de espera del club se entera sola. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-21\",\n  \"startTime\": \"10:00\",\n  \"endTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes","host":["{{baseUrl}}"],"path":["blocks",":id","holes"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Libera `[startTime, endTime]` de UN día dentro del bloqueo: ahí el turno se vuelve a vender aunque el bloqueo siga. La cancha sale del bloqueo; el día tiene que caer en `[from, to]` y la franja dentro de `[startTime, endTime]` del bloqueo (si no, 400 VALIDATION con `details.reason: outside_block` y `details.block`). Los huecos se guardan FUSIONADOS por cancha y día, con la misma fusión del panel: uno que toque o solape a otro existente se une con él (aunque el otro se salga del bloqueo), por eso la respuesta trae el bloqueo releído y el hueco resultante. Repetir la misma franja es inofensivo (fusión idempotente; los ids de ese día cambian). Emite `occupancy.changed` (`court_block_hole`, libera ese día): la lista de espera del club se entera sola. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-21\",\n  \"startTime\": \"10:00\",\n  \"endTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes","host":["{{baseUrl}}"],"path":["blocks",":id","holes"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Libera `[startTime, endTime]` de UN día dentro del bloqueo: ahí el turno se vuelve a vender aunque el bloqueo siga. La cancha sale del bloqueo; el día tiene que caer en `[from, to]` y la franja dentro de `[startTime, endTime]` del bloqueo (si no, 400 VALIDATION con `details.reason: outside_block` y `details.block`). Los huecos se guardan FUSIONADOS por cancha y día, con la misma fusión del panel: uno que toque o solape a otro existente se une con él (aunque el otro se salga del bloqueo), por eso la respuesta trae el bloqueo releído y el hueco resultante. Repetir la misma franja es inofensivo (fusión idempotente; los ids de ese día cambian). Emite `occupancy.changed` (`court_block_hole`, libera ese día): la lista de espera del club se entera sola. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-21\",\n  \"startTime\": \"10:00\",\n  \"endTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · BLOCK_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes","host":["{{baseUrl}}"],"path":["blocks",":id","holes"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Libera `[startTime, endTime]` de UN día dentro del bloqueo: ahí el turno se vuelve a vender aunque el bloqueo siga. La cancha sale del bloqueo; el día tiene que caer en `[from, to]` y la franja dentro de `[startTime, endTime]` del bloqueo (si no, 400 VALIDATION con `details.reason: outside_block` y `details.block`). Los huecos se guardan FUSIONADOS por cancha y día, con la misma fusión del panel: uno que toque o solape a otro existente se une con él (aunque el otro se salga del bloqueo), por eso la respuesta trae el bloqueo releído y el hueco resultante. Repetir la misma franja es inofensivo (fusión idempotente; los ids de ese día cambian). Emite `occupancy.changed` (`court_block_hole`, libera ese día): la lista de espera del club se entera sola. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-21\",\n  \"startTime\": \"10:00\",\n  \"endTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El bloqueo no existe o no es de este club.\",\n  \"code\": \"BLOCK_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes","host":["{{baseUrl}}"],"path":["blocks",":id","holes"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Libera `[startTime, endTime]` de UN día dentro del bloqueo: ahí el turno se vuelve a vender aunque el bloqueo siga. La cancha sale del bloqueo; el día tiene que caer en `[from, to]` y la franja dentro de `[startTime, endTime]` del bloqueo (si no, 400 VALIDATION con `details.reason: outside_block` y `details.block`). Los huecos se guardan FUSIONADOS por cancha y día, con la misma fusión del panel: uno que toque o solape a otro existente se une con él (aunque el otro se salga del bloqueo), por eso la respuesta trae el bloqueo releído y el hueco resultante. Repetir la misma franja es inofensivo (fusión idempotente; los ids de ese día cambian). Emite `occupancy.changed` (`court_block_hole`, libera ese día): la lista de espera del club se entera sola. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-21\",\n  \"startTime\": \"10:00\",\n  \"endTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes","host":["{{baseUrl}}"],"path":["blocks",":id","holes"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Libera `[startTime, endTime]` de UN día dentro del bloqueo: ahí el turno se vuelve a vender aunque el bloqueo siga. La cancha sale del bloqueo; el día tiene que caer en `[from, to]` y la franja dentro de `[startTime, endTime]` del bloqueo (si no, 400 VALIDATION con `details.reason: outside_block` y `details.block`). Los huecos se guardan FUSIONADOS por cancha y día, con la misma fusión del panel: uno que toque o solape a otro existente se une con él (aunque el otro se salga del bloqueo), por eso la respuesta trae el bloqueo releído y el hueco resultante. Repetir la misma franja es inofensivo (fusión idempotente; los ids de ese día cambian). Emite `occupancy.changed` (`court_block_hole`, libera ese día): la lista de espera del club se entera sola. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-21\",\n  \"startTime\": \"10:00\",\n  \"endTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes","host":["{{baseUrl}}"],"path":["blocks",":id","holes"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Libera `[startTime, endTime]` de UN día dentro del bloqueo: ahí el turno se vuelve a vender aunque el bloqueo siga. La cancha sale del bloqueo; el día tiene que caer en `[from, to]` y la franja dentro de `[startTime, endTime]` del bloqueo (si no, 400 VALIDATION con `details.reason: outside_block` y `details.block`). Los huecos se guardan FUSIONADOS por cancha y día, con la misma fusión del panel: uno que toque o solape a otro existente se une con él (aunque el otro se salga del bloqueo), por eso la respuesta trae el bloqueo releído y el hueco resultante. Repetir la misma franja es inofensivo (fusión idempotente; los ids de ese día cambian). Emite `occupancy.changed` (`court_block_hole`, libera ese día): la lista de espera del club se entera sola. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-21\",\n  \"startTime\": \"10:00\",\n  \"endTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes","host":["{{baseUrl}}"],"path":["blocks",":id","holes"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."}]},"description":"Libera `[startTime, endTime]` de UN día dentro del bloqueo: ahí el turno se vuelve a vender aunque el bloqueo siga. La cancha sale del bloqueo; el día tiene que caer en `[from, to]` y la franja dentro de `[startTime, endTime]` del bloqueo (si no, 400 VALIDATION con `details.reason: outside_block` y `details.block`). Los huecos se guardan FUSIONADOS por cancha y día, con la misma fusión del panel: uno que toque o solape a otro existente se une con él (aunque el otro se salga del bloqueo), por eso la respuesta trae el bloqueo releído y el hueco resultante. Repetir la misma franja es inofensivo (fusión idempotente; los ids de ese día cambian). Emite `occupancy.changed` (`court_block_hole`, libera ese día): la lista de espera del club se entera sola. Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-21\",\n  \"startTime\": \"10:00\",\n  \"endTime\": \"11:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Cerrar un hueco de un bloqueo (deleteBlockHole)","request":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes/:holeId","host":["{{baseUrl}}"],"path":["blocks",":id","holes",":holeId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."},{"key":"holeId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del hueco (`BlockDto.holes[].id`), del bloqueo de la URL."}]},"description":"Quita el hueco: el bloqueo vuelve a ocupar esa franja (lo ya reservado en el hueco queda: una reserva viva no se cancela desde acá). El hueco tiene que perforar ESE bloqueo (misma cancha, día dentro del rango, franja solapada); si no, 404 HOLE_NOT_FOUND. Emite `occupancy.changed` (`court_block_hole`, ocupa). Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"response":[{"name":"200 · Hueco cerrado.","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes/:holeId","host":["{{baseUrl}}"],"path":["blocks",":id","holes",":holeId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."},{"key":"holeId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del hueco (`BlockDto.holes[].id`), del bloqueo de la URL."}]},"description":"Quita el hueco: el bloqueo vuelve a ocupar esa franja (lo ya reservado en el hueco queda: una reserva viva no se cancela desde acá). El hueco tiene que perforar ESE bloqueo (misma cancha, día dentro del rango, franja solapada); si no, 404 HOLE_NOT_FOUND. Emite `occupancy.changed` (`court_block_hole`, ocupa). Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"block\": {\n    \"id\": \"3f2a1b0c-9d8e-4f7a-b6c5-d4e3f2a1b0c9\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"from\": \"2026-09-20\",\n    \"to\": \"2026-09-22\",\n    \"startTime\": \"08:00\",\n    \"endTime\": \"12:00\",\n    \"reason\": \"Mantenimiento del césped\",\n    \"holes\": [],\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n  },\n  \"hole\": {\n    \"id\": \"7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d\",\n    \"date\": \"2026-09-21\",\n    \"startTime\": \"10:00\",\n    \"endTime\": \"11:00\"\n  },\n  \"deleted\": true\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes/:holeId","host":["{{baseUrl}}"],"path":["blocks",":id","holes",":holeId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."},{"key":"holeId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del hueco (`BlockDto.holes[].id`), del bloqueo de la URL."}]},"description":"Quita el hueco: el bloqueo vuelve a ocupar esa franja (lo ya reservado en el hueco queda: una reserva viva no se cancela desde acá). El hueco tiene que perforar ESE bloqueo (misma cancha, día dentro del rango, franja solapada); si no, 404 HOLE_NOT_FOUND. Emite `occupancy.changed` (`court_block_hole`, ocupa). Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes/:holeId","host":["{{baseUrl}}"],"path":["blocks",":id","holes",":holeId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."},{"key":"holeId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del hueco (`BlockDto.holes[].id`), del bloqueo de la URL."}]},"description":"Quita el hueco: el bloqueo vuelve a ocupar esa franja (lo ya reservado en el hueco queda: una reserva viva no se cancela desde acá). El hueco tiene que perforar ESE bloqueo (misma cancha, día dentro del rango, franja solapada); si no, 404 HOLE_NOT_FOUND. Emite `occupancy.changed` (`court_block_hole`, ocupa). Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes/:holeId","host":["{{baseUrl}}"],"path":["blocks",":id","holes",":holeId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."},{"key":"holeId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del hueco (`BlockDto.holes[].id`), del bloqueo de la URL."}]},"description":"Quita el hueco: el bloqueo vuelve a ocupar esa franja (lo ya reservado en el hueco queda: una reserva viva no se cancela desde acá). El hueco tiene que perforar ESE bloqueo (misma cancha, día dentro del rango, franja solapada); si no, 404 HOLE_NOT_FOUND. Emite `occupancy.changed` (`court_block_hole`, ocupa). Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · BLOCK_NOT_FOUND / HOLE_NOT_FOUND","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes/:holeId","host":["{{baseUrl}}"],"path":["blocks",":id","holes",":holeId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."},{"key":"holeId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del hueco (`BlockDto.holes[].id`), del bloqueo de la URL."}]},"description":"Quita el hueco: el bloqueo vuelve a ocupar esa franja (lo ya reservado en el hueco queda: una reserva viva no se cancela desde acá). El hueco tiene que perforar ESE bloqueo (misma cancha, día dentro del rango, franja solapada); si no, 404 HOLE_NOT_FOUND. Emite `occupancy.changed` (`court_block_hole`, ocupa). Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El bloqueo no existe o no es de este club.\",\n  \"code\": \"BLOCK_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes/:holeId","host":["{{baseUrl}}"],"path":["blocks",":id","holes",":holeId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."},{"key":"holeId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del hueco (`BlockDto.holes[].id`), del bloqueo de la URL."}]},"description":"Quita el hueco: el bloqueo vuelve a ocupar esa franja (lo ya reservado en el hueco queda: una reserva viva no se cancela desde acá). El hueco tiene que perforar ESE bloqueo (misma cancha, día dentro del rango, franja solapada); si no, 404 HOLE_NOT_FOUND. Emite `occupancy.changed` (`court_block_hole`, ocupa). Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes/:holeId","host":["{{baseUrl}}"],"path":["blocks",":id","holes",":holeId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."},{"key":"holeId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del hueco (`BlockDto.holes[].id`), del bloqueo de la URL."}]},"description":"Quita el hueco: el bloqueo vuelve a ocupar esa franja (lo ya reservado en el hueco queda: una reserva viva no se cancela desde acá). El hueco tiene que perforar ESE bloqueo (misma cancha, día dentro del rango, franja solapada); si no, 404 HOLE_NOT_FOUND. Emite `occupancy.changed` (`court_block_hole`, ocupa). Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/blocks/:id/holes/:holeId","host":["{{baseUrl}}"],"path":["blocks",":id","holes",":holeId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del bloqueo."},{"key":"holeId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del hueco (`BlockDto.holes[].id`), del bloqueo de la URL."}]},"description":"Quita el hueco: el bloqueo vuelve a ocupar esa franja (lo ya reservado en el hueco queda: una reserva viva no se cancela desde acá). El hueco tiene que perforar ESE bloqueo (misma cancha, día dentro del rango, franja solapada); si no, 404 HOLE_NOT_FOUND. Emite `occupancy.changed` (`court_block_hole`, ocupa). Consume cuota de escritura.\n\nScope: `blocks:write`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Pasar lista (asistencia / no-show) (markBookingAttendance)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id/attendance","host":["{{baseUrl}}"],"path":["bookings",":id","attendance"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Marca `ATTENDED` / `NO_SHOW` sobre una reserva propia, o sobre cualquiera del club si la integración tiene `canManageAllBookings` (un POS que pasa lista de todo el club lo necesita). Mismos guards que el panel: la cuenta de servicio y el jugador vinculado sin consentimiento nunca cobran ni pagan asistencia / puntos (`scored: false`); el estado de la reserva se marca igual. Ventana: desde 30 minutos antes del comienzo hasta 7 días después del turno. Idempotente por estado. Emite `booking.attended` / `booking.no_show`. Consume cuota de escritura.\n\nScope: `attendance:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"ATTENDED\"\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · Marcada (o ya estaba: `changed: false`).","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id/attendance","host":["{{baseUrl}}"],"path":["bookings",":id","attendance"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Marca `ATTENDED` / `NO_SHOW` sobre una reserva propia, o sobre cualquiera del club si la integración tiene `canManageAllBookings` (un POS que pasa lista de todo el club lo necesita). Mismos guards que el panel: la cuenta de servicio y el jugador vinculado sin consentimiento nunca cobran ni pagan asistencia / puntos (`scored: false`); el estado de la reserva se marca igual. Ventana: desde 30 minutos antes del comienzo hasta 7 días después del turno. Idempotente por estado. Emite `booking.attended` / `booking.no_show`. Consume cuota de escritura.\n\nScope: `attendance:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"ATTENDED\"\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"booking\": {\n    \"id\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"date\": \"2026-09-14\",\n    \"startTime\": \"08:00\",\n    \"endTime\": \"09:00\",\n    \"status\": \"ATTENDED\",\n    \"origin\": \"APP\",\n    \"owned\": false,\n    \"matchCount\": 0,\n    \"recurringId\": null\n  },\n  \"previousStatus\": \"CONFIRMED\",\n  \"changed\": true,\n  \"scored\": true\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / ATTENDANCE_OUT_OF_WINDOW","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id/attendance","host":["{{baseUrl}}"],"path":["bookings",":id","attendance"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Marca `ATTENDED` / `NO_SHOW` sobre una reserva propia, o sobre cualquiera del club si la integración tiene `canManageAllBookings` (un POS que pasa lista de todo el club lo necesita). Mismos guards que el panel: la cuenta de servicio y el jugador vinculado sin consentimiento nunca cobran ni pagan asistencia / puntos (`scored: false`); el estado de la reserva se marca igual. Ventana: desde 30 minutos antes del comienzo hasta 7 días después del turno. Idempotente por estado. Emite `booking.attended` / `booking.no_show`. Consume cuota de escritura.\n\nScope: `attendance:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"ATTENDED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id/attendance","host":["{{baseUrl}}"],"path":["bookings",":id","attendance"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Marca `ATTENDED` / `NO_SHOW` sobre una reserva propia, o sobre cualquiera del club si la integración tiene `canManageAllBookings` (un POS que pasa lista de todo el club lo necesita). Mismos guards que el panel: la cuenta de servicio y el jugador vinculado sin consentimiento nunca cobran ni pagan asistencia / puntos (`scored: false`); el estado de la reserva se marca igual. Ventana: desde 30 minutos antes del comienzo hasta 7 días después del turno. Idempotente por estado. Emite `booking.attended` / `booking.no_show`. Consume cuota de escritura.\n\nScope: `attendance:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"ATTENDED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED / BOOKING_NOT_OWNED_BY_CLIENT","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id/attendance","host":["{{baseUrl}}"],"path":["bookings",":id","attendance"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Marca `ATTENDED` / `NO_SHOW` sobre una reserva propia, o sobre cualquiera del club si la integración tiene `canManageAllBookings` (un POS que pasa lista de todo el club lo necesita). Mismos guards que el panel: la cuenta de servicio y el jugador vinculado sin consentimiento nunca cobran ni pagan asistencia / puntos (`scored: false`); el estado de la reserva se marca igual. Ventana: desde 30 minutos antes del comienzo hasta 7 días después del turno. Idempotente por estado. Emite `booking.attended` / `booking.no_show`. Consume cuota de escritura.\n\nScope: `attendance:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"ATTENDED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · BOOKING_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id/attendance","host":["{{baseUrl}}"],"path":["bookings",":id","attendance"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Marca `ATTENDED` / `NO_SHOW` sobre una reserva propia, o sobre cualquiera del club si la integración tiene `canManageAllBookings` (un POS que pasa lista de todo el club lo necesita). Mismos guards que el panel: la cuenta de servicio y el jugador vinculado sin consentimiento nunca cobran ni pagan asistencia / puntos (`scored: false`); el estado de la reserva se marca igual. Ventana: desde 30 minutos antes del comienzo hasta 7 días después del turno. Idempotente por estado. Emite `booking.attended` / `booking.no_show`. Consume cuota de escritura.\n\nScope: `attendance:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"ATTENDED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva no existe o no es de este club.\",\n  \"code\": \"BOOKING_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · BOOKING_ALREADY_CANCELLED / BOOKING_NOT_MODIFIABLE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id/attendance","host":["{{baseUrl}}"],"path":["bookings",":id","attendance"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Marca `ATTENDED` / `NO_SHOW` sobre una reserva propia, o sobre cualquiera del club si la integración tiene `canManageAllBookings` (un POS que pasa lista de todo el club lo necesita). Mismos guards que el panel: la cuenta de servicio y el jugador vinculado sin consentimiento nunca cobran ni pagan asistencia / puntos (`scored: false`); el estado de la reserva se marca igual. Ventana: desde 30 minutos antes del comienzo hasta 7 días después del turno. Idempotente por estado. Emite `booking.attended` / `booking.no_show`. Consume cuota de escritura.\n\nScope: `attendance:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"ATTENDED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva ya está cancelada.\",\n  \"code\": \"BOOKING_ALREADY_CANCELLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id/attendance","host":["{{baseUrl}}"],"path":["bookings",":id","attendance"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Marca `ATTENDED` / `NO_SHOW` sobre una reserva propia, o sobre cualquiera del club si la integración tiene `canManageAllBookings` (un POS que pasa lista de todo el club lo necesita). Mismos guards que el panel: la cuenta de servicio y el jugador vinculado sin consentimiento nunca cobran ni pagan asistencia / puntos (`scored: false`); el estado de la reserva se marca igual. Ventana: desde 30 minutos antes del comienzo hasta 7 días después del turno. Idempotente por estado. Emite `booking.attended` / `booking.no_show`. Consume cuota de escritura.\n\nScope: `attendance:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"ATTENDED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id/attendance","host":["{{baseUrl}}"],"path":["bookings",":id","attendance"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Marca `ATTENDED` / `NO_SHOW` sobre una reserva propia, o sobre cualquiera del club si la integración tiene `canManageAllBookings` (un POS que pasa lista de todo el club lo necesita). Mismos guards que el panel: la cuenta de servicio y el jugador vinculado sin consentimiento nunca cobran ni pagan asistencia / puntos (`scored: false`); el estado de la reserva se marca igual. Ventana: desde 30 minutos antes del comienzo hasta 7 días después del turno. Idempotente por estado. Emite `booking.attended` / `booking.no_show`. Consume cuota de escritura.\n\nScope: `attendance:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"ATTENDED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id/attendance","host":["{{baseUrl}}"],"path":["bookings",":id","attendance"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Marca `ATTENDED` / `NO_SHOW` sobre una reserva propia, o sobre cualquiera del club si la integración tiene `canManageAllBookings` (un POS que pasa lista de todo el club lo necesita). Mismos guards que el panel: la cuenta de servicio y el jugador vinculado sin consentimiento nunca cobran ni pagan asistencia / puntos (`scored: false`); el estado de la reserva se marca igual. Ventana: desde 30 minutos antes del comienzo hasta 7 días después del turno. Idempotente por estado. Emite `booking.attended` / `booking.no_show`. Consume cuota de escritura.\n\nScope: `attendance:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"ATTENDED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/bookings/:id/attendance","host":["{{baseUrl}}"],"path":["bookings",":id","attendance"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la reserva."}]},"description":"Marca `ATTENDED` / `NO_SHOW` sobre una reserva propia, o sobre cualquiera del club si la integración tiene `canManageAllBookings` (un POS que pasa lista de todo el club lo necesita). Mismos guards que el panel: la cuenta de servicio y el jugador vinculado sin consentimiento nunca cobran ni pagan asistencia / puntos (`scored: false`); el estado de la reserva se marca igual. Ventana: desde 30 minutos antes del comienzo hasta 7 días después del turno. Idempotente por estado. Emite `booking.attended` / `booking.no_show`. Consume cuota de escritura.\n\nScope: `attendance:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"ATTENDED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Listar reservas fijas (listRecurringBookings)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las series de esta cancha.","disabled":true},{"key":"status","value":"ACTIVE","description":"Filtra por estado de la serie. Default `ACTIVE`.","disabled":true}]},"description":"Series de fijas del club (`RecurringBookingDto`), propias y ajenas: `customer` y `externalRef` sólo viajan en las que creó esta integración (`owned: true`); del resto nunca el titular. Orden: primer día, hora, id. `limit` ≤ 200.\n\nScope: `recurring:read`."},"response":[{"name":"200 · Página de series.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las series de esta cancha.","disabled":true},{"key":"status","value":"ACTIVE","description":"Filtra por estado de la serie. Default `ACTIVE`.","disabled":true}]},"description":"Series de fijas del club (`RecurringBookingDto`), propias y ajenas: `customer` y `externalRef` sólo viajan en las que creó esta integración (`owned: true`); del resto nunca el titular. Orden: primer día, hora, id. `limit` ≤ 200.\n\nScope: `recurring:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"recurringBookings\": [\n    {\n      \"id\": \"8b7c6d5e-4f3a-4b2c-9d1e-0f9a8b7c6d5e\",\n      \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n      \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n      \"courtName\": \"Cancha 1\",\n      \"kind\": \"COURT\",\n      \"categoryId\": null,\n      \"resourceNoun\": \"COURT\",\n      \"startDate\": \"2026-09-15\",\n      \"endDate\": null,\n      \"startTime\": \"20:00\",\n      \"endTime\": \"21:30\",\n      \"durationMinutes\": 90,\n      \"frequency\": \"weekly\",\n      \"status\": \"ACTIVE\",\n      \"type\": \"normal\",\n      \"price\": 1400,\n      \"timezone\": \"America/Montevideo\",\n      \"externalRef\": \"FIJA-42\",\n      \"customer\": {\n        \"name\": \"Juan Pérez\",\n        \"phone\": \"+59891234567\",\n        \"email\": null\n      },\n      \"owned\": true,\n      \"nextOccurrence\": \"2026-09-15\",\n      \"skippedDates\": [],\n      \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n    }\n  ],\n  \"total\": 1,\n  \"limit\": 100,\n  \"offset\": 0\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las series de esta cancha.","disabled":true},{"key":"status","value":"ACTIVE","description":"Filtra por estado de la serie. Default `ACTIVE`.","disabled":true}]},"description":"Series de fijas del club (`RecurringBookingDto`), propias y ajenas: `customer` y `externalRef` sólo viajan en las que creó esta integración (`owned: true`); del resto nunca el titular. Orden: primer día, hora, id. `limit` ≤ 200.\n\nScope: `recurring:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las series de esta cancha.","disabled":true},{"key":"status","value":"ACTIVE","description":"Filtra por estado de la serie. Default `ACTIVE`.","disabled":true}]},"description":"Series de fijas del club (`RecurringBookingDto`), propias y ajenas: `customer` y `externalRef` sólo viajan en las que creó esta integración (`owned: true`); del resto nunca el titular. Orden: primer día, hora, id. `limit` ≤ 200.\n\nScope: `recurring:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las series de esta cancha.","disabled":true},{"key":"status","value":"ACTIVE","description":"Filtra por estado de la serie. Default `ACTIVE`.","disabled":true}]},"description":"Series de fijas del club (`RecurringBookingDto`), propias y ajenas: `customer` y `externalRef` sólo viajan en las que creó esta integración (`owned: true`); del resto nunca el titular. Orden: primer día, hora, id. `limit` ≤ 200.\n\nScope: `recurring:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las series de esta cancha.","disabled":true},{"key":"status","value":"ACTIVE","description":"Filtra por estado de la serie. Default `ACTIVE`.","disabled":true}]},"description":"Series de fijas del club (`RecurringBookingDto`), propias y ajenas: `customer` y `externalRef` sólo viajan en las que creó esta integración (`owned: true`); del resto nunca el titular. Orden: primer día, hora, id. `limit` ≤ 200.\n\nScope: `recurring:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las series de esta cancha.","disabled":true},{"key":"status","value":"ACTIVE","description":"Filtra por estado de la serie. Default `ACTIVE`.","disabled":true}]},"description":"Series de fijas del club (`RecurringBookingDto`), propias y ajenas: `customer` y `externalRef` sólo viajan en las que creó esta integración (`owned: true`); del resto nunca el titular. Orden: primer día, hora, id. `limit` ≤ 200.\n\nScope: `recurring:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las series de esta cancha.","disabled":true},{"key":"status","value":"ACTIVE","description":"Filtra por estado de la serie. Default `ACTIVE`.","disabled":true}]},"description":"Series de fijas del club (`RecurringBookingDto`), propias y ajenas: `customer` y `externalRef` sólo viajan en las que creó esta integración (`owned: true`); del resto nunca el titular. Orden: primer día, hora, id. `limit` ≤ 200.\n\nScope: `recurring:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Crear una reserva fija (atómica, idempotente) (createRecurringBooking)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"]},"description":"Alta de una serie a nombre del usuario de servicio del club. Validaciones en orden: turno → cancha (kind COURT) → comienzo en la zona del club → idempotencia → horario de cada ocurrencia materializable → tope de futuras → pre-chequeo de ocupación de cada ocurrencia materializable (hoy → +30 días, las 4 fuentes) → INSERT de la serie + INSERT atómico de esas ocurrencias (`source = recurring`, propias de la integración). Si una carrera ocupa un turno en el medio se deshace todo y responde 409. Una serie que arranca más allá del horizonte no materializa nada hoy, pero se validan igual (horario + ocupación) sus primeros 30 días desde `startDate`. Las ocurrencias más lejanas las crea el cron cuando entran en el horizonte (si para entonces chocan, el club recibe el aviso de conflicto, como con una fija del panel). Emite `booking.created` por ocurrencia y `occupancy.changed` por la serie. Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"startDate\": \"2026-09-15\",\n  \"endDate\": null,\n  \"startTime\": \"20:00\",\n  \"durationMinutes\": 90,\n  \"frequency\": \"weekly\",\n  \"externalRef\": \"FIJA-42\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"price\": 1400\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · Replay: el `externalRef` ya existía vivo con la MISMA serie; se devuelve esa serie.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"]},"description":"Alta de una serie a nombre del usuario de servicio del club. Validaciones en orden: turno → cancha (kind COURT) → comienzo en la zona del club → idempotencia → horario de cada ocurrencia materializable → tope de futuras → pre-chequeo de ocupación de cada ocurrencia materializable (hoy → +30 días, las 4 fuentes) → INSERT de la serie + INSERT atómico de esas ocurrencias (`source = recurring`, propias de la integración). Si una carrera ocupa un turno en el medio se deshace todo y responde 409. Una serie que arranca más allá del horizonte no materializa nada hoy, pero se validan igual (horario + ocupación) sus primeros 30 días desde `startDate`. Las ocurrencias más lejanas las crea el cron cuando entran en el horizonte (si para entonces chocan, el club recibe el aviso de conflicto, como con una fija del panel). Emite `booking.created` por ocurrencia y `occupancy.changed` por la serie. Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"startDate\": \"2026-09-15\",\n  \"endDate\": null,\n  \"startTime\": \"20:00\",\n  \"durationMinutes\": 90,\n  \"frequency\": \"weekly\",\n  \"externalRef\": \"FIJA-42\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"price\": 1400\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"recurringBooking\": {\n    \"id\": \"8b7c6d5e-4f3a-4b2c-9d1e-0f9a8b7c6d5e\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"startDate\": \"2026-09-15\",\n    \"endDate\": null,\n    \"startTime\": \"20:00\",\n    \"endTime\": \"21:30\",\n    \"durationMinutes\": 90,\n    \"frequency\": \"weekly\",\n    \"status\": \"ACTIVE\",\n    \"type\": \"normal\",\n    \"price\": 1400,\n    \"timezone\": \"America/Montevideo\",\n    \"externalRef\": \"FIJA-42\",\n    \"customer\": {\n      \"name\": \"Juan Pérez\",\n      \"phone\": \"+59891234567\",\n      \"email\": null\n    },\n    \"owned\": true,\n    \"nextOccurrence\": \"2026-09-15\",\n    \"skippedDates\": [],\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n  },\n  \"materializedOccurrences\": 5\n}"},{"name":"201 · Serie creada.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"]},"description":"Alta de una serie a nombre del usuario de servicio del club. Validaciones en orden: turno → cancha (kind COURT) → comienzo en la zona del club → idempotencia → horario de cada ocurrencia materializable → tope de futuras → pre-chequeo de ocupación de cada ocurrencia materializable (hoy → +30 días, las 4 fuentes) → INSERT de la serie + INSERT atómico de esas ocurrencias (`source = recurring`, propias de la integración). Si una carrera ocupa un turno en el medio se deshace todo y responde 409. Una serie que arranca más allá del horizonte no materializa nada hoy, pero se validan igual (horario + ocupación) sus primeros 30 días desde `startDate`. Las ocurrencias más lejanas las crea el cron cuando entran en el horizonte (si para entonces chocan, el club recibe el aviso de conflicto, como con una fija del panel). Emite `booking.created` por ocurrencia y `occupancy.changed` por la serie. Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"startDate\": \"2026-09-15\",\n  \"endDate\": null,\n  \"startTime\": \"20:00\",\n  \"durationMinutes\": 90,\n  \"frequency\": \"weekly\",\n  \"externalRef\": \"FIJA-42\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"price\": 1400\n}","options":{"raw":{"language":"json"}}}},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"recurringBooking\": {\n    \"id\": \"8b7c6d5e-4f3a-4b2c-9d1e-0f9a8b7c6d5e\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"startDate\": \"2026-09-15\",\n    \"endDate\": null,\n    \"startTime\": \"20:00\",\n    \"endTime\": \"21:30\",\n    \"durationMinutes\": 90,\n    \"frequency\": \"weekly\",\n    \"status\": \"ACTIVE\",\n    \"type\": \"normal\",\n    \"price\": 1400,\n    \"timezone\": \"America/Montevideo\",\n    \"externalRef\": \"FIJA-42\",\n    \"customer\": {\n      \"name\": \"Juan Pérez\",\n      \"phone\": \"+59891234567\",\n      \"email\": null\n    },\n    \"owned\": true,\n    \"nextOccurrence\": \"2026-09-15\",\n    \"skippedDates\": [],\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n  },\n  \"materializedOccurrences\": 5\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED / INVALID_DURATION / DATE_IN_PAST / MAX_ADVANCE_EXCEEDED / OUTSIDE_OPENING_HOURS","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"]},"description":"Alta de una serie a nombre del usuario de servicio del club. Validaciones en orden: turno → cancha (kind COURT) → comienzo en la zona del club → idempotencia → horario de cada ocurrencia materializable → tope de futuras → pre-chequeo de ocupación de cada ocurrencia materializable (hoy → +30 días, las 4 fuentes) → INSERT de la serie + INSERT atómico de esas ocurrencias (`source = recurring`, propias de la integración). Si una carrera ocupa un turno en el medio se deshace todo y responde 409. Una serie que arranca más allá del horizonte no materializa nada hoy, pero se validan igual (horario + ocupación) sus primeros 30 días desde `startDate`. Las ocurrencias más lejanas las crea el cron cuando entran en el horizonte (si para entonces chocan, el club recibe el aviso de conflicto, como con una fija del panel). Emite `booking.created` por ocurrencia y `occupancy.changed` por la serie. Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"startDate\": \"2026-09-15\",\n  \"endDate\": null,\n  \"startTime\": \"20:00\",\n  \"durationMinutes\": 90,\n  \"frequency\": \"weekly\",\n  \"externalRef\": \"FIJA-42\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"price\": 1400\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"]},"description":"Alta de una serie a nombre del usuario de servicio del club. Validaciones en orden: turno → cancha (kind COURT) → comienzo en la zona del club → idempotencia → horario de cada ocurrencia materializable → tope de futuras → pre-chequeo de ocupación de cada ocurrencia materializable (hoy → +30 días, las 4 fuentes) → INSERT de la serie + INSERT atómico de esas ocurrencias (`source = recurring`, propias de la integración). Si una carrera ocupa un turno en el medio se deshace todo y responde 409. Una serie que arranca más allá del horizonte no materializa nada hoy, pero se validan igual (horario + ocupación) sus primeros 30 días desde `startDate`. Las ocurrencias más lejanas las crea el cron cuando entran en el horizonte (si para entonces chocan, el club recibe el aviso de conflicto, como con una fija del panel). Emite `booking.created` por ocurrencia y `occupancy.changed` por la serie. Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"startDate\": \"2026-09-15\",\n  \"endDate\": null,\n  \"startTime\": \"20:00\",\n  \"durationMinutes\": 90,\n  \"frequency\": \"weekly\",\n  \"externalRef\": \"FIJA-42\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"price\": 1400\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"]},"description":"Alta de una serie a nombre del usuario de servicio del club. Validaciones en orden: turno → cancha (kind COURT) → comienzo en la zona del club → idempotencia → horario de cada ocurrencia materializable → tope de futuras → pre-chequeo de ocupación de cada ocurrencia materializable (hoy → +30 días, las 4 fuentes) → INSERT de la serie + INSERT atómico de esas ocurrencias (`source = recurring`, propias de la integración). Si una carrera ocupa un turno en el medio se deshace todo y responde 409. Una serie que arranca más allá del horizonte no materializa nada hoy, pero se validan igual (horario + ocupación) sus primeros 30 días desde `startDate`. Las ocurrencias más lejanas las crea el cron cuando entran en el horizonte (si para entonces chocan, el club recibe el aviso de conflicto, como con una fija del panel). Emite `booking.created` por ocurrencia y `occupancy.changed` por la serie. Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"startDate\": \"2026-09-15\",\n  \"endDate\": null,\n  \"startTime\": \"20:00\",\n  \"durationMinutes\": 90,\n  \"frequency\": \"weekly\",\n  \"externalRef\": \"FIJA-42\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"price\": 1400\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · COURT_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"]},"description":"Alta de una serie a nombre del usuario de servicio del club. Validaciones en orden: turno → cancha (kind COURT) → comienzo en la zona del club → idempotencia → horario de cada ocurrencia materializable → tope de futuras → pre-chequeo de ocupación de cada ocurrencia materializable (hoy → +30 días, las 4 fuentes) → INSERT de la serie + INSERT atómico de esas ocurrencias (`source = recurring`, propias de la integración). Si una carrera ocupa un turno en el medio se deshace todo y responde 409. Una serie que arranca más allá del horizonte no materializa nada hoy, pero se validan igual (horario + ocupación) sus primeros 30 días desde `startDate`. Las ocurrencias más lejanas las crea el cron cuando entran en el horizonte (si para entonces chocan, el club recibe el aviso de conflicto, como con una fija del panel). Emite `booking.created` por ocurrencia y `occupancy.changed` por la serie. Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"startDate\": \"2026-09-15\",\n  \"endDate\": null,\n  \"startTime\": \"20:00\",\n  \"durationMinutes\": 90,\n  \"frequency\": \"weekly\",\n  \"externalRef\": \"FIJA-42\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"price\": 1400\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La cancha no existe o no es de este club.\",\n  \"code\": \"COURT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · RECURRING_CONFLICT / EXTERNAL_REF_USED / EXTERNAL_REF_CONFLICT / RESOURCE_NOT_COURT","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"]},"description":"Alta de una serie a nombre del usuario de servicio del club. Validaciones en orden: turno → cancha (kind COURT) → comienzo en la zona del club → idempotencia → horario de cada ocurrencia materializable → tope de futuras → pre-chequeo de ocupación de cada ocurrencia materializable (hoy → +30 días, las 4 fuentes) → INSERT de la serie + INSERT atómico de esas ocurrencias (`source = recurring`, propias de la integración). Si una carrera ocupa un turno en el medio se deshace todo y responde 409. Una serie que arranca más allá del horizonte no materializa nada hoy, pero se validan igual (horario + ocupación) sus primeros 30 días desde `startDate`. Las ocurrencias más lejanas las crea el cron cuando entran en el horizonte (si para entonces chocan, el club recibe el aviso de conflicto, como con una fija del panel). Emite `booking.created` por ocurrencia y `occupancy.changed` por la serie. Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"startDate\": \"2026-09-15\",\n  \"endDate\": null,\n  \"startTime\": \"20:00\",\n  \"durationMinutes\": 90,\n  \"frequency\": \"weekly\",\n  \"externalRef\": \"FIJA-42\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"price\": 1400\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Alguna ocurrencia de la fija choca con la agenda (reserva, fija, bloqueo o partido).\",\n  \"code\": \"RECURRING_CONFLICT\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"]},"description":"Alta de una serie a nombre del usuario de servicio del club. Validaciones en orden: turno → cancha (kind COURT) → comienzo en la zona del club → idempotencia → horario de cada ocurrencia materializable → tope de futuras → pre-chequeo de ocupación de cada ocurrencia materializable (hoy → +30 días, las 4 fuentes) → INSERT de la serie + INSERT atómico de esas ocurrencias (`source = recurring`, propias de la integración). Si una carrera ocupa un turno en el medio se deshace todo y responde 409. Una serie que arranca más allá del horizonte no materializa nada hoy, pero se validan igual (horario + ocupación) sus primeros 30 días desde `startDate`. Las ocurrencias más lejanas las crea el cron cuando entran en el horizonte (si para entonces chocan, el club recibe el aviso de conflicto, como con una fija del panel). Emite `booking.created` por ocurrencia y `occupancy.changed` por la serie. Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"startDate\": \"2026-09-15\",\n  \"endDate\": null,\n  \"startTime\": \"20:00\",\n  \"durationMinutes\": 90,\n  \"frequency\": \"weekly\",\n  \"externalRef\": \"FIJA-42\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"price\": 1400\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"]},"description":"Alta de una serie a nombre del usuario de servicio del club. Validaciones en orden: turno → cancha (kind COURT) → comienzo en la zona del club → idempotencia → horario de cada ocurrencia materializable → tope de futuras → pre-chequeo de ocupación de cada ocurrencia materializable (hoy → +30 días, las 4 fuentes) → INSERT de la serie + INSERT atómico de esas ocurrencias (`source = recurring`, propias de la integración). Si una carrera ocupa un turno en el medio se deshace todo y responde 409. Una serie que arranca más allá del horizonte no materializa nada hoy, pero se validan igual (horario + ocupación) sus primeros 30 días desde `startDate`. Las ocurrencias más lejanas las crea el cron cuando entran en el horizonte (si para entonces chocan, el club recibe el aviso de conflicto, como con una fija del panel). Emite `booking.created` por ocurrencia y `occupancy.changed` por la serie. Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"startDate\": \"2026-09-15\",\n  \"endDate\": null,\n  \"startTime\": \"20:00\",\n  \"durationMinutes\": 90,\n  \"frequency\": \"weekly\",\n  \"externalRef\": \"FIJA-42\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"price\": 1400\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"]},"description":"Alta de una serie a nombre del usuario de servicio del club. Validaciones en orden: turno → cancha (kind COURT) → comienzo en la zona del club → idempotencia → horario de cada ocurrencia materializable → tope de futuras → pre-chequeo de ocupación de cada ocurrencia materializable (hoy → +30 días, las 4 fuentes) → INSERT de la serie + INSERT atómico de esas ocurrencias (`source = recurring`, propias de la integración). Si una carrera ocupa un turno en el medio se deshace todo y responde 409. Una serie que arranca más allá del horizonte no materializa nada hoy, pero se validan igual (horario + ocupación) sus primeros 30 días desde `startDate`. Las ocurrencias más lejanas las crea el cron cuando entran en el horizonte (si para entonces chocan, el club recibe el aviso de conflicto, como con una fija del panel). Emite `booking.created` por ocurrencia y `occupancy.changed` por la serie. Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"startDate\": \"2026-09-15\",\n  \"endDate\": null,\n  \"startTime\": \"20:00\",\n  \"durationMinutes\": 90,\n  \"frequency\": \"weekly\",\n  \"externalRef\": \"FIJA-42\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"price\": 1400\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"},{"key":"Idempotency-Key","value":"","description":"Alias de `externalRef` en el body (mismas reglas: ≤ 64 chars imprimibles, de un solo uso).","disabled":true}],"url":{"raw":"{{baseUrl}}/recurring-bookings","host":["{{baseUrl}}"],"path":["recurring-bookings"]},"description":"Alta de una serie a nombre del usuario de servicio del club. Validaciones en orden: turno → cancha (kind COURT) → comienzo en la zona del club → idempotencia → horario de cada ocurrencia materializable → tope de futuras → pre-chequeo de ocupación de cada ocurrencia materializable (hoy → +30 días, las 4 fuentes) → INSERT de la serie + INSERT atómico de esas ocurrencias (`source = recurring`, propias de la integración). Si una carrera ocupa un turno en el medio se deshace todo y responde 409. Una serie que arranca más allá del horizonte no materializa nada hoy, pero se validan igual (horario + ocupación) sus primeros 30 días desde `startDate`. Las ocurrencias más lejanas las crea el cron cuando entran en el horizonte (si para entonces chocan, el club recibe el aviso de conflicto, como con una fija del panel). Emite `booking.created` por ocurrencia y `occupancy.changed` por la serie. Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"startDate\": \"2026-09-15\",\n  \"endDate\": null,\n  \"startTime\": \"20:00\",\n  \"durationMinutes\": 90,\n  \"frequency\": \"weekly\",\n  \"externalRef\": \"FIJA-42\",\n  \"customer\": {\n    \"name\": \"Juan Pérez\",\n    \"phone\": \"+598 91 234 567\"\n  },\n  \"price\": 1400\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Acortar una fija o corregir cliente / precio (updateRecurringBooking)","request":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Sólo `endDate` (acortar o cerrar la serie: las ocurrencias VIVAS que quedan afuera, de hoy en adelante, se cancelan con su evento; lo ya jugado no se toca y `endDate` nunca puede ser anterior a ayer), `customer` y `price` (se propagan a las ocurrencias futuras). Mover cancha / día / horario = DELETE + POST. Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"endDate\": \"2026-12-31\"\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · La serie actualizada.","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Sólo `endDate` (acortar o cerrar la serie: las ocurrencias VIVAS que quedan afuera, de hoy en adelante, se cancelan con su evento; lo ya jugado no se toca y `endDate` nunca puede ser anterior a ayer), `customer` y `price` (se propagan a las ocurrencias futuras). Mover cancha / día / horario = DELETE + POST. Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"endDate\": \"2026-12-31\"\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"recurringBooking\": {\n    \"id\": \"8b7c6d5e-4f3a-4b2c-9d1e-0f9a8b7c6d5e\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"startDate\": \"2026-09-15\",\n    \"endDate\": \"2026-12-31\",\n    \"startTime\": \"20:00\",\n    \"endTime\": \"21:30\",\n    \"durationMinutes\": 90,\n    \"frequency\": \"weekly\",\n    \"status\": \"ACTIVE\",\n    \"type\": \"normal\",\n    \"price\": 1400,\n    \"timezone\": \"America/Montevideo\",\n    \"externalRef\": \"FIJA-42\",\n    \"customer\": {\n      \"name\": \"Juan Pérez\",\n      \"phone\": \"+59891234567\",\n      \"email\": null\n    },\n    \"owned\": true,\n    \"nextOccurrence\": \"2026-09-15\",\n    \"skippedDates\": [],\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n  },\n  \"cancelledOccurrences\": 0,\n  \"detachedMatches\": 0\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Sólo `endDate` (acortar o cerrar la serie: las ocurrencias VIVAS que quedan afuera, de hoy en adelante, se cancelan con su evento; lo ya jugado no se toca y `endDate` nunca puede ser anterior a ayer), `customer` y `price` (se propagan a las ocurrencias futuras). Mover cancha / día / horario = DELETE + POST. Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"endDate\": \"2026-12-31\"\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Sólo `endDate` (acortar o cerrar la serie: las ocurrencias VIVAS que quedan afuera, de hoy en adelante, se cancelan con su evento; lo ya jugado no se toca y `endDate` nunca puede ser anterior a ayer), `customer` y `price` (se propagan a las ocurrencias futuras). Mover cancha / día / horario = DELETE + POST. Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"endDate\": \"2026-12-31\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED / RECURRING_NOT_OWNED_BY_CLIENT","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Sólo `endDate` (acortar o cerrar la serie: las ocurrencias VIVAS que quedan afuera, de hoy en adelante, se cancelan con su evento; lo ya jugado no se toca y `endDate` nunca puede ser anterior a ayer), `customer` y `price` (se propagan a las ocurrencias futuras). Mover cancha / día / horario = DELETE + POST. Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"endDate\": \"2026-12-31\"\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · RECURRING_NOT_FOUND","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Sólo `endDate` (acortar o cerrar la serie: las ocurrencias VIVAS que quedan afuera, de hoy en adelante, se cancelan con su evento; lo ya jugado no se toca y `endDate` nunca puede ser anterior a ayer), `customer` y `price` (se propagan a las ocurrencias futuras). Mover cancha / día / horario = DELETE + POST. Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"endDate\": \"2026-12-31\"\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva fija no existe o no es de este club.\",\n  \"code\": \"RECURRING_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · RECURRING_ALREADY_CANCELLED / RECURRING_NOT_MODIFIABLE","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Sólo `endDate` (acortar o cerrar la serie: las ocurrencias VIVAS que quedan afuera, de hoy en adelante, se cancelan con su evento; lo ya jugado no se toca y `endDate` nunca puede ser anterior a ayer), `customer` y `price` (se propagan a las ocurrencias futuras). Mover cancha / día / horario = DELETE + POST. Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"endDate\": \"2026-12-31\"\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva fija ya está cancelada.\",\n  \"code\": \"RECURRING_ALREADY_CANCELLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Sólo `endDate` (acortar o cerrar la serie: las ocurrencias VIVAS que quedan afuera, de hoy en adelante, se cancelan con su evento; lo ya jugado no se toca y `endDate` nunca puede ser anterior a ayer), `customer` y `price` (se propagan a las ocurrencias futuras). Mover cancha / día / horario = DELETE + POST. Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"endDate\": \"2026-12-31\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Sólo `endDate` (acortar o cerrar la serie: las ocurrencias VIVAS que quedan afuera, de hoy en adelante, se cancelan con su evento; lo ya jugado no se toca y `endDate` nunca puede ser anterior a ayer), `customer` y `price` (se propagan a las ocurrencias futuras). Mover cancha / día / horario = DELETE + POST. Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"endDate\": \"2026-12-31\"\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Sólo `endDate` (acortar o cerrar la serie: las ocurrencias VIVAS que quedan afuera, de hoy en adelante, se cancelan con su evento; lo ya jugado no se toca y `endDate` nunca puede ser anterior a ayer), `customer` y `price` (se propagan a las ocurrencias futuras). Mover cancha / día / horario = DELETE + POST. Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"endDate\": \"2026-12-31\"\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Sólo `endDate` (acortar o cerrar la serie: las ocurrencias VIVAS que quedan afuera, de hoy en adelante, se cancelan con su evento; lo ya jugado no se toca y `endDate` nunca puede ser anterior a ayer), `customer` y `price` (se propagan a las ocurrencias futuras). Mover cancha / día / horario = DELETE + POST. Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"endDate\": \"2026-12-31\"\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Cancelar una fija (cancelRecurringBooking)","request":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"query":[{"key":"keepFuture","value":"true","description":"`true` sólo cierra la serie: las ocurrencias ya materializadas siguen vivas como reservas sueltas.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Cierra la serie (`status = CANCELLED`) y, salvo `keepFuture=true`, cancela las ocurrencias materializadas VIVAS de hoy en adelante (evento `booking.cancelled` por cada una, partidos desligados; lo ya jugado, incluido el turno de hoy que ya terminó, no se toca). Emite `occupancy.changed` liberando la cadencia desde hoy. Idempotente (`alreadyCancelled`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura."},"response":[{"name":"200 · Cancelada, o ya lo estaba (`alreadyCancelled: true`).","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"query":[{"key":"keepFuture","value":"true","description":"`true` sólo cierra la serie: las ocurrencias ya materializadas siguen vivas como reservas sueltas.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Cierra la serie (`status = CANCELLED`) y, salvo `keepFuture=true`, cancela las ocurrencias materializadas VIVAS de hoy en adelante (evento `booking.cancelled` por cada una, partidos desligados; lo ya jugado, incluido el turno de hoy que ya terminó, no se toca). Emite `occupancy.changed` liberando la cadencia desde hoy. Idempotente (`alreadyCancelled`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"recurringBooking\": {\n    \"id\": \"8b7c6d5e-4f3a-4b2c-9d1e-0f9a8b7c6d5e\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"startDate\": \"2026-09-15\",\n    \"endDate\": null,\n    \"startTime\": \"20:00\",\n    \"endTime\": \"21:30\",\n    \"durationMinutes\": 90,\n    \"frequency\": \"weekly\",\n    \"status\": \"CANCELLED\",\n    \"type\": \"normal\",\n    \"price\": 1400,\n    \"timezone\": \"America/Montevideo\",\n    \"externalRef\": \"FIJA-42\",\n    \"customer\": {\n      \"name\": \"Juan Pérez\",\n      \"phone\": \"+59891234567\",\n      \"email\": null\n    },\n    \"owned\": true,\n    \"nextOccurrence\": null,\n    \"skippedDates\": [],\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n  },\n  \"cancelledOccurrences\": 4,\n  \"detachedMatches\": 0,\n  \"alreadyCancelled\": false\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"query":[{"key":"keepFuture","value":"true","description":"`true` sólo cierra la serie: las ocurrencias ya materializadas siguen vivas como reservas sueltas.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Cierra la serie (`status = CANCELLED`) y, salvo `keepFuture=true`, cancela las ocurrencias materializadas VIVAS de hoy en adelante (evento `booking.cancelled` por cada una, partidos desligados; lo ya jugado, incluido el turno de hoy que ya terminó, no se toca). Emite `occupancy.changed` liberando la cadencia desde hoy. Idempotente (`alreadyCancelled`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"query":[{"key":"keepFuture","value":"true","description":"`true` sólo cierra la serie: las ocurrencias ya materializadas siguen vivas como reservas sueltas.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Cierra la serie (`status = CANCELLED`) y, salvo `keepFuture=true`, cancela las ocurrencias materializadas VIVAS de hoy en adelante (evento `booking.cancelled` por cada una, partidos desligados; lo ya jugado, incluido el turno de hoy que ya terminó, no se toca). Emite `occupancy.changed` liberando la cadencia desde hoy. Idempotente (`alreadyCancelled`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED / RECURRING_NOT_OWNED_BY_CLIENT","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"query":[{"key":"keepFuture","value":"true","description":"`true` sólo cierra la serie: las ocurrencias ya materializadas siguen vivas como reservas sueltas.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Cierra la serie (`status = CANCELLED`) y, salvo `keepFuture=true`, cancela las ocurrencias materializadas VIVAS de hoy en adelante (evento `booking.cancelled` por cada una, partidos desligados; lo ya jugado, incluido el turno de hoy que ya terminó, no se toca). Emite `occupancy.changed` liberando la cadencia desde hoy. Idempotente (`alreadyCancelled`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · RECURRING_NOT_FOUND","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"query":[{"key":"keepFuture","value":"true","description":"`true` sólo cierra la serie: las ocurrencias ya materializadas siguen vivas como reservas sueltas.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Cierra la serie (`status = CANCELLED`) y, salvo `keepFuture=true`, cancela las ocurrencias materializadas VIVAS de hoy en adelante (evento `booking.cancelled` por cada una, partidos desligados; lo ya jugado, incluido el turno de hoy que ya terminó, no se toca). Emite `occupancy.changed` liberando la cadencia desde hoy. Idempotente (`alreadyCancelled`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva fija no existe o no es de este club.\",\n  \"code\": \"RECURRING_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"query":[{"key":"keepFuture","value":"true","description":"`true` sólo cierra la serie: las ocurrencias ya materializadas siguen vivas como reservas sueltas.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Cierra la serie (`status = CANCELLED`) y, salvo `keepFuture=true`, cancela las ocurrencias materializadas VIVAS de hoy en adelante (evento `booking.cancelled` por cada una, partidos desligados; lo ya jugado, incluido el turno de hoy que ya terminó, no se toca). Emite `occupancy.changed` liberando la cadencia desde hoy. Idempotente (`alreadyCancelled`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"query":[{"key":"keepFuture","value":"true","description":"`true` sólo cierra la serie: las ocurrencias ya materializadas siguen vivas como reservas sueltas.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Cierra la serie (`status = CANCELLED`) y, salvo `keepFuture=true`, cancela las ocurrencias materializadas VIVAS de hoy en adelante (evento `booking.cancelled` por cada una, partidos desligados; lo ya jugado, incluido el turno de hoy que ya terminó, no se toca). Emite `occupancy.changed` liberando la cadencia desde hoy. Idempotente (`alreadyCancelled`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"query":[{"key":"keepFuture","value":"true","description":"`true` sólo cierra la serie: las ocurrencias ya materializadas siguen vivas como reservas sueltas.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Cierra la serie (`status = CANCELLED`) y, salvo `keepFuture=true`, cancela las ocurrencias materializadas VIVAS de hoy en adelante (evento `booking.cancelled` por cada una, partidos desligados; lo ya jugado, incluido el turno de hoy que ya terminó, no se toca). Emite `occupancy.changed` liberando la cadencia desde hoy. Idempotente (`alreadyCancelled`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Una reserva fija (getRecurringBooking)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"La serie (`RecurringBookingDto`), propia o ajena, con la misma anonimización del listado: `customer` y `externalRef` sólo si la creó esta integración (`owned: true`). Es adonde apunta el `Location` del alta y el `recurringId` de una ocurrencia (`BookingDto` / `SlotDto`).\n\nScope: `recurring:read`."},"response":[{"name":"200 · La serie.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"La serie (`RecurringBookingDto`), propia o ajena, con la misma anonimización del listado: `customer` y `externalRef` sólo si la creó esta integración (`owned: true`). Es adonde apunta el `Location` del alta y el `recurringId` de una ocurrencia (`BookingDto` / `SlotDto`).\n\nScope: `recurring:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"recurringBooking\": {\n    \"id\": \"8b7c6d5e-4f3a-4b2c-9d1e-0f9a8b7c6d5e\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"startDate\": \"2026-09-15\",\n    \"endDate\": null,\n    \"startTime\": \"20:00\",\n    \"endTime\": \"21:30\",\n    \"durationMinutes\": 90,\n    \"frequency\": \"weekly\",\n    \"status\": \"ACTIVE\",\n    \"type\": \"normal\",\n    \"price\": 1400,\n    \"timezone\": \"America/Montevideo\",\n    \"externalRef\": \"FIJA-42\",\n    \"customer\": {\n      \"name\": \"Juan Pérez\",\n      \"phone\": \"+59891234567\",\n      \"email\": null\n    },\n    \"owned\": true,\n    \"nextOccurrence\": \"2026-09-15\",\n    \"skippedDates\": [],\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n  }\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"La serie (`RecurringBookingDto`), propia o ajena, con la misma anonimización del listado: `customer` y `externalRef` sólo si la creó esta integración (`owned: true`). Es adonde apunta el `Location` del alta y el `recurringId` de una ocurrencia (`BookingDto` / `SlotDto`).\n\nScope: `recurring:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"La serie (`RecurringBookingDto`), propia o ajena, con la misma anonimización del listado: `customer` y `externalRef` sólo si la creó esta integración (`owned: true`). Es adonde apunta el `Location` del alta y el `recurringId` de una ocurrencia (`BookingDto` / `SlotDto`).\n\nScope: `recurring:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"La serie (`RecurringBookingDto`), propia o ajena, con la misma anonimización del listado: `customer` y `externalRef` sólo si la creó esta integración (`owned: true`). Es adonde apunta el `Location` del alta y el `recurringId` de una ocurrencia (`BookingDto` / `SlotDto`).\n\nScope: `recurring:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · RECURRING_NOT_FOUND","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"La serie (`RecurringBookingDto`), propia o ajena, con la misma anonimización del listado: `customer` y `externalRef` sólo si la creó esta integración (`owned: true`). Es adonde apunta el `Location` del alta y el `recurringId` de una ocurrencia (`BookingDto` / `SlotDto`).\n\nScope: `recurring:read`."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva fija no existe o no es de este club.\",\n  \"code\": \"RECURRING_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"La serie (`RecurringBookingDto`), propia o ajena, con la misma anonimización del listado: `customer` y `externalRef` sólo si la creó esta integración (`owned: true`). Es adonde apunta el `Location` del alta y el `recurringId` de una ocurrencia (`BookingDto` / `SlotDto`).\n\nScope: `recurring:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"La serie (`RecurringBookingDto`), propia o ajena, con la misma anonimización del listado: `customer` y `externalRef` sólo si la creó esta integración (`owned: true`). Es adonde apunta el `Location` del alta y el `recurringId` de una ocurrencia (`BookingDto` / `SlotDto`).\n\nScope: `recurring:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id","host":["{{baseUrl}}"],"path":["recurring-bookings",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"La serie (`RecurringBookingDto`), propia o ajena, con la misma anonimización del listado: `customer` y `externalRef` sólo si la creó esta integración (`owned: true`). Es adonde apunta el `Location` del alta y el `recurringId` de una ocurrencia (`BookingDto` / `SlotDto`).\n\nScope: `recurring:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Saltar una fecha de la fija (skipRecurringBookingDate)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/exceptions","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","exceptions"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Inserta la excepción (la serie sigue) y, si la ocurrencia ya estaba materializada, la cancela con su evento. Emite `occupancy.changed` liberando ese día. Repetir la misma fecha responde 200 (`alreadySkipped: true`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-22\"\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · Ya estaba salteada (idempotente).","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/exceptions","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","exceptions"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Inserta la excepción (la serie sigue) y, si la ocurrencia ya estaba materializada, la cancela con su evento. Emite `occupancy.changed` liberando ese día. Repetir la misma fecha responde 200 (`alreadySkipped: true`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-22\"\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"recurringBooking\": {\n    \"id\": \"8b7c6d5e-4f3a-4b2c-9d1e-0f9a8b7c6d5e\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"startDate\": \"2026-09-15\",\n    \"endDate\": null,\n    \"startTime\": \"20:00\",\n    \"endTime\": \"21:30\",\n    \"durationMinutes\": 90,\n    \"frequency\": \"weekly\",\n    \"status\": \"ACTIVE\",\n    \"type\": \"normal\",\n    \"price\": 1400,\n    \"timezone\": \"America/Montevideo\",\n    \"externalRef\": \"FIJA-42\",\n    \"customer\": {\n      \"name\": \"Juan Pérez\",\n      \"phone\": \"+59891234567\",\n      \"email\": null\n    },\n    \"owned\": true,\n    \"nextOccurrence\": \"2026-09-15\",\n    \"skippedDates\": [\n      \"2026-09-22\"\n    ],\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n  },\n  \"skippedDate\": \"2026-09-22\",\n  \"cancelledBookingId\": null,\n  \"alreadySkipped\": false\n}"},{"name":"201 · Fecha salteada.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/exceptions","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","exceptions"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Inserta la excepción (la serie sigue) y, si la ocurrencia ya estaba materializada, la cancela con su evento. Emite `occupancy.changed` liberando ese día. Repetir la misma fecha responde 200 (`alreadySkipped: true`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-22\"\n}","options":{"raw":{"language":"json"}}}},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"recurringBooking\": {\n    \"id\": \"8b7c6d5e-4f3a-4b2c-9d1e-0f9a8b7c6d5e\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"courtName\": \"Cancha 1\",\n    \"kind\": \"COURT\",\n    \"categoryId\": null,\n    \"resourceNoun\": \"COURT\",\n    \"startDate\": \"2026-09-15\",\n    \"endDate\": null,\n    \"startTime\": \"20:00\",\n    \"endTime\": \"21:30\",\n    \"durationMinutes\": 90,\n    \"frequency\": \"weekly\",\n    \"status\": \"ACTIVE\",\n    \"type\": \"normal\",\n    \"price\": 1400,\n    \"timezone\": \"America/Montevideo\",\n    \"externalRef\": \"FIJA-42\",\n    \"customer\": {\n      \"name\": \"Juan Pérez\",\n      \"phone\": \"+59891234567\",\n      \"email\": null\n    },\n    \"owned\": true,\n    \"nextOccurrence\": \"2026-09-15\",\n    \"skippedDates\": [\n      \"2026-09-22\"\n    ],\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n  },\n  \"skippedDate\": \"2026-09-22\",\n  \"cancelledBookingId\": null,\n  \"alreadySkipped\": false\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / DATE_IN_PAST","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/exceptions","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","exceptions"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Inserta la excepción (la serie sigue) y, si la ocurrencia ya estaba materializada, la cancela con su evento. Emite `occupancy.changed` liberando ese día. Repetir la misma fecha responde 200 (`alreadySkipped: true`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-22\"\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/exceptions","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","exceptions"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Inserta la excepción (la serie sigue) y, si la ocurrencia ya estaba materializada, la cancela con su evento. Emite `occupancy.changed` liberando ese día. Repetir la misma fecha responde 200 (`alreadySkipped: true`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-22\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED / RECURRING_NOT_OWNED_BY_CLIENT","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/exceptions","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","exceptions"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Inserta la excepción (la serie sigue) y, si la ocurrencia ya estaba materializada, la cancela con su evento. Emite `occupancy.changed` liberando ese día. Repetir la misma fecha responde 200 (`alreadySkipped: true`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-22\"\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · RECURRING_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/exceptions","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","exceptions"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Inserta la excepción (la serie sigue) y, si la ocurrencia ya estaba materializada, la cancela con su evento. Emite `occupancy.changed` liberando ese día. Repetir la misma fecha responde 200 (`alreadySkipped: true`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-22\"\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva fija no existe o no es de este club.\",\n  \"code\": \"RECURRING_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · RECURRING_ALREADY_CANCELLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/exceptions","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","exceptions"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Inserta la excepción (la serie sigue) y, si la ocurrencia ya estaba materializada, la cancela con su evento. Emite `occupancy.changed` liberando ese día. Repetir la misma fecha responde 200 (`alreadySkipped: true`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-22\"\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva fija ya está cancelada.\",\n  \"code\": \"RECURRING_ALREADY_CANCELLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/exceptions","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","exceptions"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Inserta la excepción (la serie sigue) y, si la ocurrencia ya estaba materializada, la cancela con su evento. Emite `occupancy.changed` liberando ese día. Repetir la misma fecha responde 200 (`alreadySkipped: true`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-22\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/exceptions","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","exceptions"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Inserta la excepción (la serie sigue) y, si la ocurrencia ya estaba materializada, la cancela con su evento. Emite `occupancy.changed` liberando ese día. Repetir la misma fecha responde 200 (`alreadySkipped: true`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-22\"\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/exceptions","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","exceptions"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Inserta la excepción (la serie sigue) y, si la ocurrencia ya estaba materializada, la cancela con su evento. Emite `occupancy.changed` liberando ese día. Repetir la misma fecha responde 200 (`alreadySkipped: true`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-22\"\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/exceptions","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","exceptions"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Inserta la excepción (la serie sigue) y, si la ocurrencia ya estaba materializada, la cancela con su evento. Emite `occupancy.changed` liberando ese día. Repetir la misma fecha responde 200 (`alreadySkipped: true`). Sólo series propias (o `canManageAllBookings`). Consume cuota de escritura.\n\nScope: `recurring:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"date\": \"2026-09-22\"\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Las fechas de una fija en un rango (listRecurringBookingOccurrences)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/occurrences","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","occurrences"],"query":[{"key":"from","value":"2026-10-01","description":"Primer día del rango (`YYYY-MM-DD` naive del club). Default: hoy en el club.","disabled":true},{"key":"to","value":"2026-10-31","description":"Último día del rango (inclusive). Default: `min(endDate, from + 90 días)`. Como mucho 366 días desde `from`.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Las ocurrencias de la serie en `[from, to]`, pasadas y futuras: la cadencia proyectada (la misma del detector de conflictos: `monthly` anclada al día original, sin fin respetado) cruzada con las fechas salteadas (`SKIPPED`) y con las ocurrencias ya materializadas como reservas, cuyo `status` real (`PENDING` / `CONFIRMED` / `CANCELLED` / `ATTENDED` / `NO_SHOW`) pisa la proyección. `PROJECTED` = fecha de la cadencia sin fila todavía (más allá del horizonte de 30 días del cron; una pasada sin fila es una que el cron no llegó a crear por un conflicto). Una serie cancelada no proyecta nada: quedan sólo sus filas materializadas. `bookingId` sólo en series propias o con `canManageAllBookings` (la misma regla que `GET /bookings/{id}` sobre una reserva ajena; no la de `/occupancy`, que sólo etiqueta lo creado por esta integración). Es lo que necesita un sistema de cuotas (\"las 4 fechas de octubre\"). Sin PII, sin ETag, no emite eventos.\n\nScope: `recurring:read`."},"response":[{"name":"200 · Las fechas en el rango.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/occurrences","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","occurrences"],"query":[{"key":"from","value":"2026-10-01","description":"Primer día del rango (`YYYY-MM-DD` naive del club). Default: hoy en el club.","disabled":true},{"key":"to","value":"2026-10-31","description":"Último día del rango (inclusive). Default: `min(endDate, from + 90 días)`. Como mucho 366 días desde `from`.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Las ocurrencias de la serie en `[from, to]`, pasadas y futuras: la cadencia proyectada (la misma del detector de conflictos: `monthly` anclada al día original, sin fin respetado) cruzada con las fechas salteadas (`SKIPPED`) y con las ocurrencias ya materializadas como reservas, cuyo `status` real (`PENDING` / `CONFIRMED` / `CANCELLED` / `ATTENDED` / `NO_SHOW`) pisa la proyección. `PROJECTED` = fecha de la cadencia sin fila todavía (más allá del horizonte de 30 días del cron; una pasada sin fila es una que el cron no llegó a crear por un conflicto). Una serie cancelada no proyecta nada: quedan sólo sus filas materializadas. `bookingId` sólo en series propias o con `canManageAllBookings` (la misma regla que `GET /bookings/{id}` sobre una reserva ajena; no la de `/occupancy`, que sólo etiqueta lo creado por esta integración). Es lo que necesita un sistema de cuotas (\"las 4 fechas de octubre\"). Sin PII, sin ETag, no emite eventos.\n\nScope: `recurring:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"recurringId\": \"8b7c6d5e-4f3a-4b2c-9d1e-0f9a8b7c6d5e\",\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"from\": \"2026-10-01\",\n  \"to\": \"2026-10-31\",\n  \"timezone\": \"America/Montevideo\",\n  \"occurrences\": [\n    {\n      \"date\": \"2026-10-06\",\n      \"startTime\": \"20:00\",\n      \"endTime\": \"21:30\",\n      \"status\": \"ATTENDED\",\n      \"bookingId\": \"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d\"\n    },\n    {\n      \"date\": \"2026-10-13\",\n      \"startTime\": \"20:00\",\n      \"endTime\": \"21:30\",\n      \"status\": \"CONFIRMED\",\n      \"bookingId\": \"2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e\"\n    },\n    {\n      \"date\": \"2026-10-20\",\n      \"startTime\": \"20:00\",\n      \"endTime\": \"21:30\",\n      \"status\": \"SKIPPED\",\n      \"bookingId\": null\n    },\n    {\n      \"date\": \"2026-10-27\",\n      \"startTime\": \"20:00\",\n      \"endTime\": \"21:30\",\n      \"status\": \"PROJECTED\",\n      \"bookingId\": null\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/occurrences","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","occurrences"],"query":[{"key":"from","value":"2026-10-01","description":"Primer día del rango (`YYYY-MM-DD` naive del club). Default: hoy en el club.","disabled":true},{"key":"to","value":"2026-10-31","description":"Último día del rango (inclusive). Default: `min(endDate, from + 90 días)`. Como mucho 366 días desde `from`.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Las ocurrencias de la serie en `[from, to]`, pasadas y futuras: la cadencia proyectada (la misma del detector de conflictos: `monthly` anclada al día original, sin fin respetado) cruzada con las fechas salteadas (`SKIPPED`) y con las ocurrencias ya materializadas como reservas, cuyo `status` real (`PENDING` / `CONFIRMED` / `CANCELLED` / `ATTENDED` / `NO_SHOW`) pisa la proyección. `PROJECTED` = fecha de la cadencia sin fila todavía (más allá del horizonte de 30 días del cron; una pasada sin fila es una que el cron no llegó a crear por un conflicto). Una serie cancelada no proyecta nada: quedan sólo sus filas materializadas. `bookingId` sólo en series propias o con `canManageAllBookings` (la misma regla que `GET /bookings/{id}` sobre una reserva ajena; no la de `/occupancy`, que sólo etiqueta lo creado por esta integración). Es lo que necesita un sistema de cuotas (\"las 4 fechas de octubre\"). Sin PII, sin ETag, no emite eventos.\n\nScope: `recurring:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/occurrences","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","occurrences"],"query":[{"key":"from","value":"2026-10-01","description":"Primer día del rango (`YYYY-MM-DD` naive del club). Default: hoy en el club.","disabled":true},{"key":"to","value":"2026-10-31","description":"Último día del rango (inclusive). Default: `min(endDate, from + 90 días)`. Como mucho 366 días desde `from`.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Las ocurrencias de la serie en `[from, to]`, pasadas y futuras: la cadencia proyectada (la misma del detector de conflictos: `monthly` anclada al día original, sin fin respetado) cruzada con las fechas salteadas (`SKIPPED`) y con las ocurrencias ya materializadas como reservas, cuyo `status` real (`PENDING` / `CONFIRMED` / `CANCELLED` / `ATTENDED` / `NO_SHOW`) pisa la proyección. `PROJECTED` = fecha de la cadencia sin fila todavía (más allá del horizonte de 30 días del cron; una pasada sin fila es una que el cron no llegó a crear por un conflicto). Una serie cancelada no proyecta nada: quedan sólo sus filas materializadas. `bookingId` sólo en series propias o con `canManageAllBookings` (la misma regla que `GET /bookings/{id}` sobre una reserva ajena; no la de `/occupancy`, que sólo etiqueta lo creado por esta integración). Es lo que necesita un sistema de cuotas (\"las 4 fechas de octubre\"). Sin PII, sin ETag, no emite eventos.\n\nScope: `recurring:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/occurrences","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","occurrences"],"query":[{"key":"from","value":"2026-10-01","description":"Primer día del rango (`YYYY-MM-DD` naive del club). Default: hoy en el club.","disabled":true},{"key":"to","value":"2026-10-31","description":"Último día del rango (inclusive). Default: `min(endDate, from + 90 días)`. Como mucho 366 días desde `from`.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Las ocurrencias de la serie en `[from, to]`, pasadas y futuras: la cadencia proyectada (la misma del detector de conflictos: `monthly` anclada al día original, sin fin respetado) cruzada con las fechas salteadas (`SKIPPED`) y con las ocurrencias ya materializadas como reservas, cuyo `status` real (`PENDING` / `CONFIRMED` / `CANCELLED` / `ATTENDED` / `NO_SHOW`) pisa la proyección. `PROJECTED` = fecha de la cadencia sin fila todavía (más allá del horizonte de 30 días del cron; una pasada sin fila es una que el cron no llegó a crear por un conflicto). Una serie cancelada no proyecta nada: quedan sólo sus filas materializadas. `bookingId` sólo en series propias o con `canManageAllBookings` (la misma regla que `GET /bookings/{id}` sobre una reserva ajena; no la de `/occupancy`, que sólo etiqueta lo creado por esta integración). Es lo que necesita un sistema de cuotas (\"las 4 fechas de octubre\"). Sin PII, sin ETag, no emite eventos.\n\nScope: `recurring:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · RECURRING_NOT_FOUND","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/occurrences","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","occurrences"],"query":[{"key":"from","value":"2026-10-01","description":"Primer día del rango (`YYYY-MM-DD` naive del club). Default: hoy en el club.","disabled":true},{"key":"to","value":"2026-10-31","description":"Último día del rango (inclusive). Default: `min(endDate, from + 90 días)`. Como mucho 366 días desde `from`.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Las ocurrencias de la serie en `[from, to]`, pasadas y futuras: la cadencia proyectada (la misma del detector de conflictos: `monthly` anclada al día original, sin fin respetado) cruzada con las fechas salteadas (`SKIPPED`) y con las ocurrencias ya materializadas como reservas, cuyo `status` real (`PENDING` / `CONFIRMED` / `CANCELLED` / `ATTENDED` / `NO_SHOW`) pisa la proyección. `PROJECTED` = fecha de la cadencia sin fila todavía (más allá del horizonte de 30 días del cron; una pasada sin fila es una que el cron no llegó a crear por un conflicto). Una serie cancelada no proyecta nada: quedan sólo sus filas materializadas. `bookingId` sólo en series propias o con `canManageAllBookings` (la misma regla que `GET /bookings/{id}` sobre una reserva ajena; no la de `/occupancy`, que sólo etiqueta lo creado por esta integración). Es lo que necesita un sistema de cuotas (\"las 4 fechas de octubre\"). Sin PII, sin ETag, no emite eventos.\n\nScope: `recurring:read`."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva fija no existe o no es de este club.\",\n  \"code\": \"RECURRING_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/occurrences","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","occurrences"],"query":[{"key":"from","value":"2026-10-01","description":"Primer día del rango (`YYYY-MM-DD` naive del club). Default: hoy en el club.","disabled":true},{"key":"to","value":"2026-10-31","description":"Último día del rango (inclusive). Default: `min(endDate, from + 90 días)`. Como mucho 366 días desde `from`.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Las ocurrencias de la serie en `[from, to]`, pasadas y futuras: la cadencia proyectada (la misma del detector de conflictos: `monthly` anclada al día original, sin fin respetado) cruzada con las fechas salteadas (`SKIPPED`) y con las ocurrencias ya materializadas como reservas, cuyo `status` real (`PENDING` / `CONFIRMED` / `CANCELLED` / `ATTENDED` / `NO_SHOW`) pisa la proyección. `PROJECTED` = fecha de la cadencia sin fila todavía (más allá del horizonte de 30 días del cron; una pasada sin fila es una que el cron no llegó a crear por un conflicto). Una serie cancelada no proyecta nada: quedan sólo sus filas materializadas. `bookingId` sólo en series propias o con `canManageAllBookings` (la misma regla que `GET /bookings/{id}` sobre una reserva ajena; no la de `/occupancy`, que sólo etiqueta lo creado por esta integración). Es lo que necesita un sistema de cuotas (\"las 4 fechas de octubre\"). Sin PII, sin ETag, no emite eventos.\n\nScope: `recurring:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/occurrences","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","occurrences"],"query":[{"key":"from","value":"2026-10-01","description":"Primer día del rango (`YYYY-MM-DD` naive del club). Default: hoy en el club.","disabled":true},{"key":"to","value":"2026-10-31","description":"Último día del rango (inclusive). Default: `min(endDate, from + 90 días)`. Como mucho 366 días desde `from`.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Las ocurrencias de la serie en `[from, to]`, pasadas y futuras: la cadencia proyectada (la misma del detector de conflictos: `monthly` anclada al día original, sin fin respetado) cruzada con las fechas salteadas (`SKIPPED`) y con las ocurrencias ya materializadas como reservas, cuyo `status` real (`PENDING` / `CONFIRMED` / `CANCELLED` / `ATTENDED` / `NO_SHOW`) pisa la proyección. `PROJECTED` = fecha de la cadencia sin fila todavía (más allá del horizonte de 30 días del cron; una pasada sin fila es una que el cron no llegó a crear por un conflicto). Una serie cancelada no proyecta nada: quedan sólo sus filas materializadas. `bookingId` sólo en series propias o con `canManageAllBookings` (la misma regla que `GET /bookings/{id}` sobre una reserva ajena; no la de `/occupancy`, que sólo etiqueta lo creado por esta integración). Es lo que necesita un sistema de cuotas (\"las 4 fechas de octubre\"). Sin PII, sin ETag, no emite eventos.\n\nScope: `recurring:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/recurring-bookings/:id/occurrences","host":["{{baseUrl}}"],"path":["recurring-bookings",":id","occurrences"],"query":[{"key":"from","value":"2026-10-01","description":"Primer día del rango (`YYYY-MM-DD` naive del club). Default: hoy en el club.","disabled":true},{"key":"to","value":"2026-10-31","description":"Último día del rango (inclusive). Default: `min(endDate, from + 90 días)`. Como mucho 366 días desde `from`.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la serie de fijas."}]},"description":"Las ocurrencias de la serie en `[from, to]`, pasadas y futuras: la cadencia proyectada (la misma del detector de conflictos: `monthly` anclada al día original, sin fin respetado) cruzada con las fechas salteadas (`SKIPPED`) y con las ocurrencias ya materializadas como reservas, cuyo `status` real (`PENDING` / `CONFIRMED` / `CANCELLED` / `ATTENDED` / `NO_SHOW`) pisa la proyección. `PROJECTED` = fecha de la cadencia sin fila todavía (más allá del horizonte de 30 días del cron; una pasada sin fila es una que el cron no llegó a crear por un conflicto). Una serie cancelada no proyecta nada: quedan sólo sus filas materializadas. `bookingId` sólo en series propias o con `canManageAllBookings` (la misma regla que `GET /bookings/{id}` sobre una reserva ajena; no la de `/occupancy`, que sólo etiqueta lo creado por esta integración). Es lo que necesita un sistema de cuotas (\"las 4 fechas de octubre\"). Sin PII, sin ETag, no emite eventos.\n\nScope: `recurring:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]}]},{"name":"Torneos","description":"Torneos del club: estructura del evento, grupos, cuadro, cronograma y resultados. Las parejas, siempre anónimas; la inscripción no se hace por API.","item":[{"name":"Listar torneos (listTournaments)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por status de la categoría.","disabled":true},{"key":"from","value":"2026-10-01","description":"Torneos cuya fecha de inicio es ≥ `from` (`YYYY-MM-DD`).","disabled":true},{"key":"to","value":"2026-12-31","description":"Torneos cuya fecha de inicio es ≤ `to` (`YYYY-MM-DD`).","disabled":true},{"key":"eventId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las categorías de este evento.","disabled":true}]},"description":"Categorías (filas de `tournaments`) del club; `eventId` agrupa las que forman un mismo evento. Orden: fecha de inicio desc, alta desc. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"response":[{"name":"200 · Página de categorías.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por status de la categoría.","disabled":true},{"key":"from","value":"2026-10-01","description":"Torneos cuya fecha de inicio es ≥ `from` (`YYYY-MM-DD`).","disabled":true},{"key":"to","value":"2026-12-31","description":"Torneos cuya fecha de inicio es ≤ `to` (`YYYY-MM-DD`).","disabled":true},{"key":"eventId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las categorías de este evento.","disabled":true}]},"description":"Categorías (filas de `tournaments`) del club; `eventId` agrupa las que forman un mismo evento. Orden: fecha de inicio desc, alta desc. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"tournaments\": [\n    {\n      \"id\": \"9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d\",\n      \"eventId\": \"7a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"clubId\": \"3f1c9a52-7d0e-4b6a-9c11-2a4f8e6d5b70\",\n      \"name\": \"Torneo Primavera — 4ta\",\n      \"sport\": \"PADEL\",\n      \"format\": \"CLASICO\",\n      \"status\": \"OPEN\",\n      \"category\": \"4ta\",\n      \"gender\": \"MALE\",\n      \"description\": null,\n      \"location\": null,\n      \"price\": 1200,\n      \"maxTeams\": 12,\n      \"registeredTeams\": 7,\n      \"startDate\": \"2026-10-16\",\n      \"endDate\": \"2026-10-18\",\n      \"createdAt\": \"2026-09-18 12:00:00\"\n    }\n  ],\n  \"total\": 1,\n  \"limit\": 100,\n  \"offset\": 0\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por status de la categoría.","disabled":true},{"key":"from","value":"2026-10-01","description":"Torneos cuya fecha de inicio es ≥ `from` (`YYYY-MM-DD`).","disabled":true},{"key":"to","value":"2026-12-31","description":"Torneos cuya fecha de inicio es ≤ `to` (`YYYY-MM-DD`).","disabled":true},{"key":"eventId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las categorías de este evento.","disabled":true}]},"description":"Categorías (filas de `tournaments`) del club; `eventId` agrupa las que forman un mismo evento. Orden: fecha de inicio desc, alta desc. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por status de la categoría.","disabled":true},{"key":"from","value":"2026-10-01","description":"Torneos cuya fecha de inicio es ≥ `from` (`YYYY-MM-DD`).","disabled":true},{"key":"to","value":"2026-12-31","description":"Torneos cuya fecha de inicio es ≤ `to` (`YYYY-MM-DD`).","disabled":true},{"key":"eventId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las categorías de este evento.","disabled":true}]},"description":"Categorías (filas de `tournaments`) del club; `eventId` agrupa las que forman un mismo evento. Orden: fecha de inicio desc, alta desc. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por status de la categoría.","disabled":true},{"key":"from","value":"2026-10-01","description":"Torneos cuya fecha de inicio es ≥ `from` (`YYYY-MM-DD`).","disabled":true},{"key":"to","value":"2026-12-31","description":"Torneos cuya fecha de inicio es ≤ `to` (`YYYY-MM-DD`).","disabled":true},{"key":"eventId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las categorías de este evento.","disabled":true}]},"description":"Categorías (filas de `tournaments`) del club; `eventId` agrupa las que forman un mismo evento. Orden: fecha de inicio desc, alta desc. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por status de la categoría.","disabled":true},{"key":"from","value":"2026-10-01","description":"Torneos cuya fecha de inicio es ≥ `from` (`YYYY-MM-DD`).","disabled":true},{"key":"to","value":"2026-12-31","description":"Torneos cuya fecha de inicio es ≤ `to` (`YYYY-MM-DD`).","disabled":true},{"key":"eventId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las categorías de este evento.","disabled":true}]},"description":"Categorías (filas de `tournaments`) del club; `eventId` agrupa las que forman un mismo evento. Orden: fecha de inicio desc, alta desc. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por status de la categoría.","disabled":true},{"key":"from","value":"2026-10-01","description":"Torneos cuya fecha de inicio es ≥ `from` (`YYYY-MM-DD`).","disabled":true},{"key":"to","value":"2026-12-31","description":"Torneos cuya fecha de inicio es ≤ `to` (`YYYY-MM-DD`).","disabled":true},{"key":"eventId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las categorías de este evento.","disabled":true}]},"description":"Categorías (filas de `tournaments`) del club; `eventId` agrupa las que forman un mismo evento. Orden: fecha de inicio desc, alta desc. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por status de la categoría.","disabled":true},{"key":"from","value":"2026-10-01","description":"Torneos cuya fecha de inicio es ≥ `from` (`YYYY-MM-DD`).","disabled":true},{"key":"to","value":"2026-12-31","description":"Torneos cuya fecha de inicio es ≤ `to` (`YYYY-MM-DD`).","disabled":true},{"key":"eventId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo las categorías de este evento.","disabled":true}]},"description":"Categorías (filas de `tournaments`) del club; `eventId` agrupa las que forman un mismo evento. Orden: fecha de inicio desc, alta desc. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Crear un evento con sus categorías (createTournament)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"]},"description":"Espejo de `POST /admin/tournaments`: una fila por (género, categoría), todas `OPEN` y con el mismo `eventId`. Mismas validaciones del panel (fechas parseables, sin variante repetida → 400 VALIDATION). Audit `TOURNAMENT_CREATED` por categoría. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Torneo Primavera\",\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"4ta\",\n        \"5ta\"\n      ],\n      \"startDate\": \"2026-10-16\",\n      \"endDate\": \"2026-10-18\",\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"201 · Creado.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"]},"description":"Espejo de `POST /admin/tournaments`: una fila por (género, categoría), todas `OPEN` y con el mismo `eventId`. Mismas validaciones del panel (fechas parseables, sin variante repetida → 400 VALIDATION). Audit `TOURNAMENT_CREATED` por categoría. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Torneo Primavera\",\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"4ta\",\n        \"5ta\"\n      ],\n      \"startDate\": \"2026-10-16\",\n      \"endDate\": \"2026-10-18\",\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"eventId\": \"7a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n  \"tournaments\": [\n    {\n      \"id\": \"9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d\",\n      \"eventId\": \"7a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"clubId\": \"3f1c9a52-7d0e-4b6a-9c11-2a4f8e6d5b70\",\n      \"name\": \"Torneo Primavera — 4ta\",\n      \"sport\": \"PADEL\",\n      \"format\": \"CLASICO\",\n      \"status\": \"OPEN\",\n      \"category\": \"4ta\",\n      \"gender\": \"MALE\",\n      \"description\": null,\n      \"location\": null,\n      \"price\": 1200,\n      \"maxTeams\": 12,\n      \"registeredTeams\": 7,\n      \"startDate\": \"2026-10-16\",\n      \"endDate\": \"2026-10-18\",\n      \"createdAt\": \"2026-09-18 12:00:00\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"]},"description":"Espejo de `POST /admin/tournaments`: una fila por (género, categoría), todas `OPEN` y con el mismo `eventId`. Mismas validaciones del panel (fechas parseables, sin variante repetida → 400 VALIDATION). Audit `TOURNAMENT_CREATED` por categoría. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Torneo Primavera\",\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"4ta\",\n        \"5ta\"\n      ],\n      \"startDate\": \"2026-10-16\",\n      \"endDate\": \"2026-10-18\",\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"]},"description":"Espejo de `POST /admin/tournaments`: una fila por (género, categoría), todas `OPEN` y con el mismo `eventId`. Mismas validaciones del panel (fechas parseables, sin variante repetida → 400 VALIDATION). Audit `TOURNAMENT_CREATED` por categoría. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Torneo Primavera\",\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"4ta\",\n        \"5ta\"\n      ],\n      \"startDate\": \"2026-10-16\",\n      \"endDate\": \"2026-10-18\",\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"]},"description":"Espejo de `POST /admin/tournaments`: una fila por (género, categoría), todas `OPEN` y con el mismo `eventId`. Mismas validaciones del panel (fechas parseables, sin variante repetida → 400 VALIDATION). Audit `TOURNAMENT_CREATED` por categoría. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Torneo Primavera\",\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"4ta\",\n        \"5ta\"\n      ],\n      \"startDate\": \"2026-10-16\",\n      \"endDate\": \"2026-10-18\",\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"]},"description":"Espejo de `POST /admin/tournaments`: una fila por (género, categoría), todas `OPEN` y con el mismo `eventId`. Mismas validaciones del panel (fechas parseables, sin variante repetida → 400 VALIDATION). Audit `TOURNAMENT_CREATED` por categoría. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Torneo Primavera\",\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"4ta\",\n        \"5ta\"\n      ],\n      \"startDate\": \"2026-10-16\",\n      \"endDate\": \"2026-10-18\",\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"]},"description":"Espejo de `POST /admin/tournaments`: una fila por (género, categoría), todas `OPEN` y con el mismo `eventId`. Mismas validaciones del panel (fechas parseables, sin variante repetida → 400 VALIDATION). Audit `TOURNAMENT_CREATED` por categoría. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Torneo Primavera\",\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"4ta\",\n        \"5ta\"\n      ],\n      \"startDate\": \"2026-10-16\",\n      \"endDate\": \"2026-10-18\",\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"]},"description":"Espejo de `POST /admin/tournaments`: una fila por (género, categoría), todas `OPEN` y con el mismo `eventId`. Mismas validaciones del panel (fechas parseables, sin variante repetida → 400 VALIDATION). Audit `TOURNAMENT_CREATED` por categoría. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Torneo Primavera\",\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"4ta\",\n        \"5ta\"\n      ],\n      \"startDate\": \"2026-10-16\",\n      \"endDate\": \"2026-10-18\",\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments","host":["{{baseUrl}}"],"path":["tournaments"]},"description":"Espejo de `POST /admin/tournaments`: una fila por (género, categoría), todas `OPEN` y con el mismo `eventId`. Mismas validaciones del panel (fechas parseables, sin variante repetida → 400 VALIDATION). Audit `TOURNAMENT_CREATED` por categoría. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"name\": \"Torneo Primavera\",\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"4ta\",\n        \"5ta\"\n      ],\n      \"startDate\": \"2026-10-16\",\n      \"endDate\": \"2026-10-18\",\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Detalle de un torneo (getTournament)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"La categoría con sus hermanas del mismo evento, las parejas anónimas (`TeamDto`), los grupos, todos los partidos (el cuadro son los de `phase != GROUP`) y el podio (`[]` hasta que se finaliza). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"response":[{"name":"200 · El torneo.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"La categoría con sus hermanas del mismo evento, las parejas anónimas (`TeamDto`), los grupos, todos los partidos (el cuadro son los de `phase != GROUP`) y el podio (`[]` hasta que se finaliza). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"tournament\": {\n    \"id\": \"9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d\",\n    \"eventId\": \"7a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"clubId\": \"3f1c9a52-7d0e-4b6a-9c11-2a4f8e6d5b70\",\n    \"name\": \"Torneo Primavera — 4ta\",\n    \"sport\": \"PADEL\",\n    \"format\": \"CLASICO\",\n    \"status\": \"OPEN\",\n    \"category\": \"4ta\",\n    \"gender\": \"MALE\",\n    \"description\": null,\n    \"location\": null,\n    \"price\": 1200,\n    \"maxTeams\": 12,\n    \"registeredTeams\": 7,\n    \"startDate\": \"2026-10-16\",\n    \"endDate\": \"2026-10-18\",\n    \"createdAt\": \"2026-09-18 12:00:00\"\n  },\n  \"categories\": [\n    {\n      \"id\": \"9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d\",\n      \"eventId\": \"7a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"clubId\": \"3f1c9a52-7d0e-4b6a-9c11-2a4f8e6d5b70\",\n      \"name\": \"Torneo Primavera — 4ta\",\n      \"sport\": \"PADEL\",\n      \"format\": \"CLASICO\",\n      \"status\": \"OPEN\",\n      \"category\": \"4ta\",\n      \"gender\": \"MALE\",\n      \"description\": null,\n      \"location\": null,\n      \"price\": 1200,\n      \"maxTeams\": 12,\n      \"registeredTeams\": 7,\n      \"startDate\": \"2026-10-16\",\n      \"endDate\": \"2026-10-18\",\n      \"createdAt\": \"2026-09-18 12:00:00\"\n    }\n  ],\n  \"teams\": [\n    {\n      \"id\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"label\": \"Los Halcones\",\n      \"teamName\": \"Los Halcones\",\n      \"seed\": 1,\n      \"groupId\": \"4d3c2b1a-aaaa-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"status\": \"REGISTERED\",\n      \"paid\": true,\n      \"registeredAt\": \"2026-09-18 12:05:00\"\n    },\n    {\n      \"id\": \"1a2b3c4d-2222-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"label\": \"Pareja #2\",\n      \"teamName\": null,\n      \"seed\": null,\n      \"groupId\": \"4d3c2b1a-aaaa-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"status\": \"REGISTERED\",\n      \"paid\": false,\n      \"registeredAt\": \"2026-09-18 12:07:00\"\n    }\n  ],\n  \"groups\": [\n    {\n      \"id\": \"4d3c2b1a-aaaa-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"name\": \"A\",\n      \"timeSlot\": \"SATURDAY_MORNING\",\n      \"teamIds\": [\n        \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n        \"1a2b3c4d-2222-4a7b-8c9d-0e1f2a3b4c5d\"\n      ]\n    }\n  ],\n  \"matches\": [\n    {\n      \"id\": \"6f5e4d3c-bbbb-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"tournamentId\": \"9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d\",\n      \"phase\": \"GROUP\",\n      \"round\": 1,\n      \"groupId\": \"4d3c2b1a-aaaa-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"matchOrder\": 1,\n      \"team1Id\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"team2Id\": \"1a2b3c4d-2222-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"team1Label\": \"Los Halcones\",\n      \"team2Label\": \"Pareja #2\",\n      \"team1FromMatchId\": null,\n      \"team1FromOutcome\": null,\n      \"team2FromMatchId\": null,\n      \"team2FromOutcome\": null,\n      \"status\": \"COMPLETED\",\n      \"winnerTeamId\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"isWalkover\": false,\n      \"walkoverTeamId\": null,\n      \"sets\": [\n        {\n          \"team1\": 6,\n          \"team2\": 3\n        },\n        {\n          \"team1\": 7,\n          \"team2\": 5\n        }\n      ],\n      \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n      \"scheduledAt\": \"2026-10-17T09:00:00\"\n    }\n  ],\n  \"podium\": []\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"La categoría con sus hermanas del mismo evento, las parejas anónimas (`TeamDto`), los grupos, todos los partidos (el cuadro son los de `phase != GROUP`) y el podio (`[]` hasta que se finaliza). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"La categoría con sus hermanas del mismo evento, las parejas anónimas (`TeamDto`), los grupos, todos los partidos (el cuadro son los de `phase != GROUP`) y el podio (`[]` hasta que se finaliza). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"La categoría con sus hermanas del mismo evento, las parejas anónimas (`TeamDto`), los grupos, todos los partidos (el cuadro son los de `phase != GROUP`) y el podio (`[]` hasta que se finaliza). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · TOURNAMENT_NOT_FOUND","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"La categoría con sus hermanas del mismo evento, las parejas anónimas (`TeamDto`), los grupos, todos los partidos (el cuadro son los de `phase != GROUP`) y el podio (`[]` hasta que se finaliza). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo no existe o no es de este club.\",\n  \"code\": \"TOURNAMENT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"La categoría con sus hermanas del mismo evento, las parejas anónimas (`TeamDto`), los grupos, todos los partidos (el cuadro son los de `phase != GROUP`) y el podio (`[]` hasta que se finaliza). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"La categoría con sus hermanas del mismo evento, las parejas anónimas (`TeamDto`), los grupos, todos los partidos (el cuadro son los de `phase != GROUP`) y el podio (`[]` hasta que se finaliza). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"La categoría con sus hermanas del mismo evento, las parejas anónimas (`TeamDto`), los grupos, todos los partidos (el cuadro son los de `phase != GROUP`) y el podio (`[]` hasta que se finaliza). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Modificar un torneo (updateTournament)","request":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Nombre, descripción, lugar, fechas, cupo, precio y `status`. Las transiciones válidas son las de docs/enums.md (OPEN → CLOSED → GROUP_PHASE → ELIMINATION_PHASE → COMPLETED, CANCELLED desde cualquier no terminal, SCHEDULE_BUILDING → GROUP_PHASE, y la única hacia atrás: ELIMINATION_PHASE → GROUP_PHASE, que borra el cuadro y devuelve las parejas eliminadas al pool para poder regenerarlo); repetir el status actual es un no-op. Después aplican los guards del panel: CLOSED exige al menos una pareja, ELIMINATION_PHASE exige el cuadro generado, volver a GROUP_PHASE con eliminatorias jugadas responde 409 TOURNAMENT_ALREADY_PLAYED salvo `force: true` (que las borra y revierte su impacto en el nivel). `status: COMPLETED` es cerrar la categoría: el mismo op que `POST …/finalize` (podio, puntos Skalia, premios; exige la final jugada → si no, 400 TOURNAMENT_RULE_VIOLATION) y la respuesta suma `podium`. Los cambios de fase notifican a los inscriptos como lo hace el panel. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"CLOSED\"\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · El torneo actualizado (con `warnings` si arrancó la fase de grupos con parejas incompletas).","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Nombre, descripción, lugar, fechas, cupo, precio y `status`. Las transiciones válidas son las de docs/enums.md (OPEN → CLOSED → GROUP_PHASE → ELIMINATION_PHASE → COMPLETED, CANCELLED desde cualquier no terminal, SCHEDULE_BUILDING → GROUP_PHASE, y la única hacia atrás: ELIMINATION_PHASE → GROUP_PHASE, que borra el cuadro y devuelve las parejas eliminadas al pool para poder regenerarlo); repetir el status actual es un no-op. Después aplican los guards del panel: CLOSED exige al menos una pareja, ELIMINATION_PHASE exige el cuadro generado, volver a GROUP_PHASE con eliminatorias jugadas responde 409 TOURNAMENT_ALREADY_PLAYED salvo `force: true` (que las borra y revierte su impacto en el nivel). `status: COMPLETED` es cerrar la categoría: el mismo op que `POST …/finalize` (podio, puntos Skalia, premios; exige la final jugada → si no, 400 TOURNAMENT_RULE_VIOLATION) y la respuesta suma `podium`. Los cambios de fase notifican a los inscriptos como lo hace el panel. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"CLOSED\"\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"tournament\": {\n    \"id\": \"9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d\",\n    \"eventId\": \"7a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"clubId\": \"3f1c9a52-7d0e-4b6a-9c11-2a4f8e6d5b70\",\n    \"name\": \"Torneo Primavera — 4ta\",\n    \"sport\": \"PADEL\",\n    \"format\": \"CLASICO\",\n    \"status\": \"OPEN\",\n    \"category\": \"4ta\",\n    \"gender\": \"MALE\",\n    \"description\": null,\n    \"location\": null,\n    \"price\": 1200,\n    \"maxTeams\": 12,\n    \"registeredTeams\": 7,\n    \"startDate\": \"2026-10-16\",\n    \"endDate\": \"2026-10-18\",\n    \"createdAt\": \"2026-09-18 12:00:00\"\n  },\n  \"warnings\": []\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / TOURNAMENT_RULE_VIOLATION","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Nombre, descripción, lugar, fechas, cupo, precio y `status`. Las transiciones válidas son las de docs/enums.md (OPEN → CLOSED → GROUP_PHASE → ELIMINATION_PHASE → COMPLETED, CANCELLED desde cualquier no terminal, SCHEDULE_BUILDING → GROUP_PHASE, y la única hacia atrás: ELIMINATION_PHASE → GROUP_PHASE, que borra el cuadro y devuelve las parejas eliminadas al pool para poder regenerarlo); repetir el status actual es un no-op. Después aplican los guards del panel: CLOSED exige al menos una pareja, ELIMINATION_PHASE exige el cuadro generado, volver a GROUP_PHASE con eliminatorias jugadas responde 409 TOURNAMENT_ALREADY_PLAYED salvo `force: true` (que las borra y revierte su impacto en el nivel). `status: COMPLETED` es cerrar la categoría: el mismo op que `POST …/finalize` (podio, puntos Skalia, premios; exige la final jugada → si no, 400 TOURNAMENT_RULE_VIOLATION) y la respuesta suma `podium`. Los cambios de fase notifican a los inscriptos como lo hace el panel. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"CLOSED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Nombre, descripción, lugar, fechas, cupo, precio y `status`. Las transiciones válidas son las de docs/enums.md (OPEN → CLOSED → GROUP_PHASE → ELIMINATION_PHASE → COMPLETED, CANCELLED desde cualquier no terminal, SCHEDULE_BUILDING → GROUP_PHASE, y la única hacia atrás: ELIMINATION_PHASE → GROUP_PHASE, que borra el cuadro y devuelve las parejas eliminadas al pool para poder regenerarlo); repetir el status actual es un no-op. Después aplican los guards del panel: CLOSED exige al menos una pareja, ELIMINATION_PHASE exige el cuadro generado, volver a GROUP_PHASE con eliminatorias jugadas responde 409 TOURNAMENT_ALREADY_PLAYED salvo `force: true` (que las borra y revierte su impacto en el nivel). `status: COMPLETED` es cerrar la categoría: el mismo op que `POST …/finalize` (podio, puntos Skalia, premios; exige la final jugada → si no, 400 TOURNAMENT_RULE_VIOLATION) y la respuesta suma `podium`. Los cambios de fase notifican a los inscriptos como lo hace el panel. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"CLOSED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Nombre, descripción, lugar, fechas, cupo, precio y `status`. Las transiciones válidas son las de docs/enums.md (OPEN → CLOSED → GROUP_PHASE → ELIMINATION_PHASE → COMPLETED, CANCELLED desde cualquier no terminal, SCHEDULE_BUILDING → GROUP_PHASE, y la única hacia atrás: ELIMINATION_PHASE → GROUP_PHASE, que borra el cuadro y devuelve las parejas eliminadas al pool para poder regenerarlo); repetir el status actual es un no-op. Después aplican los guards del panel: CLOSED exige al menos una pareja, ELIMINATION_PHASE exige el cuadro generado, volver a GROUP_PHASE con eliminatorias jugadas responde 409 TOURNAMENT_ALREADY_PLAYED salvo `force: true` (que las borra y revierte su impacto en el nivel). `status: COMPLETED` es cerrar la categoría: el mismo op que `POST …/finalize` (podio, puntos Skalia, premios; exige la final jugada → si no, 400 TOURNAMENT_RULE_VIOLATION) y la respuesta suma `podium`. Los cambios de fase notifican a los inscriptos como lo hace el panel. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"CLOSED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · TOURNAMENT_NOT_FOUND","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Nombre, descripción, lugar, fechas, cupo, precio y `status`. Las transiciones válidas son las de docs/enums.md (OPEN → CLOSED → GROUP_PHASE → ELIMINATION_PHASE → COMPLETED, CANCELLED desde cualquier no terminal, SCHEDULE_BUILDING → GROUP_PHASE, y la única hacia atrás: ELIMINATION_PHASE → GROUP_PHASE, que borra el cuadro y devuelve las parejas eliminadas al pool para poder regenerarlo); repetir el status actual es un no-op. Después aplican los guards del panel: CLOSED exige al menos una pareja, ELIMINATION_PHASE exige el cuadro generado, volver a GROUP_PHASE con eliminatorias jugadas responde 409 TOURNAMENT_ALREADY_PLAYED salvo `force: true` (que las borra y revierte su impacto en el nivel). `status: COMPLETED` es cerrar la categoría: el mismo op que `POST …/finalize` (podio, puntos Skalia, premios; exige la final jugada → si no, 400 TOURNAMENT_RULE_VIOLATION) y la respuesta suma `podium`. Los cambios de fase notifican a los inscriptos como lo hace el panel. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"CLOSED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo no existe o no es de este club.\",\n  \"code\": \"TOURNAMENT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · TOURNAMENT_INVALID_TRANSITION / TOURNAMENT_ALREADY_PLAYED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Nombre, descripción, lugar, fechas, cupo, precio y `status`. Las transiciones válidas son las de docs/enums.md (OPEN → CLOSED → GROUP_PHASE → ELIMINATION_PHASE → COMPLETED, CANCELLED desde cualquier no terminal, SCHEDULE_BUILDING → GROUP_PHASE, y la única hacia atrás: ELIMINATION_PHASE → GROUP_PHASE, que borra el cuadro y devuelve las parejas eliminadas al pool para poder regenerarlo); repetir el status actual es un no-op. Después aplican los guards del panel: CLOSED exige al menos una pareja, ELIMINATION_PHASE exige el cuadro generado, volver a GROUP_PHASE con eliminatorias jugadas responde 409 TOURNAMENT_ALREADY_PLAYED salvo `force: true` (que las borra y revierte su impacto en el nivel). `status: COMPLETED` es cerrar la categoría: el mismo op que `POST …/finalize` (podio, puntos Skalia, premios; exige la final jugada → si no, 400 TOURNAMENT_RULE_VIOLATION) y la respuesta suma `podium`. Los cambios de fase notifican a los inscriptos como lo hace el panel. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"CLOSED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ese cambio de estado no está permitido desde el estado actual del torneo.\",\n  \"code\": \"TOURNAMENT_INVALID_TRANSITION\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Nombre, descripción, lugar, fechas, cupo, precio y `status`. Las transiciones válidas son las de docs/enums.md (OPEN → CLOSED → GROUP_PHASE → ELIMINATION_PHASE → COMPLETED, CANCELLED desde cualquier no terminal, SCHEDULE_BUILDING → GROUP_PHASE, y la única hacia atrás: ELIMINATION_PHASE → GROUP_PHASE, que borra el cuadro y devuelve las parejas eliminadas al pool para poder regenerarlo); repetir el status actual es un no-op. Después aplican los guards del panel: CLOSED exige al menos una pareja, ELIMINATION_PHASE exige el cuadro generado, volver a GROUP_PHASE con eliminatorias jugadas responde 409 TOURNAMENT_ALREADY_PLAYED salvo `force: true` (que las borra y revierte su impacto en el nivel). `status: COMPLETED` es cerrar la categoría: el mismo op que `POST …/finalize` (podio, puntos Skalia, premios; exige la final jugada → si no, 400 TOURNAMENT_RULE_VIOLATION) y la respuesta suma `podium`. Los cambios de fase notifican a los inscriptos como lo hace el panel. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"CLOSED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Nombre, descripción, lugar, fechas, cupo, precio y `status`. Las transiciones válidas son las de docs/enums.md (OPEN → CLOSED → GROUP_PHASE → ELIMINATION_PHASE → COMPLETED, CANCELLED desde cualquier no terminal, SCHEDULE_BUILDING → GROUP_PHASE, y la única hacia atrás: ELIMINATION_PHASE → GROUP_PHASE, que borra el cuadro y devuelve las parejas eliminadas al pool para poder regenerarlo); repetir el status actual es un no-op. Después aplican los guards del panel: CLOSED exige al menos una pareja, ELIMINATION_PHASE exige el cuadro generado, volver a GROUP_PHASE con eliminatorias jugadas responde 409 TOURNAMENT_ALREADY_PLAYED salvo `force: true` (que las borra y revierte su impacto en el nivel). `status: COMPLETED` es cerrar la categoría: el mismo op que `POST …/finalize` (podio, puntos Skalia, premios; exige la final jugada → si no, 400 TOURNAMENT_RULE_VIOLATION) y la respuesta suma `podium`. Los cambios de fase notifican a los inscriptos como lo hace el panel. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"CLOSED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Nombre, descripción, lugar, fechas, cupo, precio y `status`. Las transiciones válidas son las de docs/enums.md (OPEN → CLOSED → GROUP_PHASE → ELIMINATION_PHASE → COMPLETED, CANCELLED desde cualquier no terminal, SCHEDULE_BUILDING → GROUP_PHASE, y la única hacia atrás: ELIMINATION_PHASE → GROUP_PHASE, que borra el cuadro y devuelve las parejas eliminadas al pool para poder regenerarlo); repetir el status actual es un no-op. Después aplican los guards del panel: CLOSED exige al menos una pareja, ELIMINATION_PHASE exige el cuadro generado, volver a GROUP_PHASE con eliminatorias jugadas responde 409 TOURNAMENT_ALREADY_PLAYED salvo `force: true` (que las borra y revierte su impacto en el nivel). `status: COMPLETED` es cerrar la categoría: el mismo op que `POST …/finalize` (podio, puntos Skalia, premios; exige la final jugada → si no, 400 TOURNAMENT_RULE_VIOLATION) y la respuesta suma `podium`. Los cambios de fase notifican a los inscriptos como lo hace el panel. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"CLOSED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Nombre, descripción, lugar, fechas, cupo, precio y `status`. Las transiciones válidas son las de docs/enums.md (OPEN → CLOSED → GROUP_PHASE → ELIMINATION_PHASE → COMPLETED, CANCELLED desde cualquier no terminal, SCHEDULE_BUILDING → GROUP_PHASE, y la única hacia atrás: ELIMINATION_PHASE → GROUP_PHASE, que borra el cuadro y devuelve las parejas eliminadas al pool para poder regenerarlo); repetir el status actual es un no-op. Después aplican los guards del panel: CLOSED exige al menos una pareja, ELIMINATION_PHASE exige el cuadro generado, volver a GROUP_PHASE con eliminatorias jugadas responde 409 TOURNAMENT_ALREADY_PLAYED salvo `force: true` (que las borra y revierte su impacto en el nivel). `status: COMPLETED` es cerrar la categoría: el mismo op que `POST …/finalize` (podio, puntos Skalia, premios; exige la final jugada → si no, 400 TOURNAMENT_RULE_VIOLATION) y la respuesta suma `podium`. Los cambios de fase notifican a los inscriptos como lo hace el panel. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"status\": \"CLOSED\"\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Borrar o cancelar un torneo (deleteTournament)","request":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"query":[{"key":"force","value":"true","description":"`true` cancela el torneo (status CANCELLED, con el aviso a los inscriptos) cuando tiene parejas; sin él, 409.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin inscriptos: se borra como lo hace el panel (`deleted: true`). Con inscriptos: 409 TOURNAMENT_HAS_REGISTRATIONS salvo `?force=true`, que lo pasa a CANCELLED (`cancelled: true`, idempotente). Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"response":[{"name":"200 · Borrado o cancelado.","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"query":[{"key":"force","value":"true","description":"`true` cancela el torneo (status CANCELLED, con el aviso a los inscriptos) cuando tiene parejas; sin él, 409.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin inscriptos: se borra como lo hace el panel (`deleted: true`). Con inscriptos: 409 TOURNAMENT_HAS_REGISTRATIONS salvo `?force=true`, que lo pasa a CANCELLED (`cancelled: true`, idempotente). Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"tournament\": null,\n  \"deleted\": true,\n  \"cancelled\": false\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"query":[{"key":"force","value":"true","description":"`true` cancela el torneo (status CANCELLED, con el aviso a los inscriptos) cuando tiene parejas; sin él, 409.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin inscriptos: se borra como lo hace el panel (`deleted: true`). Con inscriptos: 409 TOURNAMENT_HAS_REGISTRATIONS salvo `?force=true`, que lo pasa a CANCELLED (`cancelled: true`, idempotente). Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"query":[{"key":"force","value":"true","description":"`true` cancela el torneo (status CANCELLED, con el aviso a los inscriptos) cuando tiene parejas; sin él, 409.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin inscriptos: se borra como lo hace el panel (`deleted: true`). Con inscriptos: 409 TOURNAMENT_HAS_REGISTRATIONS salvo `?force=true`, que lo pasa a CANCELLED (`cancelled: true`, idempotente). Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"query":[{"key":"force","value":"true","description":"`true` cancela el torneo (status CANCELLED, con el aviso a los inscriptos) cuando tiene parejas; sin él, 409.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin inscriptos: se borra como lo hace el panel (`deleted: true`). Con inscriptos: 409 TOURNAMENT_HAS_REGISTRATIONS salvo `?force=true`, que lo pasa a CANCELLED (`cancelled: true`, idempotente). Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · TOURNAMENT_NOT_FOUND","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"query":[{"key":"force","value":"true","description":"`true` cancela el torneo (status CANCELLED, con el aviso a los inscriptos) cuando tiene parejas; sin él, 409.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin inscriptos: se borra como lo hace el panel (`deleted: true`). Con inscriptos: 409 TOURNAMENT_HAS_REGISTRATIONS salvo `?force=true`, que lo pasa a CANCELLED (`cancelled: true`, idempotente). Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo no existe o no es de este club.\",\n  \"code\": \"TOURNAMENT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · TOURNAMENT_HAS_REGISTRATIONS / TOURNAMENT_INVALID_TRANSITION","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"query":[{"key":"force","value":"true","description":"`true` cancela el torneo (status CANCELLED, con el aviso a los inscriptos) cuando tiene parejas; sin él, 409.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin inscriptos: se borra como lo hace el panel (`deleted: true`). Con inscriptos: 409 TOURNAMENT_HAS_REGISTRATIONS salvo `?force=true`, que lo pasa a CANCELLED (`cancelled: true`, idempotente). Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo tiene parejas inscriptas. Repetí con force=true para cancelarlo.\",\n  \"code\": \"TOURNAMENT_HAS_REGISTRATIONS\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"query":[{"key":"force","value":"true","description":"`true` cancela el torneo (status CANCELLED, con el aviso a los inscriptos) cuando tiene parejas; sin él, 409.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin inscriptos: se borra como lo hace el panel (`deleted: true`). Con inscriptos: 409 TOURNAMENT_HAS_REGISTRATIONS salvo `?force=true`, que lo pasa a CANCELLED (`cancelled: true`, idempotente). Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"query":[{"key":"force","value":"true","description":"`true` cancela el torneo (status CANCELLED, con el aviso a los inscriptos) cuando tiene parejas; sin él, 409.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin inscriptos: se borra como lo hace el panel (`deleted: true`). Con inscriptos: 409 TOURNAMENT_HAS_REGISTRATIONS salvo `?force=true`, que lo pasa a CANCELLED (`cancelled: true`, idempotente). Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id","host":["{{baseUrl}}"],"path":["tournaments",":id"],"query":[{"key":"force","value":"true","description":"`true` cancela el torneo (status CANCELLED, con el aviso a los inscriptos) cuando tiene parejas; sin él, 409.","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin inscriptos: se borra como lo hace el panel (`deleted: true`). Con inscriptos: 409 TOURNAMENT_HAS_REGISTRATIONS salvo `?force=true`, que lo pasa a CANCELLED (`cancelled: true`, idempotente). Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Abrir más categorías en un evento (addTournamentCategories)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/categories","host":["{{baseUrl}}"],"path":["tournaments",":id","categories"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Suma categorías (filas OPEN) al evento de la categoría de la URL, con su mismo `eventId`: lo que el panel hace al editar la serie. Nombre (`\"<evento> — <categoría>\"`), deporte, descripción, lugar y club se heredan; fechas y precio también cuando la variante no los manda. Una (género, categoría) que ya existe en el evento es 409 TOURNAMENT_CATEGORY_EXISTS; una repetida dentro del body, 400 VALIDATION (mismo criterio que el alta). Un torneo legacy sin evento pasa a ser el evento (se le asigna su propio id). No renombra ni borra categorías (`DELETE /tournaments/{id}`). Audit TOURNAMENT_CREATED por fila. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"6ta\"\n      ],\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"201 · Creadas: sólo las categorías nuevas.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/categories","host":["{{baseUrl}}"],"path":["tournaments",":id","categories"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Suma categorías (filas OPEN) al evento de la categoría de la URL, con su mismo `eventId`: lo que el panel hace al editar la serie. Nombre (`\"<evento> — <categoría>\"`), deporte, descripción, lugar y club se heredan; fechas y precio también cuando la variante no los manda. Una (género, categoría) que ya existe en el evento es 409 TOURNAMENT_CATEGORY_EXISTS; una repetida dentro del body, 400 VALIDATION (mismo criterio que el alta). Un torneo legacy sin evento pasa a ser el evento (se le asigna su propio id). No renombra ni borra categorías (`DELETE /tournaments/{id}`). Audit TOURNAMENT_CREATED por fila. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"6ta\"\n      ],\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"eventId\": \"7a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n  \"tournaments\": [\n    {\n      \"id\": \"1a2b3c4d-2222-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"eventId\": \"7a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"clubId\": \"3f1c9a52-7d0e-4b6a-9c11-2a4f8e6d5b70\",\n      \"name\": \"Torneo Primavera — 6ta\",\n      \"sport\": \"PADEL\",\n      \"format\": \"CLASICO\",\n      \"status\": \"OPEN\",\n      \"category\": \"6ta\",\n      \"gender\": \"MALE\",\n      \"description\": null,\n      \"location\": null,\n      \"price\": 1200,\n      \"maxTeams\": 12,\n      \"registeredTeams\": 0,\n      \"startDate\": \"2026-10-16\",\n      \"endDate\": \"2026-10-18\",\n      \"createdAt\": \"2026-09-18 12:00:00\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/categories","host":["{{baseUrl}}"],"path":["tournaments",":id","categories"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Suma categorías (filas OPEN) al evento de la categoría de la URL, con su mismo `eventId`: lo que el panel hace al editar la serie. Nombre (`\"<evento> — <categoría>\"`), deporte, descripción, lugar y club se heredan; fechas y precio también cuando la variante no los manda. Una (género, categoría) que ya existe en el evento es 409 TOURNAMENT_CATEGORY_EXISTS; una repetida dentro del body, 400 VALIDATION (mismo criterio que el alta). Un torneo legacy sin evento pasa a ser el evento (se le asigna su propio id). No renombra ni borra categorías (`DELETE /tournaments/{id}`). Audit TOURNAMENT_CREATED por fila. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"6ta\"\n      ],\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/categories","host":["{{baseUrl}}"],"path":["tournaments",":id","categories"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Suma categorías (filas OPEN) al evento de la categoría de la URL, con su mismo `eventId`: lo que el panel hace al editar la serie. Nombre (`\"<evento> — <categoría>\"`), deporte, descripción, lugar y club se heredan; fechas y precio también cuando la variante no los manda. Una (género, categoría) que ya existe en el evento es 409 TOURNAMENT_CATEGORY_EXISTS; una repetida dentro del body, 400 VALIDATION (mismo criterio que el alta). Un torneo legacy sin evento pasa a ser el evento (se le asigna su propio id). No renombra ni borra categorías (`DELETE /tournaments/{id}`). Audit TOURNAMENT_CREATED por fila. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"6ta\"\n      ],\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/categories","host":["{{baseUrl}}"],"path":["tournaments",":id","categories"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Suma categorías (filas OPEN) al evento de la categoría de la URL, con su mismo `eventId`: lo que el panel hace al editar la serie. Nombre (`\"<evento> — <categoría>\"`), deporte, descripción, lugar y club se heredan; fechas y precio también cuando la variante no los manda. Una (género, categoría) que ya existe en el evento es 409 TOURNAMENT_CATEGORY_EXISTS; una repetida dentro del body, 400 VALIDATION (mismo criterio que el alta). Un torneo legacy sin evento pasa a ser el evento (se le asigna su propio id). No renombra ni borra categorías (`DELETE /tournaments/{id}`). Audit TOURNAMENT_CREATED por fila. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"6ta\"\n      ],\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · TOURNAMENT_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/categories","host":["{{baseUrl}}"],"path":["tournaments",":id","categories"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Suma categorías (filas OPEN) al evento de la categoría de la URL, con su mismo `eventId`: lo que el panel hace al editar la serie. Nombre (`\"<evento> — <categoría>\"`), deporte, descripción, lugar y club se heredan; fechas y precio también cuando la variante no los manda. Una (género, categoría) que ya existe en el evento es 409 TOURNAMENT_CATEGORY_EXISTS; una repetida dentro del body, 400 VALIDATION (mismo criterio que el alta). Un torneo legacy sin evento pasa a ser el evento (se le asigna su propio id). No renombra ni borra categorías (`DELETE /tournaments/{id}`). Audit TOURNAMENT_CREATED por fila. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"6ta\"\n      ],\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo no existe o no es de este club.\",\n  \"code\": \"TOURNAMENT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · TOURNAMENT_CATEGORY_EXISTS / TOURNAMENT_INVALID_TRANSITION","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/categories","host":["{{baseUrl}}"],"path":["tournaments",":id","categories"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Suma categorías (filas OPEN) al evento de la categoría de la URL, con su mismo `eventId`: lo que el panel hace al editar la serie. Nombre (`\"<evento> — <categoría>\"`), deporte, descripción, lugar y club se heredan; fechas y precio también cuando la variante no los manda. Una (género, categoría) que ya existe en el evento es 409 TOURNAMENT_CATEGORY_EXISTS; una repetida dentro del body, 400 VALIDATION (mismo criterio que el alta). Un torneo legacy sin evento pasa a ser el evento (se le asigna su propio id). No renombra ni borra categorías (`DELETE /tournaments/{id}`). Audit TOURNAMENT_CREATED por fila. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"6ta\"\n      ],\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El evento ya tiene esa categoría para ese género.\",\n  \"code\": \"TOURNAMENT_CATEGORY_EXISTS\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/categories","host":["{{baseUrl}}"],"path":["tournaments",":id","categories"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Suma categorías (filas OPEN) al evento de la categoría de la URL, con su mismo `eventId`: lo que el panel hace al editar la serie. Nombre (`\"<evento> — <categoría>\"`), deporte, descripción, lugar y club se heredan; fechas y precio también cuando la variante no los manda. Una (género, categoría) que ya existe en el evento es 409 TOURNAMENT_CATEGORY_EXISTS; una repetida dentro del body, 400 VALIDATION (mismo criterio que el alta). Un torneo legacy sin evento pasa a ser el evento (se le asigna su propio id). No renombra ni borra categorías (`DELETE /tournaments/{id}`). Audit TOURNAMENT_CREATED por fila. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"6ta\"\n      ],\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/categories","host":["{{baseUrl}}"],"path":["tournaments",":id","categories"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Suma categorías (filas OPEN) al evento de la categoría de la URL, con su mismo `eventId`: lo que el panel hace al editar la serie. Nombre (`\"<evento> — <categoría>\"`), deporte, descripción, lugar y club se heredan; fechas y precio también cuando la variante no los manda. Una (género, categoría) que ya existe en el evento es 409 TOURNAMENT_CATEGORY_EXISTS; una repetida dentro del body, 400 VALIDATION (mismo criterio que el alta). Un torneo legacy sin evento pasa a ser el evento (se le asigna su propio id). No renombra ni borra categorías (`DELETE /tournaments/{id}`). Audit TOURNAMENT_CREATED por fila. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"6ta\"\n      ],\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/categories","host":["{{baseUrl}}"],"path":["tournaments",":id","categories"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Suma categorías (filas OPEN) al evento de la categoría de la URL, con su mismo `eventId`: lo que el panel hace al editar la serie. Nombre (`\"<evento> — <categoría>\"`), deporte, descripción, lugar y club se heredan; fechas y precio también cuando la variante no los manda. Una (género, categoría) que ya existe en el evento es 409 TOURNAMENT_CATEGORY_EXISTS; una repetida dentro del body, 400 VALIDATION (mismo criterio que el alta). Un torneo legacy sin evento pasa a ser el evento (se le asigna su propio id). No renombra ni borra categorías (`DELETE /tournaments/{id}`). Audit TOURNAMENT_CREATED por fila. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"6ta\"\n      ],\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/categories","host":["{{baseUrl}}"],"path":["tournaments",":id","categories"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Suma categorías (filas OPEN) al evento de la categoría de la URL, con su mismo `eventId`: lo que el panel hace al editar la serie. Nombre (`\"<evento> — <categoría>\"`), deporte, descripción, lugar y club se heredan; fechas y precio también cuando la variante no los manda. Una (género, categoría) que ya existe en el evento es 409 TOURNAMENT_CATEGORY_EXISTS; una repetida dentro del body, 400 VALIDATION (mismo criterio que el alta). Un torneo legacy sin evento pasa a ser el evento (se le asigna su propio id). No renombra ni borra categorías (`DELETE /tournaments/{id}`). Audit TOURNAMENT_CREATED por fila. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"variants\": [\n    {\n      \"gender\": \"MALE\",\n      \"categories\": [\n        \"6ta\"\n      ],\n      \"maxTeams\": 12,\n      \"price\": 1200\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Finalizar una categoría (finalizeTournament)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/finalize","host":["{{baseUrl}}"],"path":["tournaments",":id","finalize"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin body. El botón \"Finalizar\" del panel: exige ELIMINATION_PHASE con la final jugada; escribe el podio (1 campeón, 2 subcampeón, 3 los dos semifinalistas), acredita los puntos Skalia por posición (idempotentes por (torneo, jugador)), habilita los premios configurados y avisa a los ganadores (en background), cura mirrors faltantes y deja la categoría COMPLETED con las parejas que no ganaron en ELIMINATED. Idempotente: repetirlo sobre una COMPLETED responde 200 con el podio que tiene, sin volver a otorgar nada. Audit TOURNAMENT_FINALIZED. Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"response":[{"name":"200 · Cerrada (o ya lo estaba): la categoría y su podio.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/finalize","host":["{{baseUrl}}"],"path":["tournaments",":id","finalize"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin body. El botón \"Finalizar\" del panel: exige ELIMINATION_PHASE con la final jugada; escribe el podio (1 campeón, 2 subcampeón, 3 los dos semifinalistas), acredita los puntos Skalia por posición (idempotentes por (torneo, jugador)), habilita los premios configurados y avisa a los ganadores (en background), cura mirrors faltantes y deja la categoría COMPLETED con las parejas que no ganaron en ELIMINATED. Idempotente: repetirlo sobre una COMPLETED responde 200 con el podio que tiene, sin volver a otorgar nada. Audit TOURNAMENT_FINALIZED. Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"tournament\": {\n    \"id\": \"9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d\",\n    \"eventId\": \"7a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"clubId\": \"3f1c9a52-7d0e-4b6a-9c11-2a4f8e6d5b70\",\n    \"name\": \"Torneo Primavera — 4ta\",\n    \"sport\": \"PADEL\",\n    \"format\": \"CLASICO\",\n    \"status\": \"COMPLETED\",\n    \"category\": \"4ta\",\n    \"gender\": \"MALE\",\n    \"description\": null,\n    \"location\": null,\n    \"price\": 1200,\n    \"maxTeams\": 12,\n    \"registeredTeams\": 7,\n    \"startDate\": \"2026-10-16\",\n    \"endDate\": \"2026-10-18\",\n    \"createdAt\": \"2026-09-18 12:00:00\"\n  },\n  \"podium\": [\n    {\n      \"position\": 1,\n      \"teamId\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"label\": \"Los Halcones\"\n    },\n    {\n      \"position\": 2,\n      \"teamId\": \"1a2b3c4d-2222-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"label\": \"Pareja #2\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / TOURNAMENT_RULE_VIOLATION","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/finalize","host":["{{baseUrl}}"],"path":["tournaments",":id","finalize"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin body. El botón \"Finalizar\" del panel: exige ELIMINATION_PHASE con la final jugada; escribe el podio (1 campeón, 2 subcampeón, 3 los dos semifinalistas), acredita los puntos Skalia por posición (idempotentes por (torneo, jugador)), habilita los premios configurados y avisa a los ganadores (en background), cura mirrors faltantes y deja la categoría COMPLETED con las parejas que no ganaron en ELIMINATED. Idempotente: repetirlo sobre una COMPLETED responde 200 con el podio que tiene, sin volver a otorgar nada. Audit TOURNAMENT_FINALIZED. Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/finalize","host":["{{baseUrl}}"],"path":["tournaments",":id","finalize"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin body. El botón \"Finalizar\" del panel: exige ELIMINATION_PHASE con la final jugada; escribe el podio (1 campeón, 2 subcampeón, 3 los dos semifinalistas), acredita los puntos Skalia por posición (idempotentes por (torneo, jugador)), habilita los premios configurados y avisa a los ganadores (en background), cura mirrors faltantes y deja la categoría COMPLETED con las parejas que no ganaron en ELIMINATED. Idempotente: repetirlo sobre una COMPLETED responde 200 con el podio que tiene, sin volver a otorgar nada. Audit TOURNAMENT_FINALIZED. Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/finalize","host":["{{baseUrl}}"],"path":["tournaments",":id","finalize"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin body. El botón \"Finalizar\" del panel: exige ELIMINATION_PHASE con la final jugada; escribe el podio (1 campeón, 2 subcampeón, 3 los dos semifinalistas), acredita los puntos Skalia por posición (idempotentes por (torneo, jugador)), habilita los premios configurados y avisa a los ganadores (en background), cura mirrors faltantes y deja la categoría COMPLETED con las parejas que no ganaron en ELIMINATED. Idempotente: repetirlo sobre una COMPLETED responde 200 con el podio que tiene, sin volver a otorgar nada. Audit TOURNAMENT_FINALIZED. Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · TOURNAMENT_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/finalize","host":["{{baseUrl}}"],"path":["tournaments",":id","finalize"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin body. El botón \"Finalizar\" del panel: exige ELIMINATION_PHASE con la final jugada; escribe el podio (1 campeón, 2 subcampeón, 3 los dos semifinalistas), acredita los puntos Skalia por posición (idempotentes por (torneo, jugador)), habilita los premios configurados y avisa a los ganadores (en background), cura mirrors faltantes y deja la categoría COMPLETED con las parejas que no ganaron en ELIMINATED. Idempotente: repetirlo sobre una COMPLETED responde 200 con el podio que tiene, sin volver a otorgar nada. Audit TOURNAMENT_FINALIZED. Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo no existe o no es de este club.\",\n  \"code\": \"TOURNAMENT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · TOURNAMENT_INVALID_TRANSITION","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/finalize","host":["{{baseUrl}}"],"path":["tournaments",":id","finalize"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin body. El botón \"Finalizar\" del panel: exige ELIMINATION_PHASE con la final jugada; escribe el podio (1 campeón, 2 subcampeón, 3 los dos semifinalistas), acredita los puntos Skalia por posición (idempotentes por (torneo, jugador)), habilita los premios configurados y avisa a los ganadores (en background), cura mirrors faltantes y deja la categoría COMPLETED con las parejas que no ganaron en ELIMINATED. Idempotente: repetirlo sobre una COMPLETED responde 200 con el podio que tiene, sin volver a otorgar nada. Audit TOURNAMENT_FINALIZED. Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ese cambio de estado no está permitido desde el estado actual del torneo.\",\n  \"code\": \"TOURNAMENT_INVALID_TRANSITION\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/finalize","host":["{{baseUrl}}"],"path":["tournaments",":id","finalize"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin body. El botón \"Finalizar\" del panel: exige ELIMINATION_PHASE con la final jugada; escribe el podio (1 campeón, 2 subcampeón, 3 los dos semifinalistas), acredita los puntos Skalia por posición (idempotentes por (torneo, jugador)), habilita los premios configurados y avisa a los ganadores (en background), cura mirrors faltantes y deja la categoría COMPLETED con las parejas que no ganaron en ELIMINATED. Idempotente: repetirlo sobre una COMPLETED responde 200 con el podio que tiene, sin volver a otorgar nada. Audit TOURNAMENT_FINALIZED. Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/finalize","host":["{{baseUrl}}"],"path":["tournaments",":id","finalize"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin body. El botón \"Finalizar\" del panel: exige ELIMINATION_PHASE con la final jugada; escribe el podio (1 campeón, 2 subcampeón, 3 los dos semifinalistas), acredita los puntos Skalia por posición (idempotentes por (torneo, jugador)), habilita los premios configurados y avisa a los ganadores (en background), cura mirrors faltantes y deja la categoría COMPLETED con las parejas que no ganaron en ELIMINATED. Idempotente: repetirlo sobre una COMPLETED responde 200 con el podio que tiene, sin volver a otorgar nada. Audit TOURNAMENT_FINALIZED. Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/finalize","host":["{{baseUrl}}"],"path":["tournaments",":id","finalize"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Sin body. El botón \"Finalizar\" del panel: exige ELIMINATION_PHASE con la final jugada; escribe el podio (1 campeón, 2 subcampeón, 3 los dos semifinalistas), acredita los puntos Skalia por posición (idempotentes por (torneo, jugador)), habilita los premios configurados y avisa a los ganadores (en background), cura mirrors faltantes y deja la categoría COMPLETED con las parejas que no ganaron en ELIMINATED. Idempotente: repetirlo sobre una COMPLETED responde 200 con el podio que tiene, sin volver a otorgar nada. Audit TOURNAMENT_FINALIZED. Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Generar el cuadro de eliminatorias (generateTournamentBracket)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-bracket","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-bracket"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Clasifican las 2 mejores de cada grupo (o `qualifiedTeamIds`, que tienen que ser parejas de ESTA categoría: un id ajeno es 400 VALIDATION con `details.unknownTeamIds`, nunca se ignora), se siembran mejor contra peor y el torneo pasa a ELIMINATION_PHASE. Sólo desde SCHEDULE_BUILDING / GROUP_PHASE. Para rehacer un cuadro ya generado: `PATCH { status: GROUP_PHASE }` (con `force: true` si hay eliminatorias jugadas) y volver a llamar. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · Partidos del cuadro.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-bracket","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-bracket"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Clasifican las 2 mejores de cada grupo (o `qualifiedTeamIds`, que tienen que ser parejas de ESTA categoría: un id ajeno es 400 VALIDATION con `details.unknownTeamIds`, nunca se ignora), se siembran mejor contra peor y el torneo pasa a ELIMINATION_PHASE. Sólo desde SCHEDULE_BUILDING / GROUP_PHASE. Para rehacer un cuadro ya generado: `PATCH { status: GROUP_PHASE }` (con `force: true` si hay eliminatorias jugadas) y volver a llamar. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"matches\": [\n    {\n      \"id\": \"6f5e4d3c-bbbb-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"tournamentId\": \"9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d\",\n      \"phase\": \"GROUP\",\n      \"round\": 1,\n      \"groupId\": \"4d3c2b1a-aaaa-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"matchOrder\": 1,\n      \"team1Id\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"team2Id\": \"1a2b3c4d-2222-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"team1Label\": \"Los Halcones\",\n      \"team2Label\": \"Pareja #2\",\n      \"team1FromMatchId\": null,\n      \"team1FromOutcome\": null,\n      \"team2FromMatchId\": null,\n      \"team2FromOutcome\": null,\n      \"status\": \"COMPLETED\",\n      \"winnerTeamId\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"isWalkover\": false,\n      \"walkoverTeamId\": null,\n      \"sets\": [\n        {\n          \"team1\": 6,\n          \"team2\": 3\n        },\n        {\n          \"team1\": 7,\n          \"team2\": 5\n        }\n      ],\n      \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n      \"scheduledAt\": \"2026-10-17T09:00:00\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / TOURNAMENT_STATUS_INVALID / TOURNAMENT_RULE_VIOLATION","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-bracket","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-bracket"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Clasifican las 2 mejores de cada grupo (o `qualifiedTeamIds`, que tienen que ser parejas de ESTA categoría: un id ajeno es 400 VALIDATION con `details.unknownTeamIds`, nunca se ignora), se siembran mejor contra peor y el torneo pasa a ELIMINATION_PHASE. Sólo desde SCHEDULE_BUILDING / GROUP_PHASE. Para rehacer un cuadro ya generado: `PATCH { status: GROUP_PHASE }` (con `force: true` si hay eliminatorias jugadas) y volver a llamar. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-bracket","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-bracket"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Clasifican las 2 mejores de cada grupo (o `qualifiedTeamIds`, que tienen que ser parejas de ESTA categoría: un id ajeno es 400 VALIDATION con `details.unknownTeamIds`, nunca se ignora), se siembran mejor contra peor y el torneo pasa a ELIMINATION_PHASE. Sólo desde SCHEDULE_BUILDING / GROUP_PHASE. Para rehacer un cuadro ya generado: `PATCH { status: GROUP_PHASE }` (con `force: true` si hay eliminatorias jugadas) y volver a llamar. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-bracket","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-bracket"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Clasifican las 2 mejores de cada grupo (o `qualifiedTeamIds`, que tienen que ser parejas de ESTA categoría: un id ajeno es 400 VALIDATION con `details.unknownTeamIds`, nunca se ignora), se siembran mejor contra peor y el torneo pasa a ELIMINATION_PHASE. Sólo desde SCHEDULE_BUILDING / GROUP_PHASE. Para rehacer un cuadro ya generado: `PATCH { status: GROUP_PHASE }` (con `force: true` si hay eliminatorias jugadas) y volver a llamar. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · TOURNAMENT_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-bracket","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-bracket"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Clasifican las 2 mejores de cada grupo (o `qualifiedTeamIds`, que tienen que ser parejas de ESTA categoría: un id ajeno es 400 VALIDATION con `details.unknownTeamIds`, nunca se ignora), se siembran mejor contra peor y el torneo pasa a ELIMINATION_PHASE. Sólo desde SCHEDULE_BUILDING / GROUP_PHASE. Para rehacer un cuadro ya generado: `PATCH { status: GROUP_PHASE }` (con `force: true` si hay eliminatorias jugadas) y volver a llamar. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo no existe o no es de este club.\",\n  \"code\": \"TOURNAMENT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · BRACKET_ALREADY_GENERATED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-bracket","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-bracket"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Clasifican las 2 mejores de cada grupo (o `qualifiedTeamIds`, que tienen que ser parejas de ESTA categoría: un id ajeno es 400 VALIDATION con `details.unknownTeamIds`, nunca se ignora), se siembran mejor contra peor y el torneo pasa a ELIMINATION_PHASE. Sólo desde SCHEDULE_BUILDING / GROUP_PHASE. Para rehacer un cuadro ya generado: `PATCH { status: GROUP_PHASE }` (con `force: true` si hay eliminatorias jugadas) y volver a llamar. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuadro ya fue generado. Volvé el torneo a fase de grupos antes de regenerarlo.\",\n  \"code\": \"BRACKET_ALREADY_GENERATED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-bracket","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-bracket"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Clasifican las 2 mejores de cada grupo (o `qualifiedTeamIds`, que tienen que ser parejas de ESTA categoría: un id ajeno es 400 VALIDATION con `details.unknownTeamIds`, nunca se ignora), se siembran mejor contra peor y el torneo pasa a ELIMINATION_PHASE. Sólo desde SCHEDULE_BUILDING / GROUP_PHASE. Para rehacer un cuadro ya generado: `PATCH { status: GROUP_PHASE }` (con `force: true` si hay eliminatorias jugadas) y volver a llamar. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-bracket","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-bracket"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Clasifican las 2 mejores de cada grupo (o `qualifiedTeamIds`, que tienen que ser parejas de ESTA categoría: un id ajeno es 400 VALIDATION con `details.unknownTeamIds`, nunca se ignora), se siembran mejor contra peor y el torneo pasa a ELIMINATION_PHASE. Sólo desde SCHEDULE_BUILDING / GROUP_PHASE. Para rehacer un cuadro ya generado: `PATCH { status: GROUP_PHASE }` (con `force: true` si hay eliminatorias jugadas) y volver a llamar. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-bracket","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-bracket"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Clasifican las 2 mejores de cada grupo (o `qualifiedTeamIds`, que tienen que ser parejas de ESTA categoría: un id ajeno es 400 VALIDATION con `details.unknownTeamIds`, nunca se ignora), se siembran mejor contra peor y el torneo pasa a ELIMINATION_PHASE. Sólo desde SCHEDULE_BUILDING / GROUP_PHASE. Para rehacer un cuadro ya generado: `PATCH { status: GROUP_PHASE }` (con `force: true` si hay eliminatorias jugadas) y volver a llamar. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-bracket","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-bracket"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Clasifican las 2 mejores de cada grupo (o `qualifiedTeamIds`, que tienen que ser parejas de ESTA categoría: un id ajeno es 400 VALIDATION con `details.unknownTeamIds`, nunca se ignora), se siembran mejor contra peor y el torneo pasa a ELIMINATION_PHASE. Sólo desde SCHEDULE_BUILDING / GROUP_PHASE. Para rehacer un cuadro ya generado: `PATCH { status: GROUP_PHASE }` (con `force: true` si hay eliminatorias jugadas) y volver a llamar. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Sortear los grupos (generateTournamentGroups)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-groups","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-groups"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo handler que el panel: una cabeza de serie por grupo (por nivel promedio), el resto por afinidad horaria si `autoFill`; arma los partidos de cada grupo y deja el torneo en SCHEDULE_BUILDING. Regenerar borra grupos, partidos y sus reservas (emisor único). Exige al menos 3 parejas completas. Un torneo COMPLETED / CANCELLED no se regenera ni con `force`. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"autoFill\": true\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · Grupos generados (con `warnings` si hubo que forzar algo).","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-groups","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-groups"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo handler que el panel: una cabeza de serie por grupo (por nivel promedio), el resto por afinidad horaria si `autoFill`; arma los partidos de cada grupo y deja el torneo en SCHEDULE_BUILDING. Regenerar borra grupos, partidos y sus reservas (emisor único). Exige al menos 3 parejas completas. Un torneo COMPLETED / CANCELLED no se regenera ni con `force`. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"autoFill\": true\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"groups\": [\n    {\n      \"id\": \"4d3c2b1a-aaaa-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"name\": \"A\",\n      \"timeSlot\": \"SATURDAY_MORNING\",\n      \"teamIds\": [\n        \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n        \"1a2b3c4d-2222-4a7b-8c9d-0e1f2a3b4c5d\"\n      ]\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / TOURNAMENT_RULE_VIOLATION","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-groups","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-groups"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo handler que el panel: una cabeza de serie por grupo (por nivel promedio), el resto por afinidad horaria si `autoFill`; arma los partidos de cada grupo y deja el torneo en SCHEDULE_BUILDING. Regenerar borra grupos, partidos y sus reservas (emisor único). Exige al menos 3 parejas completas. Un torneo COMPLETED / CANCELLED no se regenera ni con `force`. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"autoFill\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-groups","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-groups"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo handler que el panel: una cabeza de serie por grupo (por nivel promedio), el resto por afinidad horaria si `autoFill`; arma los partidos de cada grupo y deja el torneo en SCHEDULE_BUILDING. Regenerar borra grupos, partidos y sus reservas (emisor único). Exige al menos 3 parejas completas. Un torneo COMPLETED / CANCELLED no se regenera ni con `force`. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"autoFill\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-groups","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-groups"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo handler que el panel: una cabeza de serie por grupo (por nivel promedio), el resto por afinidad horaria si `autoFill`; arma los partidos de cada grupo y deja el torneo en SCHEDULE_BUILDING. Regenerar borra grupos, partidos y sus reservas (emisor único). Exige al menos 3 parejas completas. Un torneo COMPLETED / CANCELLED no se regenera ni con `force`. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"autoFill\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · TOURNAMENT_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-groups","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-groups"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo handler que el panel: una cabeza de serie por grupo (por nivel promedio), el resto por afinidad horaria si `autoFill`; arma los partidos de cada grupo y deja el torneo en SCHEDULE_BUILDING. Regenerar borra grupos, partidos y sus reservas (emisor único). Exige al menos 3 parejas completas. Un torneo COMPLETED / CANCELLED no se regenera ni con `force`. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"autoFill\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo no existe o no es de este club.\",\n  \"code\": \"TOURNAMENT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · DUPLICATE_PAIRS / TOURNAMENT_ALREADY_PLAYED / TOURNAMENT_INVALID_TRANSITION","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-groups","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-groups"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo handler que el panel: una cabeza de serie por grupo (por nivel promedio), el resto por afinidad horaria si `autoFill`; arma los partidos de cada grupo y deja el torneo en SCHEDULE_BUILDING. Regenerar borra grupos, partidos y sus reservas (emisor único). Exige al menos 3 parejas completas. Un torneo COMPLETED / CANCELLED no se regenera ni con `force`. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"autoFill\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Hay parejas duplicadas inscriptas. Dá de baja las repetidas antes de generar los grupos.\",\n  \"code\": \"DUPLICATE_PAIRS\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-groups","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-groups"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo handler que el panel: una cabeza de serie por grupo (por nivel promedio), el resto por afinidad horaria si `autoFill`; arma los partidos de cada grupo y deja el torneo en SCHEDULE_BUILDING. Regenerar borra grupos, partidos y sus reservas (emisor único). Exige al menos 3 parejas completas. Un torneo COMPLETED / CANCELLED no se regenera ni con `force`. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"autoFill\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-groups","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-groups"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo handler que el panel: una cabeza de serie por grupo (por nivel promedio), el resto por afinidad horaria si `autoFill`; arma los partidos de cada grupo y deja el torneo en SCHEDULE_BUILDING. Regenerar borra grupos, partidos y sus reservas (emisor único). Exige al menos 3 parejas completas. Un torneo COMPLETED / CANCELLED no se regenera ni con `force`. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"autoFill\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-groups","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-groups"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo handler que el panel: una cabeza de serie por grupo (por nivel promedio), el resto por afinidad horaria si `autoFill`; arma los partidos de cada grupo y deja el torneo en SCHEDULE_BUILDING. Regenerar borra grupos, partidos y sus reservas (emisor único). Exige al menos 3 parejas completas. Un torneo COMPLETED / CANCELLED no se regenera ni con `force`. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"autoFill\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-groups","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-groups"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo handler que el panel: una cabeza de serie por grupo (por nivel promedio), el resto por afinidad horaria si `autoFill`; arma los partidos de cada grupo y deja el torneo en SCHEDULE_BUILDING. Regenerar borra grupos, partidos y sus reservas (emisor único). Exige al menos 3 parejas completas. Un torneo COMPLETED / CANCELLED no se regenera ni con `force`. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"autoFill\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Regenerar los partidos de grupos (generateTournamentMatches)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-matches","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-matches"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Rehace los partidos de la fase de grupos a partir de los grupos actuales (2 parejas → 1 partido; 3 → cadena \"ganador queda en cancha\"; 4+ → round-robin) y borra los anteriores con sus reservas. Bloqueado si ya hay partidos de grupo jugados o si el torneo es terminal. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"response":[{"name":"200 · Partidos de grupo.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-matches","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-matches"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Rehace los partidos de la fase de grupos a partir de los grupos actuales (2 parejas → 1 partido; 3 → cadena \"ganador queda en cancha\"; 4+ → round-robin) y borra los anteriores con sus reservas. Bloqueado si ya hay partidos de grupo jugados o si el torneo es terminal. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"matches\": [\n    {\n      \"id\": \"6f5e4d3c-bbbb-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"tournamentId\": \"9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d\",\n      \"phase\": \"GROUP\",\n      \"round\": 1,\n      \"groupId\": \"4d3c2b1a-aaaa-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"matchOrder\": 1,\n      \"team1Id\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"team2Id\": \"1a2b3c4d-2222-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"team1Label\": \"Los Halcones\",\n      \"team2Label\": \"Pareja #2\",\n      \"team1FromMatchId\": null,\n      \"team1FromOutcome\": null,\n      \"team2FromMatchId\": null,\n      \"team2FromOutcome\": null,\n      \"status\": \"COMPLETED\",\n      \"winnerTeamId\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"isWalkover\": false,\n      \"walkoverTeamId\": null,\n      \"sets\": [\n        {\n          \"team1\": 6,\n          \"team2\": 3\n        },\n        {\n          \"team1\": 7,\n          \"team2\": 5\n        }\n      ],\n      \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n      \"scheduledAt\": \"2026-10-17T09:00:00\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / TOURNAMENT_RULE_VIOLATION","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-matches","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-matches"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Rehace los partidos de la fase de grupos a partir de los grupos actuales (2 parejas → 1 partido; 3 → cadena \"ganador queda en cancha\"; 4+ → round-robin) y borra los anteriores con sus reservas. Bloqueado si ya hay partidos de grupo jugados o si el torneo es terminal. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-matches","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-matches"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Rehace los partidos de la fase de grupos a partir de los grupos actuales (2 parejas → 1 partido; 3 → cadena \"ganador queda en cancha\"; 4+ → round-robin) y borra los anteriores con sus reservas. Bloqueado si ya hay partidos de grupo jugados o si el torneo es terminal. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-matches","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-matches"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Rehace los partidos de la fase de grupos a partir de los grupos actuales (2 parejas → 1 partido; 3 → cadena \"ganador queda en cancha\"; 4+ → round-robin) y borra los anteriores con sus reservas. Bloqueado si ya hay partidos de grupo jugados o si el torneo es terminal. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · TOURNAMENT_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-matches","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-matches"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Rehace los partidos de la fase de grupos a partir de los grupos actuales (2 parejas → 1 partido; 3 → cadena \"ganador queda en cancha\"; 4+ → round-robin) y borra los anteriores con sus reservas. Bloqueado si ya hay partidos de grupo jugados o si el torneo es terminal. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo no existe o no es de este club.\",\n  \"code\": \"TOURNAMENT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · TOURNAMENT_ALREADY_PLAYED / TOURNAMENT_INVALID_TRANSITION","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-matches","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-matches"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Rehace los partidos de la fase de grupos a partir de los grupos actuales (2 parejas → 1 partido; 3 → cadena \"ganador queda en cancha\"; 4+ → round-robin) y borra los anteriores con sus reservas. Bloqueado si ya hay partidos de grupo jugados o si el torneo es terminal. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo ya tiene partidos jugados. Repetí con force=true para borrarlos.\",\n  \"code\": \"TOURNAMENT_ALREADY_PLAYED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-matches","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-matches"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Rehace los partidos de la fase de grupos a partir de los grupos actuales (2 parejas → 1 partido; 3 → cadena \"ganador queda en cancha\"; 4+ → round-robin) y borra los anteriores con sus reservas. Bloqueado si ya hay partidos de grupo jugados o si el torneo es terminal. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-matches","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-matches"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Rehace los partidos de la fase de grupos a partir de los grupos actuales (2 parejas → 1 partido; 3 → cadena \"ganador queda en cancha\"; 4+ → round-robin) y borra los anteriores con sus reservas. Bloqueado si ya hay partidos de grupo jugados o si el torneo es terminal. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/generate-matches","host":["{{baseUrl}}"],"path":["tournaments",":id","generate-matches"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Rehace los partidos de la fase de grupos a partir de los grupos actuales (2 parejas → 1 partido; 3 → cadena \"ganador queda en cancha\"; 4+ → round-robin) y borra los anteriores con sus reservas. Bloqueado si ya hay partidos de grupo jugados o si el torneo es terminal. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Partidos de un torneo (listTournamentMatches)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches","host":["{{baseUrl}}"],"path":["tournaments",":id","matches"],"query":[{"key":"phase","value":"GROUP","description":"Filtra por fase (`GROUP`, `R16`, `QF`, `SF`, `FINAL`).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Grupos y cuadro, con las parejas por id y etiqueta anónima, fase, ronda, cancha, horario y sets. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"response":[{"name":"200 · Partidos.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches","host":["{{baseUrl}}"],"path":["tournaments",":id","matches"],"query":[{"key":"phase","value":"GROUP","description":"Filtra por fase (`GROUP`, `R16`, `QF`, `SF`, `FINAL`).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Grupos y cuadro, con las parejas por id y etiqueta anónima, fase, ronda, cancha, horario y sets. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"matches\": [\n    {\n      \"id\": \"6f5e4d3c-bbbb-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"tournamentId\": \"9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d\",\n      \"phase\": \"GROUP\",\n      \"round\": 1,\n      \"groupId\": \"4d3c2b1a-aaaa-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"matchOrder\": 1,\n      \"team1Id\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"team2Id\": \"1a2b3c4d-2222-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"team1Label\": \"Los Halcones\",\n      \"team2Label\": \"Pareja #2\",\n      \"team1FromMatchId\": null,\n      \"team1FromOutcome\": null,\n      \"team2FromMatchId\": null,\n      \"team2FromOutcome\": null,\n      \"status\": \"COMPLETED\",\n      \"winnerTeamId\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"isWalkover\": false,\n      \"walkoverTeamId\": null,\n      \"sets\": [\n        {\n          \"team1\": 6,\n          \"team2\": 3\n        },\n        {\n          \"team1\": 7,\n          \"team2\": 5\n        }\n      ],\n      \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n      \"scheduledAt\": \"2026-10-17T09:00:00\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches","host":["{{baseUrl}}"],"path":["tournaments",":id","matches"],"query":[{"key":"phase","value":"GROUP","description":"Filtra por fase (`GROUP`, `R16`, `QF`, `SF`, `FINAL`).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Grupos y cuadro, con las parejas por id y etiqueta anónima, fase, ronda, cancha, horario y sets. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches","host":["{{baseUrl}}"],"path":["tournaments",":id","matches"],"query":[{"key":"phase","value":"GROUP","description":"Filtra por fase (`GROUP`, `R16`, `QF`, `SF`, `FINAL`).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Grupos y cuadro, con las parejas por id y etiqueta anónima, fase, ronda, cancha, horario y sets. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches","host":["{{baseUrl}}"],"path":["tournaments",":id","matches"],"query":[{"key":"phase","value":"GROUP","description":"Filtra por fase (`GROUP`, `R16`, `QF`, `SF`, `FINAL`).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Grupos y cuadro, con las parejas por id y etiqueta anónima, fase, ronda, cancha, horario y sets. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · TOURNAMENT_NOT_FOUND","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches","host":["{{baseUrl}}"],"path":["tournaments",":id","matches"],"query":[{"key":"phase","value":"GROUP","description":"Filtra por fase (`GROUP`, `R16`, `QF`, `SF`, `FINAL`).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Grupos y cuadro, con las parejas por id y etiqueta anónima, fase, ronda, cancha, horario y sets. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo no existe o no es de este club.\",\n  \"code\": \"TOURNAMENT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches","host":["{{baseUrl}}"],"path":["tournaments",":id","matches"],"query":[{"key":"phase","value":"GROUP","description":"Filtra por fase (`GROUP`, `R16`, `QF`, `SF`, `FINAL`).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Grupos y cuadro, con las parejas por id y etiqueta anónima, fase, ronda, cancha, horario y sets. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches","host":["{{baseUrl}}"],"path":["tournaments",":id","matches"],"query":[{"key":"phase","value":"GROUP","description":"Filtra por fase (`GROUP`, `R16`, `QF`, `SF`, `FINAL`).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Grupos y cuadro, con las parejas por id y etiqueta anónima, fase, ronda, cancha, horario y sets. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches","host":["{{baseUrl}}"],"path":["tournaments",":id","matches"],"query":[{"key":"phase","value":"GROUP","description":"Filtra por fase (`GROUP`, `R16`, `QF`, `SF`, `FINAL`).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Grupos y cuadro, con las parejas por id y etiqueta anónima, fase, ronda, cancha, horario y sets. Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Cargar el resultado de un partido (saveTournamentMatchResult)","request":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/result","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","result"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"Mismos guards que el panel: torneo no terminado, parejas completas, sets sin empate, ganador coherente, no pisar partidos dependientes ya jugados. Propaga la cadena \"ganador queda en cancha\", avanza el cuadro, aplica el nivel Skalia de los 4 jugadores (salvo W.O.), notifica y, si cerró la fase de grupos, genera el cuadro solo. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"sets\": [\n    {\n      \"team1\": 6,\n      \"team2\": 3\n    },\n    {\n      \"team1\": 7,\n      \"team2\": 5\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · El partido con su resultado.","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/result","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","result"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"Mismos guards que el panel: torneo no terminado, parejas completas, sets sin empate, ganador coherente, no pisar partidos dependientes ya jugados. Propaga la cadena \"ganador queda en cancha\", avanza el cuadro, aplica el nivel Skalia de los 4 jugadores (salvo W.O.), notifica y, si cerró la fase de grupos, genera el cuadro solo. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"sets\": [\n    {\n      \"team1\": 6,\n      \"team2\": 3\n    },\n    {\n      \"team1\": 7,\n      \"team2\": 5\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"match\": {\n    \"id\": \"6f5e4d3c-bbbb-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"tournamentId\": \"9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d\",\n    \"phase\": \"GROUP\",\n    \"round\": 1,\n    \"groupId\": \"4d3c2b1a-aaaa-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"matchOrder\": 1,\n    \"team1Id\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"team2Id\": \"1a2b3c4d-2222-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"team1Label\": \"Los Halcones\",\n    \"team2Label\": \"Pareja #2\",\n    \"team1FromMatchId\": null,\n    \"team1FromOutcome\": null,\n    \"team2FromMatchId\": null,\n    \"team2FromOutcome\": null,\n    \"status\": \"COMPLETED\",\n    \"winnerTeamId\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"isWalkover\": false,\n    \"walkoverTeamId\": null,\n    \"sets\": [\n      {\n        \"team1\": 6,\n        \"team2\": 3\n      },\n      {\n        \"team1\": 7,\n        \"team2\": 5\n      }\n    ],\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"scheduledAt\": \"2026-10-17T09:00:00\"\n  }\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / TOURNAMENT_RULE_VIOLATION","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/result","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","result"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"Mismos guards que el panel: torneo no terminado, parejas completas, sets sin empate, ganador coherente, no pisar partidos dependientes ya jugados. Propaga la cadena \"ganador queda en cancha\", avanza el cuadro, aplica el nivel Skalia de los 4 jugadores (salvo W.O.), notifica y, si cerró la fase de grupos, genera el cuadro solo. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"sets\": [\n    {\n      \"team1\": 6,\n      \"team2\": 3\n    },\n    {\n      \"team1\": 7,\n      \"team2\": 5\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/result","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","result"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"Mismos guards que el panel: torneo no terminado, parejas completas, sets sin empate, ganador coherente, no pisar partidos dependientes ya jugados. Propaga la cadena \"ganador queda en cancha\", avanza el cuadro, aplica el nivel Skalia de los 4 jugadores (salvo W.O.), notifica y, si cerró la fase de grupos, genera el cuadro solo. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"sets\": [\n    {\n      \"team1\": 6,\n      \"team2\": 3\n    },\n    {\n      \"team1\": 7,\n      \"team2\": 5\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/result","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","result"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"Mismos guards que el panel: torneo no terminado, parejas completas, sets sin empate, ganador coherente, no pisar partidos dependientes ya jugados. Propaga la cadena \"ganador queda en cancha\", avanza el cuadro, aplica el nivel Skalia de los 4 jugadores (salvo W.O.), notifica y, si cerró la fase de grupos, genera el cuadro solo. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"sets\": [\n    {\n      \"team1\": 6,\n      \"team2\": 3\n    },\n    {\n      \"team1\": 7,\n      \"team2\": 5\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · TOURNAMENT_NOT_FOUND / TOURNAMENT_MATCH_NOT_FOUND","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/result","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","result"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"Mismos guards que el panel: torneo no terminado, parejas completas, sets sin empate, ganador coherente, no pisar partidos dependientes ya jugados. Propaga la cadena \"ganador queda en cancha\", avanza el cuadro, aplica el nivel Skalia de los 4 jugadores (salvo W.O.), notifica y, si cerró la fase de grupos, genera el cuadro solo. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"sets\": [\n    {\n      \"team1\": 6,\n      \"team2\": 3\n    },\n    {\n      \"team1\": 7,\n      \"team2\": 5\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo no existe o no es de este club.\",\n  \"code\": \"TOURNAMENT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · INCOMPLETE_PAIR_IN_MATCH / CHILD_MATCH_ALREADY_PLAYED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/result","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","result"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"Mismos guards que el panel: torneo no terminado, parejas completas, sets sin empate, ganador coherente, no pisar partidos dependientes ya jugados. Propaga la cadena \"ganador queda en cancha\", avanza el cuadro, aplica el nivel Skalia de los 4 jugadores (salvo W.O.), notifica y, si cerró la fase de grupos, genera el cuadro solo. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"sets\": [\n    {\n      \"team1\": 6,\n      \"team2\": 3\n    },\n    {\n      \"team1\": 7,\n      \"team2\": 5\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Una de las parejas del partido todavía no tiene compañero.\",\n  \"code\": \"INCOMPLETE_PAIR_IN_MATCH\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/result","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","result"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"Mismos guards que el panel: torneo no terminado, parejas completas, sets sin empate, ganador coherente, no pisar partidos dependientes ya jugados. Propaga la cadena \"ganador queda en cancha\", avanza el cuadro, aplica el nivel Skalia de los 4 jugadores (salvo W.O.), notifica y, si cerró la fase de grupos, genera el cuadro solo. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"sets\": [\n    {\n      \"team1\": 6,\n      \"team2\": 3\n    },\n    {\n      \"team1\": 7,\n      \"team2\": 5\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/result","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","result"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"Mismos guards que el panel: torneo no terminado, parejas completas, sets sin empate, ganador coherente, no pisar partidos dependientes ya jugados. Propaga la cadena \"ganador queda en cancha\", avanza el cuadro, aplica el nivel Skalia de los 4 jugadores (salvo W.O.), notifica y, si cerró la fase de grupos, genera el cuadro solo. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"sets\": [\n    {\n      \"team1\": 6,\n      \"team2\": 3\n    },\n    {\n      \"team1\": 7,\n      \"team2\": 5\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/result","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","result"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"Mismos guards que el panel: torneo no terminado, parejas completas, sets sin empate, ganador coherente, no pisar partidos dependientes ya jugados. Propaga la cadena \"ganador queda en cancha\", avanza el cuadro, aplica el nivel Skalia de los 4 jugadores (salvo W.O.), notifica y, si cerró la fase de grupos, genera el cuadro solo. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"sets\": [\n    {\n      \"team1\": 6,\n      \"team2\": 3\n    },\n    {\n      \"team1\": 7,\n      \"team2\": 5\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/result","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","result"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"Mismos guards que el panel: torneo no terminado, parejas completas, sets sin empate, ganador coherente, no pisar partidos dependientes ya jugados. Propaga la cadena \"ganador queda en cancha\", avanza el cuadro, aplica el nivel Skalia de los 4 jugadores (salvo W.O.), notifica y, si cerró la fase de grupos, genera el cuadro solo. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"sets\": [\n    {\n      \"team1\": 6,\n      \"team2\": 3\n    },\n    {\n      \"team1\": 7,\n      \"team2\": 5\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Programar cancha y horario (scheduleTournamentMatch)","request":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"La cancha tiene que ser del club del torneo. Después es el handler del panel: reglas de la fase de grupos (dos partidos del mismo grupo no comparten horario; una pareja descansa al menos 1 h), libera las reservas comunes que pisen el slot, crea o mueve la reserva del partido (emisor único: `booking.*` con actor `tournament` + `occupancy.changed` con actor `api`) y auto-programa los hijos de la cadena en la misma cancha. `null` en los dos desprograma. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"scheduledAt\": \"2026-10-17T09:00\"\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · El partido programado.","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"La cancha tiene que ser del club del torneo. Después es el handler del panel: reglas de la fase de grupos (dos partidos del mismo grupo no comparten horario; una pareja descansa al menos 1 h), libera las reservas comunes que pisen el slot, crea o mueve la reserva del partido (emisor único: `booking.*` con actor `tournament` + `occupancy.changed` con actor `api`) y auto-programa los hijos de la cadena en la misma cancha. `null` en los dos desprograma. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"scheduledAt\": \"2026-10-17T09:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"match\": {\n    \"id\": \"6f5e4d3c-bbbb-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"tournamentId\": \"9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d\",\n    \"phase\": \"GROUP\",\n    \"round\": 1,\n    \"groupId\": \"4d3c2b1a-aaaa-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"matchOrder\": 1,\n    \"team1Id\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"team2Id\": \"1a2b3c4d-2222-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"team1Label\": \"Los Halcones\",\n    \"team2Label\": \"Pareja #2\",\n    \"team1FromMatchId\": null,\n    \"team1FromOutcome\": null,\n    \"team2FromMatchId\": null,\n    \"team2FromOutcome\": null,\n    \"status\": \"COMPLETED\",\n    \"winnerTeamId\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"isWalkover\": false,\n    \"walkoverTeamId\": null,\n    \"sets\": [\n      {\n        \"team1\": 6,\n        \"team2\": 3\n      },\n      {\n        \"team1\": 7,\n        \"team2\": 5\n      }\n    ],\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"scheduledAt\": \"2026-10-17T09:00:00\"\n  }\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / TOURNAMENT_RULE_VIOLATION","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"La cancha tiene que ser del club del torneo. Después es el handler del panel: reglas de la fase de grupos (dos partidos del mismo grupo no comparten horario; una pareja descansa al menos 1 h), libera las reservas comunes que pisen el slot, crea o mueve la reserva del partido (emisor único: `booking.*` con actor `tournament` + `occupancy.changed` con actor `api`) y auto-programa los hijos de la cadena en la misma cancha. `null` en los dos desprograma. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"scheduledAt\": \"2026-10-17T09:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"La cancha tiene que ser del club del torneo. Después es el handler del panel: reglas de la fase de grupos (dos partidos del mismo grupo no comparten horario; una pareja descansa al menos 1 h), libera las reservas comunes que pisen el slot, crea o mueve la reserva del partido (emisor único: `booking.*` con actor `tournament` + `occupancy.changed` con actor `api`) y auto-programa los hijos de la cadena en la misma cancha. `null` en los dos desprograma. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"scheduledAt\": \"2026-10-17T09:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"La cancha tiene que ser del club del torneo. Después es el handler del panel: reglas de la fase de grupos (dos partidos del mismo grupo no comparten horario; una pareja descansa al menos 1 h), libera las reservas comunes que pisen el slot, crea o mueve la reserva del partido (emisor único: `booking.*` con actor `tournament` + `occupancy.changed` con actor `api`) y auto-programa los hijos de la cadena en la misma cancha. `null` en los dos desprograma. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"scheduledAt\": \"2026-10-17T09:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · TOURNAMENT_NOT_FOUND / TOURNAMENT_MATCH_NOT_FOUND / COURT_NOT_FOUND","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"La cancha tiene que ser del club del torneo. Después es el handler del panel: reglas de la fase de grupos (dos partidos del mismo grupo no comparten horario; una pareja descansa al menos 1 h), libera las reservas comunes que pisen el slot, crea o mueve la reserva del partido (emisor único: `booking.*` con actor `tournament` + `occupancy.changed` con actor `api`) y auto-programa los hijos de la cadena en la misma cancha. `null` en los dos desprograma. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"scheduledAt\": \"2026-10-17T09:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo no existe o no es de este club.\",\n  \"code\": \"TOURNAMENT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · TOURNAMENT_SCHEDULE_CONFLICT / BOOKING_CONFLICT / RESOURCE_NOT_COURT","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"La cancha tiene que ser del club del torneo. Después es el handler del panel: reglas de la fase de grupos (dos partidos del mismo grupo no comparten horario; una pareja descansa al menos 1 h), libera las reservas comunes que pisen el slot, crea o mueve la reserva del partido (emisor único: `booking.*` con actor `tournament` + `occupancy.changed` con actor `api`) y auto-programa los hijos de la cadena en la misma cancha. `null` en los dos desprograma. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"scheduledAt\": \"2026-10-17T09:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El horario choca con otro partido del grupo o con el descanso de una pareja.\",\n  \"code\": \"TOURNAMENT_SCHEDULE_CONFLICT\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"La cancha tiene que ser del club del torneo. Después es el handler del panel: reglas de la fase de grupos (dos partidos del mismo grupo no comparten horario; una pareja descansa al menos 1 h), libera las reservas comunes que pisen el slot, crea o mueve la reserva del partido (emisor único: `booking.*` con actor `tournament` + `occupancy.changed` con actor `api`) y auto-programa los hijos de la cadena en la misma cancha. `null` en los dos desprograma. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"scheduledAt\": \"2026-10-17T09:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"La cancha tiene que ser del club del torneo. Después es el handler del panel: reglas de la fase de grupos (dos partidos del mismo grupo no comparten horario; una pareja descansa al menos 1 h), libera las reservas comunes que pisen el slot, crea o mueve la reserva del partido (emisor único: `booking.*` con actor `tournament` + `occupancy.changed` con actor `api`) y auto-programa los hijos de la cadena en la misma cancha. `null` en los dos desprograma. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"scheduledAt\": \"2026-10-17T09:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"La cancha tiene que ser del club del torneo. Después es el handler del panel: reglas de la fase de grupos (dos partidos del mismo grupo no comparten horario; una pareja descansa al menos 1 h), libera las reservas comunes que pisen el slot, crea o mueve la reserva del partido (emisor único: `booking.*` con actor `tournament` + `occupancy.changed` con actor `api`) y auto-programa los hijos de la cadena en la misma cancha. `null` en los dos desprograma. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"scheduledAt\": \"2026-10-17T09:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/matches/:matchId/schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","matches",":matchId","schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"matchId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido (`TournamentMatchDto.id`), del torneo de la URL."}]},"description":"La cancha tiene que ser del club del torneo. Después es el handler del panel: reglas de la fase de grupos (dos partidos del mismo grupo no comparten horario; una pareja descansa al menos 1 h), libera las reservas comunes que pisen el slot, crea o mueve la reserva del partido (emisor único: `booking.*` con actor `tournament` + `occupancy.changed` con actor `api`) y auto-programa los hijos de la cadena en la misma cancha. `null` en los dos desprograma. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n  \"scheduledAt\": \"2026-10-17T09:00\"\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Tabla de posiciones por grupo (getTournamentStandings)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/standings","host":["{{baseUrl}}"],"path":["tournaments",":id","standings"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo que la app (ganados → diferencia de sets → diferencia de games; clasifican las 2 primeras). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"response":[{"name":"200 · Tablas.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/standings","host":["{{baseUrl}}"],"path":["tournaments",":id","standings"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo que la app (ganados → diferencia de sets → diferencia de games; clasifican las 2 primeras). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"groups\": [\n    {\n      \"groupId\": \"4d3c2b1a-aaaa-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"groupName\": \"A\",\n      \"standings\": [\n        {\n          \"teamId\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n          \"label\": \"Los Halcones\",\n          \"played\": 2,\n          \"won\": 2,\n          \"lost\": 0,\n          \"setsWon\": 4,\n          \"setsLost\": 1,\n          \"gamesWon\": 25,\n          \"gamesLost\": 14,\n          \"qualified\": true\n        }\n      ]\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/standings","host":["{{baseUrl}}"],"path":["tournaments",":id","standings"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo que la app (ganados → diferencia de sets → diferencia de games; clasifican las 2 primeras). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/standings","host":["{{baseUrl}}"],"path":["tournaments",":id","standings"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo que la app (ganados → diferencia de sets → diferencia de games; clasifican las 2 primeras). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/standings","host":["{{baseUrl}}"],"path":["tournaments",":id","standings"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo que la app (ganados → diferencia de sets → diferencia de games; clasifican las 2 primeras). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · TOURNAMENT_NOT_FOUND","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/standings","host":["{{baseUrl}}"],"path":["tournaments",":id","standings"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo que la app (ganados → diferencia de sets → diferencia de games; clasifican las 2 primeras). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo no existe o no es de este club.\",\n  \"code\": \"TOURNAMENT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/standings","host":["{{baseUrl}}"],"path":["tournaments",":id","standings"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo que la app (ganados → diferencia de sets → diferencia de games; clasifican las 2 primeras). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/standings","host":["{{baseUrl}}"],"path":["tournaments",":id","standings"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo que la app (ganados → diferencia de sets → diferencia de games; clasifican las 2 primeras). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/tournaments/:id/standings","host":["{{baseUrl}}"],"path":["tournaments",":id","standings"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo que la app (ganados → diferencia de sets → diferencia de games; clasifican las 2 primeras). Nunca datos de las personas que integran una pareja.\n\nScope: `tournaments:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Sugerir horarios por grupo (suggestTournamentSchedule)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/suggest-schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","suggest-schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo del panel: grupos en paralelo hasta la cantidad de canchas del club, 3 partidos consecutivos por grupo, por franja de preferencia. No escribe nada (después programás cada partido con `/matches/{matchId}/schedule`). Consume cuota de escritura por ser POST.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"saturdayMorningStart\": \"09:00\",\n  \"matchDuration\": 90\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · Sugerencia por grupo.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/suggest-schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","suggest-schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo del panel: grupos en paralelo hasta la cantidad de canchas del club, 3 partidos consecutivos por grupo, por franja de preferencia. No escribe nada (después programás cada partido con `/matches/{matchId}/schedule`). Consume cuota de escritura por ser POST.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"saturdayMorningStart\": \"09:00\",\n  \"matchDuration\": 90\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"schedule\": [\n    {\n      \"groupId\": \"4d3c2b1a-aaaa-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"groupName\": \"A\",\n      \"suggestedStartTime\": \"2026-10-17T12:00:00.000Z\",\n      \"timeSlot\": \"SATURDAY_MORNING\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / TOURNAMENT_RULE_VIOLATION","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/suggest-schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","suggest-schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo del panel: grupos en paralelo hasta la cantidad de canchas del club, 3 partidos consecutivos por grupo, por franja de preferencia. No escribe nada (después programás cada partido con `/matches/{matchId}/schedule`). Consume cuota de escritura por ser POST.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"saturdayMorningStart\": \"09:00\",\n  \"matchDuration\": 90\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/suggest-schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","suggest-schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo del panel: grupos en paralelo hasta la cantidad de canchas del club, 3 partidos consecutivos por grupo, por franja de preferencia. No escribe nada (después programás cada partido con `/matches/{matchId}/schedule`). Consume cuota de escritura por ser POST.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"saturdayMorningStart\": \"09:00\",\n  \"matchDuration\": 90\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/suggest-schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","suggest-schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo del panel: grupos en paralelo hasta la cantidad de canchas del club, 3 partidos consecutivos por grupo, por franja de preferencia. No escribe nada (después programás cada partido con `/matches/{matchId}/schedule`). Consume cuota de escritura por ser POST.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"saturdayMorningStart\": \"09:00\",\n  \"matchDuration\": 90\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · TOURNAMENT_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/suggest-schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","suggest-schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo del panel: grupos en paralelo hasta la cantidad de canchas del club, 3 partidos consecutivos por grupo, por franja de preferencia. No escribe nada (después programás cada partido con `/matches/{matchId}/schedule`). Consume cuota de escritura por ser POST.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"saturdayMorningStart\": \"09:00\",\n  \"matchDuration\": 90\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo no existe o no es de este club.\",\n  \"code\": \"TOURNAMENT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/suggest-schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","suggest-schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo del panel: grupos en paralelo hasta la cantidad de canchas del club, 3 partidos consecutivos por grupo, por franja de preferencia. No escribe nada (después programás cada partido con `/matches/{matchId}/schedule`). Consume cuota de escritura por ser POST.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"saturdayMorningStart\": \"09:00\",\n  \"matchDuration\": 90\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/suggest-schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","suggest-schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo del panel: grupos en paralelo hasta la cantidad de canchas del club, 3 partidos consecutivos por grupo, por franja de preferencia. No escribe nada (después programás cada partido con `/matches/{matchId}/schedule`). Consume cuota de escritura por ser POST.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"saturdayMorningStart\": \"09:00\",\n  \"matchDuration\": 90\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/suggest-schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","suggest-schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo del panel: grupos en paralelo hasta la cantidad de canchas del club, 3 partidos consecutivos por grupo, por franja de preferencia. No escribe nada (después programás cada partido con `/matches/{matchId}/schedule`). Consume cuota de escritura por ser POST.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"saturdayMorningStart\": \"09:00\",\n  \"matchDuration\": 90\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/suggest-schedule","host":["{{baseUrl}}"],"path":["tournaments",":id","suggest-schedule"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."}]},"description":"Mismo cálculo del panel: grupos en paralelo hasta la cantidad de canchas del club, 3 partidos consecutivos por grupo, por franja de preferencia. No escribe nada (después programás cada partido con `/matches/{matchId}/schedule`). Consume cuota de escritura por ser POST.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"saturdayMorningStart\": \"09:00\",\n  \"matchDuration\": 90\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Cobro, nombre de equipo o baja de una pareja (updateTournamentTeam)","request":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/teams/:teamId","host":["{{baseUrl}}"],"path":["tournaments",":id","teams",":teamId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"teamId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la pareja (`TeamDto.id`), de la categoría de la URL."}]},"description":"Lo que un POS necesita sin abrir el panel: marcar `paid`, poner o quitar el nombre de equipo, dar de baja (`WITHDRAWN`, avisa a los integrantes como lo hace la app) o reingresar (`REGISTERED`, si el cupo lo permite). Una pareja con partidos jugados no se da de baja; en un torneo terminal o sobre una ELIMINATED el estado no cambia (`paid` y `teamName` sí se editan siempre). Repetir el mismo `status` es un no-op sin avisos. Audit TOURNAMENT_TEAM_UPDATED (`details.fields`, sin nombres). Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"paid\": true\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · La pareja actualizada.","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/teams/:teamId","host":["{{baseUrl}}"],"path":["tournaments",":id","teams",":teamId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"teamId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la pareja (`TeamDto.id`), de la categoría de la URL."}]},"description":"Lo que un POS necesita sin abrir el panel: marcar `paid`, poner o quitar el nombre de equipo, dar de baja (`WITHDRAWN`, avisa a los integrantes como lo hace la app) o reingresar (`REGISTERED`, si el cupo lo permite). Una pareja con partidos jugados no se da de baja; en un torneo terminal o sobre una ELIMINATED el estado no cambia (`paid` y `teamName` sí se editan siempre). Repetir el mismo `status` es un no-op sin avisos. Audit TOURNAMENT_TEAM_UPDATED (`details.fields`, sin nombres). Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"paid\": true\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"team\": {\n    \"id\": \"1a2b3c4d-1111-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"label\": \"Los Halcones\",\n    \"teamName\": \"Los Halcones\",\n    \"seed\": 1,\n    \"groupId\": \"4d3c2b1a-aaaa-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"status\": \"REGISTERED\",\n    \"paid\": true,\n    \"registeredAt\": \"2026-09-18 12:05:00\"\n  }\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/teams/:teamId","host":["{{baseUrl}}"],"path":["tournaments",":id","teams",":teamId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"teamId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la pareja (`TeamDto.id`), de la categoría de la URL."}]},"description":"Lo que un POS necesita sin abrir el panel: marcar `paid`, poner o quitar el nombre de equipo, dar de baja (`WITHDRAWN`, avisa a los integrantes como lo hace la app) o reingresar (`REGISTERED`, si el cupo lo permite). Una pareja con partidos jugados no se da de baja; en un torneo terminal o sobre una ELIMINATED el estado no cambia (`paid` y `teamName` sí se editan siempre). Repetir el mismo `status` es un no-op sin avisos. Audit TOURNAMENT_TEAM_UPDATED (`details.fields`, sin nombres). Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"paid\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/teams/:teamId","host":["{{baseUrl}}"],"path":["tournaments",":id","teams",":teamId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"teamId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la pareja (`TeamDto.id`), de la categoría de la URL."}]},"description":"Lo que un POS necesita sin abrir el panel: marcar `paid`, poner o quitar el nombre de equipo, dar de baja (`WITHDRAWN`, avisa a los integrantes como lo hace la app) o reingresar (`REGISTERED`, si el cupo lo permite). Una pareja con partidos jugados no se da de baja; en un torneo terminal o sobre una ELIMINATED el estado no cambia (`paid` y `teamName` sí se editan siempre). Repetir el mismo `status` es un no-op sin avisos. Audit TOURNAMENT_TEAM_UPDATED (`details.fields`, sin nombres). Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"paid\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/teams/:teamId","host":["{{baseUrl}}"],"path":["tournaments",":id","teams",":teamId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"teamId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la pareja (`TeamDto.id`), de la categoría de la URL."}]},"description":"Lo que un POS necesita sin abrir el panel: marcar `paid`, poner o quitar el nombre de equipo, dar de baja (`WITHDRAWN`, avisa a los integrantes como lo hace la app) o reingresar (`REGISTERED`, si el cupo lo permite). Una pareja con partidos jugados no se da de baja; en un torneo terminal o sobre una ELIMINATED el estado no cambia (`paid` y `teamName` sí se editan siempre). Repetir el mismo `status` es un no-op sin avisos. Audit TOURNAMENT_TEAM_UPDATED (`details.fields`, sin nombres). Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"paid\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · TOURNAMENT_NOT_FOUND / TOURNAMENT_TEAM_NOT_FOUND","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/teams/:teamId","host":["{{baseUrl}}"],"path":["tournaments",":id","teams",":teamId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"teamId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la pareja (`TeamDto.id`), de la categoría de la URL."}]},"description":"Lo que un POS necesita sin abrir el panel: marcar `paid`, poner o quitar el nombre de equipo, dar de baja (`WITHDRAWN`, avisa a los integrantes como lo hace la app) o reingresar (`REGISTERED`, si el cupo lo permite). Una pareja con partidos jugados no se da de baja; en un torneo terminal o sobre una ELIMINATED el estado no cambia (`paid` y `teamName` sí se editan siempre). Repetir el mismo `status` es un no-op sin avisos. Audit TOURNAMENT_TEAM_UPDATED (`details.fields`, sin nombres). Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"paid\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo no existe o no es de este club.\",\n  \"code\": \"TOURNAMENT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · TOURNAMENT_ALREADY_PLAYED / TOURNAMENT_RULE_VIOLATION / TOURNAMENT_INVALID_TRANSITION","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/teams/:teamId","host":["{{baseUrl}}"],"path":["tournaments",":id","teams",":teamId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"teamId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la pareja (`TeamDto.id`), de la categoría de la URL."}]},"description":"Lo que un POS necesita sin abrir el panel: marcar `paid`, poner o quitar el nombre de equipo, dar de baja (`WITHDRAWN`, avisa a los integrantes como lo hace la app) o reingresar (`REGISTERED`, si el cupo lo permite). Una pareja con partidos jugados no se da de baja; en un torneo terminal o sobre una ELIMINATED el estado no cambia (`paid` y `teamName` sí se editan siempre). Repetir el mismo `status` es un no-op sin avisos. Audit TOURNAMENT_TEAM_UPDATED (`details.fields`, sin nombres). Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"paid\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El torneo ya tiene partidos jugados. Repetí con force=true para borrarlos.\",\n  \"code\": \"TOURNAMENT_ALREADY_PLAYED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/teams/:teamId","host":["{{baseUrl}}"],"path":["tournaments",":id","teams",":teamId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"teamId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la pareja (`TeamDto.id`), de la categoría de la URL."}]},"description":"Lo que un POS necesita sin abrir el panel: marcar `paid`, poner o quitar el nombre de equipo, dar de baja (`WITHDRAWN`, avisa a los integrantes como lo hace la app) o reingresar (`REGISTERED`, si el cupo lo permite). Una pareja con partidos jugados no se da de baja; en un torneo terminal o sobre una ELIMINATED el estado no cambia (`paid` y `teamName` sí se editan siempre). Repetir el mismo `status` es un no-op sin avisos. Audit TOURNAMENT_TEAM_UPDATED (`details.fields`, sin nombres). Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"paid\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/teams/:teamId","host":["{{baseUrl}}"],"path":["tournaments",":id","teams",":teamId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"teamId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la pareja (`TeamDto.id`), de la categoría de la URL."}]},"description":"Lo que un POS necesita sin abrir el panel: marcar `paid`, poner o quitar el nombre de equipo, dar de baja (`WITHDRAWN`, avisa a los integrantes como lo hace la app) o reingresar (`REGISTERED`, si el cupo lo permite). Una pareja con partidos jugados no se da de baja; en un torneo terminal o sobre una ELIMINATED el estado no cambia (`paid` y `teamName` sí se editan siempre). Repetir el mismo `status` es un no-op sin avisos. Audit TOURNAMENT_TEAM_UPDATED (`details.fields`, sin nombres). Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"paid\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/teams/:teamId","host":["{{baseUrl}}"],"path":["tournaments",":id","teams",":teamId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"teamId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la pareja (`TeamDto.id`), de la categoría de la URL."}]},"description":"Lo que un POS necesita sin abrir el panel: marcar `paid`, poner o quitar el nombre de equipo, dar de baja (`WITHDRAWN`, avisa a los integrantes como lo hace la app) o reingresar (`REGISTERED`, si el cupo lo permite). Una pareja con partidos jugados no se da de baja; en un torneo terminal o sobre una ELIMINATED el estado no cambia (`paid` y `teamName` sí se editan siempre). Repetir el mismo `status` es un no-op sin avisos. Audit TOURNAMENT_TEAM_UPDATED (`details.fields`, sin nombres). Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"paid\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/tournaments/:id/teams/:teamId","host":["{{baseUrl}}"],"path":["tournaments",":id","teams",":teamId"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`TournamentDto.id`)."},{"key":"teamId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la pareja (`TeamDto.id`), de la categoría de la URL."}]},"description":"Lo que un POS necesita sin abrir el panel: marcar `paid`, poner o quitar el nombre de equipo, dar de baja (`WITHDRAWN`, avisa a los integrantes como lo hace la app) o reingresar (`REGISTERED`, si el cupo lo permite). Una pareja con partidos jugados no se da de baja; en un torneo terminal o sobre una ELIMINATED el estado no cambia (`paid` y `teamName` sí se editan siempre). Repetir el mismo `status` es un no-op sin avisos. Audit TOURNAMENT_TEAM_UPDATED (`details.fields`, sin nombres). Nunca datos de las personas que integran una pareja. Consume cuota de escritura.\n\nScope: `tournaments:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"paid\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]}]},{"name":"Club","description":"Ficha, configuración de negocio, espacios y categorías de recurso del club.","item":[{"name":"Espacios y servicios del club (listClubAmenities)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los espacios y servicios (amenities) que el club tiene marcados, del catálogo de la plataforma. Orden: nombre.\n\nScope: `amenities:read`."},"response":[{"name":"200 · Los del club.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los espacios y servicios (amenities) que el club tiene marcados, del catálogo de la plataforma. Orden: nombre.\n\nScope: `amenities:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n  \"amenities\": [\n    {\n      \"id\": \"amen-wifi\",\n      \"name\": \"WiFi\",\n      \"icon\": \"wifi\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los espacios y servicios (amenities) que el club tiene marcados, del catálogo de la plataforma. Orden: nombre.\n\nScope: `amenities:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los espacios y servicios (amenities) que el club tiene marcados, del catálogo de la plataforma. Orden: nombre.\n\nScope: `amenities:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los espacios y servicios (amenities) que el club tiene marcados, del catálogo de la plataforma. Orden: nombre.\n\nScope: `amenities:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los espacios y servicios (amenities) que el club tiene marcados, del catálogo de la plataforma. Orden: nombre.\n\nScope: `amenities:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los espacios y servicios (amenities) que el club tiene marcados, del catálogo de la plataforma. Orden: nombre.\n\nScope: `amenities:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los espacios y servicios (amenities) que el club tiene marcados, del catálogo de la plataforma. Orden: nombre.\n\nScope: `amenities:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Reemplazar los espacios y servicios del club (replaceClubAmenities)","request":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"]},"description":"Reemplazo COMPLETO del conjunto (espejo de `PUT /club-owner/clubs/:id/amenities`): lo que no está en `ids` se quita; `[]` lo vacía. Un id fuera del catálogo rechaza todo sin escribir nada. Scope sensible `amenities:write`. Audit `CLUB_AMENITIES_UPDATED`. Consume cuota de escritura.\n\nScope: `amenities:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"ids\": [\n    \"amen-wifi\",\n    \"amen-estacionamiento\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · El conjunto resultante.","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"]},"description":"Reemplazo COMPLETO del conjunto (espejo de `PUT /club-owner/clubs/:id/amenities`): lo que no está en `ids` se quita; `[]` lo vacía. Un id fuera del catálogo rechaza todo sin escribir nada. Scope sensible `amenities:write`. Audit `CLUB_AMENITIES_UPDATED`. Consume cuota de escritura.\n\nScope: `amenities:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"ids\": [\n    \"amen-wifi\",\n    \"amen-estacionamiento\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n  \"amenities\": [\n    {\n      \"id\": \"amen-wifi\",\n      \"name\": \"WiFi\",\n      \"icon\": \"wifi\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"]},"description":"Reemplazo COMPLETO del conjunto (espejo de `PUT /club-owner/clubs/:id/amenities`): lo que no está en `ids` se quita; `[]` lo vacía. Un id fuera del catálogo rechaza todo sin escribir nada. Scope sensible `amenities:write`. Audit `CLUB_AMENITIES_UPDATED`. Consume cuota de escritura.\n\nScope: `amenities:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"ids\": [\n    \"amen-wifi\",\n    \"amen-estacionamiento\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"]},"description":"Reemplazo COMPLETO del conjunto (espejo de `PUT /club-owner/clubs/:id/amenities`): lo que no está en `ids` se quita; `[]` lo vacía. Un id fuera del catálogo rechaza todo sin escribir nada. Scope sensible `amenities:write`. Audit `CLUB_AMENITIES_UPDATED`. Consume cuota de escritura.\n\nScope: `amenities:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"ids\": [\n    \"amen-wifi\",\n    \"amen-estacionamiento\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"]},"description":"Reemplazo COMPLETO del conjunto (espejo de `PUT /club-owner/clubs/:id/amenities`): lo que no está en `ids` se quita; `[]` lo vacía. Un id fuera del catálogo rechaza todo sin escribir nada. Scope sensible `amenities:write`. Audit `CLUB_AMENITIES_UPDATED`. Consume cuota de escritura.\n\nScope: `amenities:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"ids\": [\n    \"amen-wifi\",\n    \"amen-estacionamiento\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · AMENITY_NOT_FOUND","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"]},"description":"Reemplazo COMPLETO del conjunto (espejo de `PUT /club-owner/clubs/:id/amenities`): lo que no está en `ids` se quita; `[]` lo vacía. Un id fuera del catálogo rechaza todo sin escribir nada. Scope sensible `amenities:write`. Audit `CLUB_AMENITIES_UPDATED`. Consume cuota de escritura.\n\nScope: `amenities:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"ids\": [\n    \"amen-wifi\",\n    \"amen-estacionamiento\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Algún espacio o servicio no existe en el catálogo: mirá GET /amenities/catalog.\",\n  \"code\": \"AMENITY_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"]},"description":"Reemplazo COMPLETO del conjunto (espejo de `PUT /club-owner/clubs/:id/amenities`): lo que no está en `ids` se quita; `[]` lo vacía. Un id fuera del catálogo rechaza todo sin escribir nada. Scope sensible `amenities:write`. Audit `CLUB_AMENITIES_UPDATED`. Consume cuota de escritura.\n\nScope: `amenities:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"ids\": [\n    \"amen-wifi\",\n    \"amen-estacionamiento\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"]},"description":"Reemplazo COMPLETO del conjunto (espejo de `PUT /club-owner/clubs/:id/amenities`): lo que no está en `ids` se quita; `[]` lo vacía. Un id fuera del catálogo rechaza todo sin escribir nada. Scope sensible `amenities:write`. Audit `CLUB_AMENITIES_UPDATED`. Consume cuota de escritura.\n\nScope: `amenities:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"ids\": [\n    \"amen-wifi\",\n    \"amen-estacionamiento\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"]},"description":"Reemplazo COMPLETO del conjunto (espejo de `PUT /club-owner/clubs/:id/amenities`): lo que no está en `ids` se quita; `[]` lo vacía. Un id fuera del catálogo rechaza todo sin escribir nada. Scope sensible `amenities:write`. Audit `CLUB_AMENITIES_UPDATED`. Consume cuota de escritura.\n\nScope: `amenities:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"ids\": [\n    \"amen-wifi\",\n    \"amen-estacionamiento\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PUT","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/amenities","host":["{{baseUrl}}"],"path":["amenities"]},"description":"Reemplazo COMPLETO del conjunto (espejo de `PUT /club-owner/clubs/:id/amenities`): lo que no está en `ids` se quita; `[]` lo vacía. Un id fuera del catálogo rechaza todo sin escribir nada. Scope sensible `amenities:write`. Audit `CLUB_AMENITIES_UPDATED`. Consume cuota de escritura.\n\nScope: `amenities:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"ids\": [\n    \"amen-wifi\",\n    \"amen-estacionamiento\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Catálogo de espacios y servicios (listAmenityCatalog)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities/catalog","host":["{{baseUrl}}"],"path":["amenities","catalog"]},"description":"Todo el catálogo de la plataforma (lo define Skalia): los ids que acepta `PUT /amenities`. Orden: nombre. Es un recurso global: no lleva `clubId` (el scope `amenities:read` se evalúa sobre la key, como `/me`).\n\nScope: `amenities:read`."},"response":[{"name":"200 · El catálogo.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities/catalog","host":["{{baseUrl}}"],"path":["amenities","catalog"]},"description":"Todo el catálogo de la plataforma (lo define Skalia): los ids que acepta `PUT /amenities`. Orden: nombre. Es un recurso global: no lleva `clubId` (el scope `amenities:read` se evalúa sobre la key, como `/me`).\n\nScope: `amenities:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"amenities\": [\n    {\n      \"id\": \"amen-wifi\",\n      \"name\": \"WiFi\",\n      \"icon\": \"wifi\"\n    },\n    {\n      \"id\": \"amen-estacionamiento\",\n      \"name\": \"Estacionamiento\",\n      \"icon\": \"local_parking\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities/catalog","host":["{{baseUrl}}"],"path":["amenities","catalog"]},"description":"Todo el catálogo de la plataforma (lo define Skalia): los ids que acepta `PUT /amenities`. Orden: nombre. Es un recurso global: no lleva `clubId` (el scope `amenities:read` se evalúa sobre la key, como `/me`).\n\nScope: `amenities:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities/catalog","host":["{{baseUrl}}"],"path":["amenities","catalog"]},"description":"Todo el catálogo de la plataforma (lo define Skalia): los ids que acepta `PUT /amenities`. Orden: nombre. Es un recurso global: no lleva `clubId` (el scope `amenities:read` se evalúa sobre la key, como `/me`).\n\nScope: `amenities:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities/catalog","host":["{{baseUrl}}"],"path":["amenities","catalog"]},"description":"Todo el catálogo de la plataforma (lo define Skalia): los ids que acepta `PUT /amenities`. Orden: nombre. Es un recurso global: no lleva `clubId` (el scope `amenities:read` se evalúa sobre la key, como `/me`).\n\nScope: `amenities:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities/catalog","host":["{{baseUrl}}"],"path":["amenities","catalog"]},"description":"Todo el catálogo de la plataforma (lo define Skalia): los ids que acepta `PUT /amenities`. Orden: nombre. Es un recurso global: no lleva `clubId` (el scope `amenities:read` se evalúa sobre la key, como `/me`).\n\nScope: `amenities:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities/catalog","host":["{{baseUrl}}"],"path":["amenities","catalog"]},"description":"Todo el catálogo de la plataforma (lo define Skalia): los ids que acepta `PUT /amenities`. Orden: nombre. Es un recurso global: no lleva `clubId` (el scope `amenities:read` se evalúa sobre la key, como `/me`).\n\nScope: `amenities:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/amenities/catalog","host":["{{baseUrl}}"],"path":["amenities","catalog"]},"description":"Todo el catálogo de la plataforma (lo define Skalia): los ids que acepta `PUT /amenities`. Orden: nombre. Es un recurso global: no lleva `clubId` (el scope `amenities:read` se evalúa sobre la key, como `/me`).\n\nScope: `amenities:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Ficha del club (getClub)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La ficha pública del club, sus banderas de plataforma (`modules`), su configuración de negocio (`settings`, la misma de `GET /settings`) y sus seguidores en Skalia (`followers`: `total` como prueba social, `notifiable` como audiencia real de los avisos; sólo dos enteros). Nunca credenciales (streaming, ingest, tokens) ni datos de personas.\n\nScope: `club:read`."},"response":[{"name":"200 · La ficha.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La ficha pública del club, sus banderas de plataforma (`modules`), su configuración de negocio (`settings`, la misma de `GET /settings`) y sus seguidores en Skalia (`followers`: `total` como prueba social, `notifiable` como audiencia real de los avisos; sólo dos enteros). Nunca credenciales (streaming, ingest, tokens) ni datos de personas.\n\nScope: `club:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"id\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n  \"name\": \"Club Norte\",\n  \"description\": \"Cuatro canchas de pádel techadas.\",\n  \"address\": \"Av. Italia 1234\",\n  \"city\": \"Montevideo\",\n  \"latitude\": -34.8836,\n  \"longitude\": -56.1284,\n  \"phone\": \"+59899000000\",\n  \"website\": \"https://clubnorte.uy\",\n  \"email\": \"hola@clubnorte.uy\",\n  \"instagram\": \"clubnorte\",\n  \"facebook\": null,\n  \"logoUrl\": \"https://assets.skaliasports.com/clubs/norte.png\",\n  \"timezone\": \"America/Montevideo\",\n  \"currency\": \"UYU\",\n  \"countryCode\": \"598\",\n  \"sports\": [\n    \"PADEL\"\n  ],\n  \"modules\": {\n    \"bookings\": true,\n    \"api\": true,\n    \"streaming\": false,\n    \"resourceCategories\": false\n  },\n  \"settings\": {\n    \"bookingPolicy\": \"AUTO_CONFIRM\",\n    \"cancellationWindowHours\": 2,\n    \"noShowGraceMinutes\": 30,\n    \"maxBookingsPerUserPerDay\": null,\n    \"maxAdvanceBookingDays\": 30,\n    \"requirePayment\": false,\n    \"currency\": \"UYU\",\n    \"timezone\": \"America/Montevideo\",\n    \"peakHoursEnabled\": true,\n    \"peakHoursStart\": \"18:00\",\n    \"peakHoursEnd\": \"23:00\",\n    \"peakHoursDays\": [\n      1,\n      2,\n      3,\n      4,\n      5\n    ],\n    \"spontaneousCategories\": [],\n    \"updatedAt\": \"2026-09-14T12:00:00.000Z\"\n  },\n  \"followers\": {\n    \"total\": 128,\n    \"notifiable\": 97\n  }\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La ficha pública del club, sus banderas de plataforma (`modules`), su configuración de negocio (`settings`, la misma de `GET /settings`) y sus seguidores en Skalia (`followers`: `total` como prueba social, `notifiable` como audiencia real de los avisos; sólo dos enteros). Nunca credenciales (streaming, ingest, tokens) ni datos de personas.\n\nScope: `club:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La ficha pública del club, sus banderas de plataforma (`modules`), su configuración de negocio (`settings`, la misma de `GET /settings`) y sus seguidores en Skalia (`followers`: `total` como prueba social, `notifiable` como audiencia real de los avisos; sólo dos enteros). Nunca credenciales (streaming, ingest, tokens) ni datos de personas.\n\nScope: `club:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La ficha pública del club, sus banderas de plataforma (`modules`), su configuración de negocio (`settings`, la misma de `GET /settings`) y sus seguidores en Skalia (`followers`: `total` como prueba social, `notifiable` como audiencia real de los avisos; sólo dos enteros). Nunca credenciales (streaming, ingest, tokens) ni datos de personas.\n\nScope: `club:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La ficha pública del club, sus banderas de plataforma (`modules`), su configuración de negocio (`settings`, la misma de `GET /settings`) y sus seguidores en Skalia (`followers`: `total` como prueba social, `notifiable` como audiencia real de los avisos; sólo dos enteros). Nunca credenciales (streaming, ingest, tokens) ni datos de personas.\n\nScope: `club:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La ficha pública del club, sus banderas de plataforma (`modules`), su configuración de negocio (`settings`, la misma de `GET /settings`) y sus seguidores en Skalia (`followers`: `total` como prueba social, `notifiable` como audiencia real de los avisos; sólo dos enteros). Nunca credenciales (streaming, ingest, tokens) ni datos de personas.\n\nScope: `club:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La ficha pública del club, sus banderas de plataforma (`modules`), su configuración de negocio (`settings`, la misma de `GET /settings`) y sus seguidores en Skalia (`followers`: `total` como prueba social, `notifiable` como audiencia real de los avisos; sólo dos enteros). Nunca credenciales (streaming, ingest, tokens) ni datos de personas.\n\nScope: `club:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Editar la ficha del club (updateClub)","request":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"]},"description":"Edición parcial de texto, coordenadas y URL https del logo (sin subir binarios: el logo se aloja fuera del storage de Skalia). Scope sensible `club:write` (sólo el OWNER emite una key que lo incluya). Audit `CLUB_UPDATED` (con los valores enviados). Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"description\": \"Cuatro canchas de pádel techadas.\",\n  \"phone\": \"+59899000000\",\n  \"website\": \"https://clubnorte.uy\"\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · La ficha actualizada.","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"]},"description":"Edición parcial de texto, coordenadas y URL https del logo (sin subir binarios: el logo se aloja fuera del storage de Skalia). Scope sensible `club:write` (sólo el OWNER emite una key que lo incluya). Audit `CLUB_UPDATED` (con los valores enviados). Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"description\": \"Cuatro canchas de pádel techadas.\",\n  \"phone\": \"+59899000000\",\n  \"website\": \"https://clubnorte.uy\"\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"id\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n  \"name\": \"Club Norte\",\n  \"description\": \"Cuatro canchas de pádel techadas.\",\n  \"address\": \"Av. Italia 1234\",\n  \"city\": \"Montevideo\",\n  \"latitude\": -34.8836,\n  \"longitude\": -56.1284,\n  \"phone\": \"+59899000000\",\n  \"website\": \"https://clubnorte.uy\",\n  \"email\": \"hola@clubnorte.uy\",\n  \"instagram\": \"clubnorte\",\n  \"facebook\": null,\n  \"logoUrl\": \"https://assets.skaliasports.com/clubs/norte.png\",\n  \"timezone\": \"America/Montevideo\",\n  \"currency\": \"UYU\",\n  \"countryCode\": \"598\",\n  \"sports\": [\n    \"PADEL\"\n  ],\n  \"modules\": {\n    \"bookings\": true,\n    \"api\": true,\n    \"streaming\": false,\n    \"resourceCategories\": false\n  },\n  \"settings\": {\n    \"bookingPolicy\": \"AUTO_CONFIRM\",\n    \"cancellationWindowHours\": 2,\n    \"noShowGraceMinutes\": 30,\n    \"maxBookingsPerUserPerDay\": null,\n    \"maxAdvanceBookingDays\": 30,\n    \"requirePayment\": false,\n    \"currency\": \"UYU\",\n    \"timezone\": \"America/Montevideo\",\n    \"peakHoursEnabled\": true,\n    \"peakHoursStart\": \"18:00\",\n    \"peakHoursEnd\": \"23:00\",\n    \"peakHoursDays\": [\n      1,\n      2,\n      3,\n      4,\n      5\n    ],\n    \"spontaneousCategories\": [],\n    \"updatedAt\": \"2026-09-14T12:00:00.000Z\"\n  },\n  \"followers\": {\n    \"total\": 128,\n    \"notifiable\": 97\n  }\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED / LOGO_URL_RESERVED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"]},"description":"Edición parcial de texto, coordenadas y URL https del logo (sin subir binarios: el logo se aloja fuera del storage de Skalia). Scope sensible `club:write` (sólo el OWNER emite una key que lo incluya). Audit `CLUB_UPDATED` (con los valores enviados). Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"description\": \"Cuatro canchas de pádel techadas.\",\n  \"phone\": \"+59899000000\",\n  \"website\": \"https://clubnorte.uy\"\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"]},"description":"Edición parcial de texto, coordenadas y URL https del logo (sin subir binarios: el logo se aloja fuera del storage de Skalia). Scope sensible `club:write` (sólo el OWNER emite una key que lo incluya). Audit `CLUB_UPDATED` (con los valores enviados). Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"description\": \"Cuatro canchas de pádel techadas.\",\n  \"phone\": \"+59899000000\",\n  \"website\": \"https://clubnorte.uy\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"]},"description":"Edición parcial de texto, coordenadas y URL https del logo (sin subir binarios: el logo se aloja fuera del storage de Skalia). Scope sensible `club:write` (sólo el OWNER emite una key que lo incluya). Audit `CLUB_UPDATED` (con los valores enviados). Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"description\": \"Cuatro canchas de pádel techadas.\",\n  \"phone\": \"+59899000000\",\n  \"website\": \"https://clubnorte.uy\"\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"]},"description":"Edición parcial de texto, coordenadas y URL https del logo (sin subir binarios: el logo se aloja fuera del storage de Skalia). Scope sensible `club:write` (sólo el OWNER emite una key que lo incluya). Audit `CLUB_UPDATED` (con los valores enviados). Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"description\": \"Cuatro canchas de pádel techadas.\",\n  \"phone\": \"+59899000000\",\n  \"website\": \"https://clubnorte.uy\"\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"]},"description":"Edición parcial de texto, coordenadas y URL https del logo (sin subir binarios: el logo se aloja fuera del storage de Skalia). Scope sensible `club:write` (sólo el OWNER emite una key que lo incluya). Audit `CLUB_UPDATED` (con los valores enviados). Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"description\": \"Cuatro canchas de pádel techadas.\",\n  \"phone\": \"+59899000000\",\n  \"website\": \"https://clubnorte.uy\"\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"]},"description":"Edición parcial de texto, coordenadas y URL https del logo (sin subir binarios: el logo se aloja fuera del storage de Skalia). Scope sensible `club:write` (sólo el OWNER emite una key que lo incluya). Audit `CLUB_UPDATED` (con los valores enviados). Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"description\": \"Cuatro canchas de pádel techadas.\",\n  \"phone\": \"+59899000000\",\n  \"website\": \"https://clubnorte.uy\"\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/club","host":["{{baseUrl}}"],"path":["club"]},"description":"Edición parcial de texto, coordenadas y URL https del logo (sin subir binarios: el logo se aloja fuera del storage de Skalia). Scope sensible `club:write` (sólo el OWNER emite una key que lo incluya). Audit `CLUB_UPDATED` (con los valores enviados). Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"description\": \"Cuatro canchas de pádel techadas.\",\n  \"phone\": \"+59899000000\",\n  \"website\": \"https://clubnorte.uy\"\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Categorías de recurso del club (listResourceCategories)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Todas las categorías de recurso (F6) del club, deshabilitadas y default incluidas, más `moduleEnabled` (si el módulo está apagado la lectura igual responde; las escrituras no).\n\nScope: `club:read`."},"response":[{"name":"200 · Las categorías.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Todas las categorías de recurso (F6) del club, deshabilitadas y default incluidas, más `moduleEnabled` (si el módulo está apagado la lectura igual responde; las escrituras no).\n\nScope: `club:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n  \"moduleEnabled\": true,\n  \"categories\": [\n    {\n      \"id\": \"3c9d2f10-7a4b-4e5c-9d6e-1f2a3b4c5d6e\",\n      \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n      \"kind\": \"CLINIC\",\n      \"resourceNoun\": \"PROFESSIONAL\",\n      \"label\": \"Clínica\",\n      \"icon\": \"medical_services\",\n      \"sortOrder\": 2,\n      \"enabled\": true,\n      \"isDefault\": false,\n      \"bookingPolicy\": \"MANUAL\",\n      \"pricingMode\": \"FLAT\",\n      \"priceUnit\": \"TURN\",\n      \"allowedDurations\": [\n        30,\n        60\n      ],\n      \"defaultDurationMinutes\": 30,\n      \"approvalTimeoutHours\": 2,\n      \"approvalGraceMinutes\": 60,\n      \"cancellationWindowHours\": 24,\n      \"awardsPoints\": false,\n      \"resourceCount\": 1\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Todas las categorías de recurso (F6) del club, deshabilitadas y default incluidas, más `moduleEnabled` (si el módulo está apagado la lectura igual responde; las escrituras no).\n\nScope: `club:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Todas las categorías de recurso (F6) del club, deshabilitadas y default incluidas, más `moduleEnabled` (si el módulo está apagado la lectura igual responde; las escrituras no).\n\nScope: `club:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Todas las categorías de recurso (F6) del club, deshabilitadas y default incluidas, más `moduleEnabled` (si el módulo está apagado la lectura igual responde; las escrituras no).\n\nScope: `club:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Todas las categorías de recurso (F6) del club, deshabilitadas y default incluidas, más `moduleEnabled` (si el módulo está apagado la lectura igual responde; las escrituras no).\n\nScope: `club:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Todas las categorías de recurso (F6) del club, deshabilitadas y default incluidas, más `moduleEnabled` (si el módulo está apagado la lectura igual responde; las escrituras no).\n\nScope: `club:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Todas las categorías de recurso (F6) del club, deshabilitadas y default incluidas, más `moduleEnabled` (si el módulo está apagado la lectura igual responde; las escrituras no).\n\nScope: `club:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Crear una categoría de recurso (createResourceCategory)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"]},"description":"Espejo de `POST /club-owner/clubs/:clubId/resource-categories`, con los mismos defaults por kind y gates. La PRIMERA categoría de un club con canchas sin categoría materializa \"Canchas\" (`defaultCourtCategoryId`). Exige el módulo de categorías del club (lo prende Skalia). Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_CREATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"kind\": \"CLINIC\",\n  \"label\": \"Clínica\",\n  \"bookingPolicy\": \"MANUAL\",\n  \"pricingMode\": \"FLAT\",\n  \"allowedDurations\": [\n    30,\n    60\n  ],\n  \"cancellationWindowHours\": 24\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"201 · Creada.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"]},"description":"Espejo de `POST /club-owner/clubs/:clubId/resource-categories`, con los mismos defaults por kind y gates. La PRIMERA categoría de un club con canchas sin categoría materializa \"Canchas\" (`defaultCourtCategoryId`). Exige el módulo de categorías del club (lo prende Skalia). Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_CREATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"kind\": \"CLINIC\",\n  \"label\": \"Clínica\",\n  \"bookingPolicy\": \"MANUAL\",\n  \"pricingMode\": \"FLAT\",\n  \"allowedDurations\": [\n    30,\n    60\n  ],\n  \"cancellationWindowHours\": 24\n}","options":{"raw":{"language":"json"}}}},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"category\": {\n    \"id\": \"3c9d2f10-7a4b-4e5c-9d6e-1f2a3b4c5d6e\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"kind\": \"CLINIC\",\n    \"resourceNoun\": \"PROFESSIONAL\",\n    \"label\": \"Clínica\",\n    \"icon\": \"medical_services\",\n    \"sortOrder\": 2,\n    \"enabled\": true,\n    \"isDefault\": false,\n    \"bookingPolicy\": \"MANUAL\",\n    \"pricingMode\": \"FLAT\",\n    \"priceUnit\": \"TURN\",\n    \"allowedDurations\": [\n      30,\n      60\n    ],\n    \"defaultDurationMinutes\": 30,\n    \"approvalTimeoutHours\": 2,\n    \"approvalGraceMinutes\": 60,\n    \"cancellationWindowHours\": 24,\n    \"awardsPoints\": false,\n    \"resourceCount\": 1\n  },\n  \"defaultCourtCategoryId\": null\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED / INVALID_CATEGORY_INPUT / RESOURCE_KIND_UNSUPPORTED / AWARDS_POINTS_NOT_ALLOWED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"]},"description":"Espejo de `POST /club-owner/clubs/:clubId/resource-categories`, con los mismos defaults por kind y gates. La PRIMERA categoría de un club con canchas sin categoría materializa \"Canchas\" (`defaultCourtCategoryId`). Exige el módulo de categorías del club (lo prende Skalia). Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_CREATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"kind\": \"CLINIC\",\n  \"label\": \"Clínica\",\n  \"bookingPolicy\": \"MANUAL\",\n  \"pricingMode\": \"FLAT\",\n  \"allowedDurations\": [\n    30,\n    60\n  ],\n  \"cancellationWindowHours\": 24\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"]},"description":"Espejo de `POST /club-owner/clubs/:clubId/resource-categories`, con los mismos defaults por kind y gates. La PRIMERA categoría de un club con canchas sin categoría materializa \"Canchas\" (`defaultCourtCategoryId`). Exige el módulo de categorías del club (lo prende Skalia). Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_CREATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"kind\": \"CLINIC\",\n  \"label\": \"Clínica\",\n  \"bookingPolicy\": \"MANUAL\",\n  \"pricingMode\": \"FLAT\",\n  \"allowedDurations\": [\n    30,\n    60\n  ],\n  \"cancellationWindowHours\": 24\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED / RESOURCE_CATEGORIES_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"]},"description":"Espejo de `POST /club-owner/clubs/:clubId/resource-categories`, con los mismos defaults por kind y gates. La PRIMERA categoría de un club con canchas sin categoría materializa \"Canchas\" (`defaultCourtCategoryId`). Exige el módulo de categorías del club (lo prende Skalia). Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_CREATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"kind\": \"CLINIC\",\n  \"label\": \"Clínica\",\n  \"bookingPolicy\": \"MANUAL\",\n  \"pricingMode\": \"FLAT\",\n  \"allowedDurations\": [\n    30,\n    60\n  ],\n  \"cancellationWindowHours\": 24\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"]},"description":"Espejo de `POST /club-owner/clubs/:clubId/resource-categories`, con los mismos defaults por kind y gates. La PRIMERA categoría de un club con canchas sin categoría materializa \"Canchas\" (`defaultCourtCategoryId`). Exige el módulo de categorías del club (lo prende Skalia). Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_CREATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"kind\": \"CLINIC\",\n  \"label\": \"Clínica\",\n  \"bookingPolicy\": \"MANUAL\",\n  \"pricingMode\": \"FLAT\",\n  \"allowedDurations\": [\n    30,\n    60\n  ],\n  \"cancellationWindowHours\": 24\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"]},"description":"Espejo de `POST /club-owner/clubs/:clubId/resource-categories`, con los mismos defaults por kind y gates. La PRIMERA categoría de un club con canchas sin categoría materializa \"Canchas\" (`defaultCourtCategoryId`). Exige el módulo de categorías del club (lo prende Skalia). Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_CREATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"kind\": \"CLINIC\",\n  \"label\": \"Clínica\",\n  \"bookingPolicy\": \"MANUAL\",\n  \"pricingMode\": \"FLAT\",\n  \"allowedDurations\": [\n    30,\n    60\n  ],\n  \"cancellationWindowHours\": 24\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"]},"description":"Espejo de `POST /club-owner/clubs/:clubId/resource-categories`, con los mismos defaults por kind y gates. La PRIMERA categoría de un club con canchas sin categoría materializa \"Canchas\" (`defaultCourtCategoryId`). Exige el módulo de categorías del club (lo prende Skalia). Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_CREATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"kind\": \"CLINIC\",\n  \"label\": \"Clínica\",\n  \"bookingPolicy\": \"MANUAL\",\n  \"pricingMode\": \"FLAT\",\n  \"allowedDurations\": [\n    30,\n    60\n  ],\n  \"cancellationWindowHours\": 24\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories","host":["{{baseUrl}}"],"path":["resource-categories"]},"description":"Espejo de `POST /club-owner/clubs/:clubId/resource-categories`, con los mismos defaults por kind y gates. La PRIMERA categoría de un club con canchas sin categoría materializa \"Canchas\" (`defaultCourtCategoryId`). Exige el módulo de categorías del club (lo prende Skalia). Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_CREATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"kind\": \"CLINIC\",\n  \"label\": \"Clínica\",\n  \"bookingPolicy\": \"MANUAL\",\n  \"pricingMode\": \"FLAT\",\n  \"allowedDurations\": [\n    30,\n    60\n  ],\n  \"cancellationWindowHours\": 24\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Editar una categoría de recurso (updateResourceCategory)","request":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `PATCH /club-owner/resource-categories/:id`: parcial; `kind` inmutable; `resourceNoun` sólo cambia sin recursos; cambiar `allowedDurations` sin `defaultDurationMinutes` la recalcula. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"label\": \"Consultorios\",\n  \"enabled\": true\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · La categoría actualizada.","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `PATCH /club-owner/resource-categories/:id`: parcial; `kind` inmutable; `resourceNoun` sólo cambia sin recursos; cambiar `allowedDurations` sin `defaultDurationMinutes` la recalcula. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"label\": \"Consultorios\",\n  \"enabled\": true\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"category\": {\n    \"id\": \"3c9d2f10-7a4b-4e5c-9d6e-1f2a3b4c5d6e\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"kind\": \"CLINIC\",\n    \"resourceNoun\": \"PROFESSIONAL\",\n    \"label\": \"Clínica\",\n    \"icon\": \"medical_services\",\n    \"sortOrder\": 2,\n    \"enabled\": true,\n    \"isDefault\": false,\n    \"bookingPolicy\": \"MANUAL\",\n    \"pricingMode\": \"FLAT\",\n    \"priceUnit\": \"TURN\",\n    \"allowedDurations\": [\n      30,\n      60\n    ],\n    \"defaultDurationMinutes\": 30,\n    \"approvalTimeoutHours\": 2,\n    \"approvalGraceMinutes\": 60,\n    \"cancellationWindowHours\": 24,\n    \"awardsPoints\": false,\n    \"resourceCount\": 1\n  }\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / RESOURCE_KIND_CHANGE_NOT_ALLOWED / INVALID_CATEGORY_INPUT / RESOURCE_KIND_UNSUPPORTED / AWARDS_POINTS_NOT_ALLOWED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `PATCH /club-owner/resource-categories/:id`: parcial; `kind` inmutable; `resourceNoun` sólo cambia sin recursos; cambiar `allowedDurations` sin `defaultDurationMinutes` la recalcula. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"label\": \"Consultorios\",\n  \"enabled\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `PATCH /club-owner/resource-categories/:id`: parcial; `kind` inmutable; `resourceNoun` sólo cambia sin recursos; cambiar `allowedDurations` sin `defaultDurationMinutes` la recalcula. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"label\": \"Consultorios\",\n  \"enabled\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED / RESOURCE_CATEGORIES_DISABLED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `PATCH /club-owner/resource-categories/:id`: parcial; `kind` inmutable; `resourceNoun` sólo cambia sin recursos; cambiar `allowedDurations` sin `defaultDurationMinutes` la recalcula. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"label\": \"Consultorios\",\n  \"enabled\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · CATEGORY_NOT_FOUND","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `PATCH /club-owner/resource-categories/:id`: parcial; `kind` inmutable; `resourceNoun` sólo cambia sin recursos; cambiar `allowedDurations` sin `defaultDurationMinutes` la recalcula. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"label\": \"Consultorios\",\n  \"enabled\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La categoría no existe o no es de este club.\",\n  \"code\": \"CATEGORY_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · CATEGORY_HAS_RESOURCES","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `PATCH /club-owner/resource-categories/:id`: parcial; `kind` inmutable; `resourceNoun` sólo cambia sin recursos; cambiar `allowedDurations` sin `defaultDurationMinutes` la recalcula. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"label\": \"Consultorios\",\n  \"enabled\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La categoría tiene recursos: movelos o borralos antes.\",\n  \"code\": \"CATEGORY_HAS_RESOURCES\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `PATCH /club-owner/resource-categories/:id`: parcial; `kind` inmutable; `resourceNoun` sólo cambia sin recursos; cambiar `allowedDurations` sin `defaultDurationMinutes` la recalcula. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"label\": \"Consultorios\",\n  \"enabled\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `PATCH /club-owner/resource-categories/:id`: parcial; `kind` inmutable; `resourceNoun` sólo cambia sin recursos; cambiar `allowedDurations` sin `defaultDurationMinutes` la recalcula. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"label\": \"Consultorios\",\n  \"enabled\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `PATCH /club-owner/resource-categories/:id`: parcial; `kind` inmutable; `resourceNoun` sólo cambia sin recursos; cambiar `allowedDurations` sin `defaultDurationMinutes` la recalcula. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"label\": \"Consultorios\",\n  \"enabled\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `PATCH /club-owner/resource-categories/:id`: parcial; `kind` inmutable; `resourceNoun` sólo cambia sin recursos; cambiar `allowedDurations` sin `defaultDurationMinutes` la recalcula. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"label\": \"Consultorios\",\n  \"enabled\": true\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Borrar una categoría de recurso (deleteResourceCategory)","request":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `DELETE /club-owner/resource-categories/:id`: sólo una categoría vacía y que no sea la \"Canchas\" materializada. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_DELETED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura."},"response":[{"name":"200 · Borrada.","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `DELETE /club-owner/resource-categories/:id`: sólo una categoría vacía y que no sea la \"Canchas\" materializada. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_DELETED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"deleted\": true,\n  \"categoryId\": \"3c9d2f10-7a4b-4e5c-9d6e-1f2a3b4c5d6e\"\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `DELETE /club-owner/resource-categories/:id`: sólo una categoría vacía y que no sea la \"Canchas\" materializada. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_DELETED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `DELETE /club-owner/resource-categories/:id`: sólo una categoría vacía y que no sea la \"Canchas\" materializada. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_DELETED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED / RESOURCE_CATEGORIES_DISABLED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `DELETE /club-owner/resource-categories/:id`: sólo una categoría vacía y que no sea la \"Canchas\" materializada. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_DELETED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · CATEGORY_NOT_FOUND","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `DELETE /club-owner/resource-categories/:id`: sólo una categoría vacía y que no sea la \"Canchas\" materializada. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_DELETED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La categoría no existe o no es de este club.\",\n  \"code\": \"CATEGORY_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · CATEGORY_IS_DEFAULT / CATEGORY_HAS_RESOURCES","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `DELETE /club-owner/resource-categories/:id`: sólo una categoría vacía y que no sea la \"Canchas\" materializada. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_DELETED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura."},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La categoría de canchas no se puede borrar.\",\n  \"code\": \"CATEGORY_IS_DEFAULT\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `DELETE /club-owner/resource-categories/:id`: sólo una categoría vacía y que no sea la \"Canchas\" materializada. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_DELETED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `DELETE /club-owner/resource-categories/:id`: sólo una categoría vacía y que no sea la \"Canchas\" materializada. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_DELETED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/resource-categories/:id","host":["{{baseUrl}}"],"path":["resource-categories",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la categoría (`GET /resource-categories`)."}]},"description":"Espejo de `DELETE /club-owner/resource-categories/:id`: sólo una categoría vacía y que no sea la \"Canchas\" materializada. Exige el módulo de categorías. Scope sensible `club:write`. Audit `RESOURCE_CATEGORY_DELETED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Configuración del club (getClubSettings)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La configuración de NEGOCIO de `club_settings`: política de confirmación, ventanas, topes, moneda, zona, franja pico y cola de espontáneos. Nada de credenciales.\n\nScope: `club:read`."},"response":[{"name":"200 · La configuración.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La configuración de NEGOCIO de `club_settings`: política de confirmación, ventanas, topes, moneda, zona, franja pico y cola de espontáneos. Nada de credenciales.\n\nScope: `club:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"bookingPolicy\": \"AUTO_CONFIRM\",\n  \"cancellationWindowHours\": 2,\n  \"noShowGraceMinutes\": 30,\n  \"maxBookingsPerUserPerDay\": null,\n  \"maxAdvanceBookingDays\": 30,\n  \"requirePayment\": false,\n  \"currency\": \"UYU\",\n  \"timezone\": \"America/Montevideo\",\n  \"peakHoursEnabled\": true,\n  \"peakHoursStart\": \"18:00\",\n  \"peakHoursEnd\": \"23:00\",\n  \"peakHoursDays\": [\n    1,\n    2,\n    3,\n    4,\n    5\n  ],\n  \"spontaneousCategories\": [],\n  \"updatedAt\": \"2026-09-14T12:00:00.000Z\"\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La configuración de NEGOCIO de `club_settings`: política de confirmación, ventanas, topes, moneda, zona, franja pico y cola de espontáneos. Nada de credenciales.\n\nScope: `club:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La configuración de NEGOCIO de `club_settings`: política de confirmación, ventanas, topes, moneda, zona, franja pico y cola de espontáneos. Nada de credenciales.\n\nScope: `club:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La configuración de NEGOCIO de `club_settings`: política de confirmación, ventanas, topes, moneda, zona, franja pico y cola de espontáneos. Nada de credenciales.\n\nScope: `club:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La configuración de NEGOCIO de `club_settings`: política de confirmación, ventanas, topes, moneda, zona, franja pico y cola de espontáneos. Nada de credenciales.\n\nScope: `club:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La configuración de NEGOCIO de `club_settings`: política de confirmación, ventanas, topes, moneda, zona, franja pico y cola de espontáneos. Nada de credenciales.\n\nScope: `club:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"La configuración de NEGOCIO de `club_settings`: política de confirmación, ventanas, topes, moneda, zona, franja pico y cola de espontáneos. Nada de credenciales.\n\nScope: `club:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Editar la configuración del club (updateClubSettings)","request":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"]},"description":"Parcial, con las MISMAS validaciones del panel (`PATCH /club-owner/clubs/:id/settings`): zona IANA válida, franja pico `HH:MM` con fin posterior al inicio (contra lo guardado si sólo mandás uno), días 0..6, cola de categorías conocida. Scope sensible `club:write`. Audit `SETTINGS_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"cancellationWindowHours\": 4,\n  \"peakHoursEnabled\": true,\n  \"peakHoursStart\": \"18:00\",\n  \"peakHoursEnd\": \"23:00\",\n  \"peakHoursDays\": [\n    1,\n    2,\n    3,\n    4,\n    5\n  ]\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · La configuración actualizada.","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"]},"description":"Parcial, con las MISMAS validaciones del panel (`PATCH /club-owner/clubs/:id/settings`): zona IANA válida, franja pico `HH:MM` con fin posterior al inicio (contra lo guardado si sólo mandás uno), días 0..6, cola de categorías conocida. Scope sensible `club:write`. Audit `SETTINGS_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"cancellationWindowHours\": 4,\n  \"peakHoursEnabled\": true,\n  \"peakHoursStart\": \"18:00\",\n  \"peakHoursEnd\": \"23:00\",\n  \"peakHoursDays\": [\n    1,\n    2,\n    3,\n    4,\n    5\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"bookingPolicy\": \"AUTO_CONFIRM\",\n  \"cancellationWindowHours\": 2,\n  \"noShowGraceMinutes\": 30,\n  \"maxBookingsPerUserPerDay\": null,\n  \"maxAdvanceBookingDays\": 30,\n  \"requirePayment\": false,\n  \"currency\": \"UYU\",\n  \"timezone\": \"America/Montevideo\",\n  \"peakHoursEnabled\": true,\n  \"peakHoursStart\": \"18:00\",\n  \"peakHoursEnd\": \"23:00\",\n  \"peakHoursDays\": [\n    1,\n    2,\n    3,\n    4,\n    5\n  ],\n  \"spontaneousCategories\": [],\n  \"updatedAt\": \"2026-09-14T12:00:00.000Z\"\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED / INVALID_PEAK_RANGE","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"]},"description":"Parcial, con las MISMAS validaciones del panel (`PATCH /club-owner/clubs/:id/settings`): zona IANA válida, franja pico `HH:MM` con fin posterior al inicio (contra lo guardado si sólo mandás uno), días 0..6, cola de categorías conocida. Scope sensible `club:write`. Audit `SETTINGS_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"cancellationWindowHours\": 4,\n  \"peakHoursEnabled\": true,\n  \"peakHoursStart\": \"18:00\",\n  \"peakHoursEnd\": \"23:00\",\n  \"peakHoursDays\": [\n    1,\n    2,\n    3,\n    4,\n    5\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"]},"description":"Parcial, con las MISMAS validaciones del panel (`PATCH /club-owner/clubs/:id/settings`): zona IANA válida, franja pico `HH:MM` con fin posterior al inicio (contra lo guardado si sólo mandás uno), días 0..6, cola de categorías conocida. Scope sensible `club:write`. Audit `SETTINGS_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"cancellationWindowHours\": 4,\n  \"peakHoursEnabled\": true,\n  \"peakHoursStart\": \"18:00\",\n  \"peakHoursEnd\": \"23:00\",\n  \"peakHoursDays\": [\n    1,\n    2,\n    3,\n    4,\n    5\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"]},"description":"Parcial, con las MISMAS validaciones del panel (`PATCH /club-owner/clubs/:id/settings`): zona IANA válida, franja pico `HH:MM` con fin posterior al inicio (contra lo guardado si sólo mandás uno), días 0..6, cola de categorías conocida. Scope sensible `club:write`. Audit `SETTINGS_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"cancellationWindowHours\": 4,\n  \"peakHoursEnabled\": true,\n  \"peakHoursStart\": \"18:00\",\n  \"peakHoursEnd\": \"23:00\",\n  \"peakHoursDays\": [\n    1,\n    2,\n    3,\n    4,\n    5\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"]},"description":"Parcial, con las MISMAS validaciones del panel (`PATCH /club-owner/clubs/:id/settings`): zona IANA válida, franja pico `HH:MM` con fin posterior al inicio (contra lo guardado si sólo mandás uno), días 0..6, cola de categorías conocida. Scope sensible `club:write`. Audit `SETTINGS_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"cancellationWindowHours\": 4,\n  \"peakHoursEnabled\": true,\n  \"peakHoursStart\": \"18:00\",\n  \"peakHoursEnd\": \"23:00\",\n  \"peakHoursDays\": [\n    1,\n    2,\n    3,\n    4,\n    5\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"]},"description":"Parcial, con las MISMAS validaciones del panel (`PATCH /club-owner/clubs/:id/settings`): zona IANA válida, franja pico `HH:MM` con fin posterior al inicio (contra lo guardado si sólo mandás uno), días 0..6, cola de categorías conocida. Scope sensible `club:write`. Audit `SETTINGS_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"cancellationWindowHours\": 4,\n  \"peakHoursEnabled\": true,\n  \"peakHoursStart\": \"18:00\",\n  \"peakHoursEnd\": \"23:00\",\n  \"peakHoursDays\": [\n    1,\n    2,\n    3,\n    4,\n    5\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"]},"description":"Parcial, con las MISMAS validaciones del panel (`PATCH /club-owner/clubs/:id/settings`): zona IANA válida, franja pico `HH:MM` con fin posterior al inicio (contra lo guardado si sólo mandás uno), días 0..6, cola de categorías conocida. Scope sensible `club:write`. Audit `SETTINGS_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"cancellationWindowHours\": 4,\n  \"peakHoursEnabled\": true,\n  \"peakHoursStart\": \"18:00\",\n  \"peakHoursEnd\": \"23:00\",\n  \"peakHoursDays\": [\n    1,\n    2,\n    3,\n    4,\n    5\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/settings","host":["{{baseUrl}}"],"path":["settings"]},"description":"Parcial, con las MISMAS validaciones del panel (`PATCH /club-owner/clubs/:id/settings`): zona IANA válida, franja pico `HH:MM` con fin posterior al inicio (contra lo guardado si sólo mandás uno), días 0..6, cola de categorías conocida. Scope sensible `club:write`. Audit `SETTINGS_UPDATED`. Consume cuota de escritura.\n\nScope: `club:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"cancellationWindowHours\": 4,\n  \"peakHoursEnabled\": true,\n  \"peakHoursStart\": \"18:00\",\n  \"peakHoursEnd\": \"23:00\",\n  \"peakHoursDays\": [\n    1,\n    2,\n    3,\n    4,\n    5\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]}]},{"name":"Webhooks","description":"Webhooks salientes: recibí los eventos de la agenda firmados, sin pollear.","item":[{"name":"Listar webhooks (listWebhooks)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los webhooks de la integración (máximo 5). Un webhook recibe los eventos de todos los clubes con grant de la integración. Nunca devuelve el secreto.\n\nScope: `webhooks:manage`."},"response":[{"name":"200 · Los webhooks.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los webhooks de la integración (máximo 5). Un webhook recibe los eventos de todos los clubes con grant de la integración. Nunca devuelve el secreto.\n\nScope: `webhooks:manage`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"webhooks\": [\n    {\n      \"id\": \"7c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f\",\n      \"url\": \"https://pos.miclub.uy/skalia/webhook\",\n      \"events\": [\n        \"booking.created\",\n        \"booking.cancelled\"\n      ],\n      \"status\": \"ACTIVE\",\n      \"failuresInARow\": 0,\n      \"lastSuccessAt\": \"2026-09-18T12:00:00.000Z\",\n      \"lastFailureAt\": null,\n      \"disabledAt\": null,\n      \"disabledReason\": null,\n      \"createdAt\": \"2026-09-18T11:00:00.000Z\",\n      \"updatedAt\": \"2026-09-18T12:00:00.000Z\"\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los webhooks de la integración (máximo 5). Un webhook recibe los eventos de todos los clubes con grant de la integración. Nunca devuelve el secreto.\n\nScope: `webhooks:manage`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los webhooks de la integración (máximo 5). Un webhook recibe los eventos de todos los clubes con grant de la integración. Nunca devuelve el secreto.\n\nScope: `webhooks:manage`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los webhooks de la integración (máximo 5). Un webhook recibe los eventos de todos los clubes con grant de la integración. Nunca devuelve el secreto.\n\nScope: `webhooks:manage`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los webhooks de la integración (máximo 5). Un webhook recibe los eventos de todos los clubes con grant de la integración. Nunca devuelve el secreto.\n\nScope: `webhooks:manage`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los webhooks de la integración (máximo 5). Un webhook recibe los eventos de todos los clubes con grant de la integración. Nunca devuelve el secreto.\n\nScope: `webhooks:manage`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true}]},"description":"Los webhooks de la integración (máximo 5). Un webhook recibe los eventos de todos los clubes con grant de la integración. Nunca devuelve el secreto.\n\nScope: `webhooks:manage`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Registrar un webhook (createWebhook)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"]},"description":"Alta de un receptor. La URL tiene que ser https y resolver a una dirección pública (se valida al registrar y en CADA entrega; un DNS que después apunte a una red privada hace fallar la entrega, no la desvía). La respuesta trae el secreto `whsec_…` UNA sola vez. Cada entrega es un POST JSON con `X-Skalia-Event`, `X-Skalia-Event-Id`, `X-Skalia-Delivery-Id` y `X-Skalia-Signature: t=<unix>,v1=<hmac-sha256(secret, t + \".\" + body)>`; respondé 2xx en menos de 5 s. Reintentos con backoff 1 min, 5 min, 30 min, 2 h, 12 h; al 6.º fallo la entrega queda DEAD; 25 fallos seguidos apagan el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"url\": \"https://pos.miclub.uy/skalia/webhook\",\n  \"events\": [\n    \"booking.created\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"201 · Creado. `secret` viaja sólo acá.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"]},"description":"Alta de un receptor. La URL tiene que ser https y resolver a una dirección pública (se valida al registrar y en CADA entrega; un DNS que después apunte a una red privada hace fallar la entrega, no la desvía). La respuesta trae el secreto `whsec_…` UNA sola vez. Cada entrega es un POST JSON con `X-Skalia-Event`, `X-Skalia-Event-Id`, `X-Skalia-Delivery-Id` y `X-Skalia-Signature: t=<unix>,v1=<hmac-sha256(secret, t + \".\" + body)>`; respondé 2xx en menos de 5 s. Reintentos con backoff 1 min, 5 min, 30 min, 2 h, 12 h; al 6.º fallo la entrega queda DEAD; 25 fallos seguidos apagan el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"url\": \"https://pos.miclub.uy/skalia/webhook\",\n  \"events\": [\n    \"booking.created\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"webhook\": {\n    \"id\": \"7c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f\",\n    \"url\": \"https://pos.miclub.uy/skalia/webhook\",\n    \"events\": [\n      \"booking.created\",\n      \"booking.cancelled\"\n    ],\n    \"status\": \"ACTIVE\",\n    \"failuresInARow\": 0,\n    \"lastSuccessAt\": \"2026-09-18T12:00:00.000Z\",\n    \"lastFailureAt\": null,\n    \"disabledAt\": null,\n    \"disabledReason\": null,\n    \"createdAt\": \"2026-09-18T11:00:00.000Z\",\n    \"updatedAt\": \"2026-09-18T12:00:00.000Z\"\n  },\n  \"secret\": \"whsec_Q2xhdmUgZGUgZWplbXBsbywgbm8gbGEgdXNlcw\"\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED / WEBHOOK_URL_INVALID","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"]},"description":"Alta de un receptor. La URL tiene que ser https y resolver a una dirección pública (se valida al registrar y en CADA entrega; un DNS que después apunte a una red privada hace fallar la entrega, no la desvía). La respuesta trae el secreto `whsec_…` UNA sola vez. Cada entrega es un POST JSON con `X-Skalia-Event`, `X-Skalia-Event-Id`, `X-Skalia-Delivery-Id` y `X-Skalia-Signature: t=<unix>,v1=<hmac-sha256(secret, t + \".\" + body)>`; respondé 2xx en menos de 5 s. Reintentos con backoff 1 min, 5 min, 30 min, 2 h, 12 h; al 6.º fallo la entrega queda DEAD; 25 fallos seguidos apagan el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"url\": \"https://pos.miclub.uy/skalia/webhook\",\n  \"events\": [\n    \"booking.created\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"]},"description":"Alta de un receptor. La URL tiene que ser https y resolver a una dirección pública (se valida al registrar y en CADA entrega; un DNS que después apunte a una red privada hace fallar la entrega, no la desvía). La respuesta trae el secreto `whsec_…` UNA sola vez. Cada entrega es un POST JSON con `X-Skalia-Event`, `X-Skalia-Event-Id`, `X-Skalia-Delivery-Id` y `X-Skalia-Signature: t=<unix>,v1=<hmac-sha256(secret, t + \".\" + body)>`; respondé 2xx en menos de 5 s. Reintentos con backoff 1 min, 5 min, 30 min, 2 h, 12 h; al 6.º fallo la entrega queda DEAD; 25 fallos seguidos apagan el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"url\": \"https://pos.miclub.uy/skalia/webhook\",\n  \"events\": [\n    \"booking.created\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"]},"description":"Alta de un receptor. La URL tiene que ser https y resolver a una dirección pública (se valida al registrar y en CADA entrega; un DNS que después apunte a una red privada hace fallar la entrega, no la desvía). La respuesta trae el secreto `whsec_…` UNA sola vez. Cada entrega es un POST JSON con `X-Skalia-Event`, `X-Skalia-Event-Id`, `X-Skalia-Delivery-Id` y `X-Skalia-Signature: t=<unix>,v1=<hmac-sha256(secret, t + \".\" + body)>`; respondé 2xx en menos de 5 s. Reintentos con backoff 1 min, 5 min, 30 min, 2 h, 12 h; al 6.º fallo la entrega queda DEAD; 25 fallos seguidos apagan el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"url\": \"https://pos.miclub.uy/skalia/webhook\",\n  \"events\": [\n    \"booking.created\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · WEBHOOK_LIMIT","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"]},"description":"Alta de un receptor. La URL tiene que ser https y resolver a una dirección pública (se valida al registrar y en CADA entrega; un DNS que después apunte a una red privada hace fallar la entrega, no la desvía). La respuesta trae el secreto `whsec_…` UNA sola vez. Cada entrega es un POST JSON con `X-Skalia-Event`, `X-Skalia-Event-Id`, `X-Skalia-Delivery-Id` y `X-Skalia-Signature: t=<unix>,v1=<hmac-sha256(secret, t + \".\" + body)>`; respondé 2xx en menos de 5 s. Reintentos con backoff 1 min, 5 min, 30 min, 2 h, 12 h; al 6.º fallo la entrega queda DEAD; 25 fallos seguidos apagan el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"url\": \"https://pos.miclub.uy/skalia/webhook\",\n  \"events\": [\n    \"booking.created\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración ya tiene el máximo de webhooks.\",\n  \"code\": \"WEBHOOK_LIMIT\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"]},"description":"Alta de un receptor. La URL tiene que ser https y resolver a una dirección pública (se valida al registrar y en CADA entrega; un DNS que después apunte a una red privada hace fallar la entrega, no la desvía). La respuesta trae el secreto `whsec_…` UNA sola vez. Cada entrega es un POST JSON con `X-Skalia-Event`, `X-Skalia-Event-Id`, `X-Skalia-Delivery-Id` y `X-Skalia-Signature: t=<unix>,v1=<hmac-sha256(secret, t + \".\" + body)>`; respondé 2xx en menos de 5 s. Reintentos con backoff 1 min, 5 min, 30 min, 2 h, 12 h; al 6.º fallo la entrega queda DEAD; 25 fallos seguidos apagan el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"url\": \"https://pos.miclub.uy/skalia/webhook\",\n  \"events\": [\n    \"booking.created\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"]},"description":"Alta de un receptor. La URL tiene que ser https y resolver a una dirección pública (se valida al registrar y en CADA entrega; un DNS que después apunte a una red privada hace fallar la entrega, no la desvía). La respuesta trae el secreto `whsec_…` UNA sola vez. Cada entrega es un POST JSON con `X-Skalia-Event`, `X-Skalia-Event-Id`, `X-Skalia-Delivery-Id` y `X-Skalia-Signature: t=<unix>,v1=<hmac-sha256(secret, t + \".\" + body)>`; respondé 2xx en menos de 5 s. Reintentos con backoff 1 min, 5 min, 30 min, 2 h, 12 h; al 6.º fallo la entrega queda DEAD; 25 fallos seguidos apagan el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"url\": \"https://pos.miclub.uy/skalia/webhook\",\n  \"events\": [\n    \"booking.created\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"]},"description":"Alta de un receptor. La URL tiene que ser https y resolver a una dirección pública (se valida al registrar y en CADA entrega; un DNS que después apunte a una red privada hace fallar la entrega, no la desvía). La respuesta trae el secreto `whsec_…` UNA sola vez. Cada entrega es un POST JSON con `X-Skalia-Event`, `X-Skalia-Event-Id`, `X-Skalia-Delivery-Id` y `X-Skalia-Signature: t=<unix>,v1=<hmac-sha256(secret, t + \".\" + body)>`; respondé 2xx en menos de 5 s. Reintentos con backoff 1 min, 5 min, 30 min, 2 h, 12 h; al 6.º fallo la entrega queda DEAD; 25 fallos seguidos apagan el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"url\": \"https://pos.miclub.uy/skalia/webhook\",\n  \"events\": [\n    \"booking.created\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED / WEBHOOKS_UNAVAILABLE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"]},"description":"Alta de un receptor. La URL tiene que ser https y resolver a una dirección pública (se valida al registrar y en CADA entrega; un DNS que después apunte a una red privada hace fallar la entrega, no la desvía). La respuesta trae el secreto `whsec_…` UNA sola vez. Cada entrega es un POST JSON con `X-Skalia-Event`, `X-Skalia-Event-Id`, `X-Skalia-Delivery-Id` y `X-Skalia-Signature: t=<unix>,v1=<hmac-sha256(secret, t + \".\" + body)>`; respondé 2xx en menos de 5 s. Reintentos con backoff 1 min, 5 min, 30 min, 2 h, 12 h; al 6.º fallo la entrega queda DEAD; 25 fallos seguidos apagan el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"url\": \"https://pos.miclub.uy/skalia/webhook\",\n  \"events\": [\n    \"booking.created\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Editar un webhook (updateWebhook)","request":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Cambiar la URL (se re-valida), los eventos o el estado. `status: DISABLED` deja de entregar y las pendientes esperan; `ACTIVE` lo reactiva, resetea la racha de fallos y el cron retoma lo pendiente. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"events\": [\n    \"booking.created\",\n    \"booking.updated\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"200 · El webhook actualizado y qué cambió.","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Cambiar la URL (se re-valida), los eventos o el estado. `status: DISABLED` deja de entregar y las pendientes esperan; `ACTIVE` lo reactiva, resetea la racha de fallos y el cron retoma lo pendiente. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"events\": [\n    \"booking.created\",\n    \"booking.updated\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"webhook\": {\n    \"id\": \"7c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f\",\n    \"url\": \"https://pos.miclub.uy/skalia/webhook\",\n    \"events\": [\n      \"booking.created\",\n      \"booking.cancelled\"\n    ],\n    \"status\": \"ACTIVE\",\n    \"failuresInARow\": 0,\n    \"lastSuccessAt\": \"2026-09-18T12:00:00.000Z\",\n    \"lastFailureAt\": null,\n    \"disabledAt\": null,\n    \"disabledReason\": null,\n    \"createdAt\": \"2026-09-18T11:00:00.000Z\",\n    \"updatedAt\": \"2026-09-18T12:00:00.000Z\"\n  },\n  \"changed\": [\n    \"url\"\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / WEBHOOK_URL_INVALID","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Cambiar la URL (se re-valida), los eventos o el estado. `status: DISABLED` deja de entregar y las pendientes esperan; `ACTIVE` lo reactiva, resetea la racha de fallos y el cron retoma lo pendiente. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"events\": [\n    \"booking.created\",\n    \"booking.updated\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Cambiar la URL (se re-valida), los eventos o el estado. `status: DISABLED` deja de entregar y las pendientes esperan; `ACTIVE` lo reactiva, resetea la racha de fallos y el cron retoma lo pendiente. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"events\": [\n    \"booking.created\",\n    \"booking.updated\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Cambiar la URL (se re-valida), los eventos o el estado. `status: DISABLED` deja de entregar y las pendientes esperan; `ACTIVE` lo reactiva, resetea la racha de fallos y el cron retoma lo pendiente. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"events\": [\n    \"booking.created\",\n    \"booking.updated\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · WEBHOOK_NOT_FOUND","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Cambiar la URL (se re-valida), los eventos o el estado. `status: DISABLED` deja de entregar y las pendientes esperan; `ACTIVE` lo reactiva, resetea la racha de fallos y el cron retoma lo pendiente. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"events\": [\n    \"booking.created\",\n    \"booking.updated\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El webhook no existe o no es de esta integración.\",\n  \"code\": \"WEBHOOK_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Cambiar la URL (se re-valida), los eventos o el estado. `status: DISABLED` deja de entregar y las pendientes esperan; `ACTIVE` lo reactiva, resetea la racha de fallos y el cron retoma lo pendiente. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"events\": [\n    \"booking.created\",\n    \"booking.updated\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Cambiar la URL (se re-valida), los eventos o el estado. `status: DISABLED` deja de entregar y las pendientes esperan; `ACTIVE` lo reactiva, resetea la racha de fallos y el cron retoma lo pendiente. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"events\": [\n    \"booking.created\",\n    \"booking.updated\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Cambiar la URL (se re-valida), los eventos o el estado. `status: DISABLED` deja de entregar y las pendientes esperan; `ACTIVE` lo reactiva, resetea la racha de fallos y el cron retoma lo pendiente. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"events\": [\n    \"booking.created\",\n    \"booking.updated\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"PATCH","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Cambiar la URL (se re-valida), los eventos o el estado. `status: DISABLED` deja de entregar y las pendientes esperan; `ACTIVE` lo reactiva, resetea la racha de fallos y el cron retoma lo pendiente. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"events\": [\n    \"booking.created\",\n    \"booking.updated\",\n    \"booking.cancelled\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Borrar un webhook (deleteWebhook)","request":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Borra el webhook y su historial de entregas. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"response":[{"name":"200 · Borrado.","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Borra el webhook y su historial de entregas. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"id\": \"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d\",\n  \"deleted\": true\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Borra el webhook y su historial de entregas. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Borra el webhook y su historial de entregas. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Borra el webhook y su historial de entregas. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · WEBHOOK_NOT_FOUND","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Borra el webhook y su historial de entregas. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El webhook no existe o no es de esta integración.\",\n  \"code\": \"WEBHOOK_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Borra el webhook y su historial de entregas. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Borra el webhook y su historial de entregas. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id","host":["{{baseUrl}}"],"path":["webhooks",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Borra el webhook y su historial de entregas. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Historial de entregas (listWebhookDeliveries)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries"],"query":[{"key":"status","value":"PENDING","description":"Filtra por estado de la entrega.","disabled":true},{"key":"limit","value":"1","description":"Entregas por página, 1..200 (default 50).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación por offset).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Las entregas del webhook, más recientes primero, con el último status HTTP y el último error. Retención 30 días.\n\nScope: `webhooks:manage`."},"response":[{"name":"200 · Página de entregas.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries"],"query":[{"key":"status","value":"PENDING","description":"Filtra por estado de la entrega.","disabled":true},{"key":"limit","value":"1","description":"Entregas por página, 1..200 (default 50).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación por offset).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Las entregas del webhook, más recientes primero, con el último status HTTP y el último error. Retención 30 días.\n\nScope: `webhooks:manage`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"deliveries\": [\n    {\n      \"id\": \"9f8e7d6c-5b4a-4c3d-9e2f-1a0b9c8d7e6f\",\n      \"eventId\": 1042,\n      \"event\": \"booking.created\",\n      \"status\": \"DELIVERED\",\n      \"attempts\": 1,\n      \"nextAttemptAt\": \"2026-09-18T12:00:00.000Z\",\n      \"lastStatus\": 200,\n      \"lastError\": null,\n      \"lastAttemptAt\": \"2026-09-18T12:00:01.000Z\",\n      \"deliveredAt\": \"2026-09-18T12:00:01.000Z\",\n      \"createdAt\": \"2026-09-18T12:00:00.000Z\"\n    }\n  ],\n  \"total\": 1,\n  \"limit\": 1,\n  \"offset\": 1\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries"],"query":[{"key":"status","value":"PENDING","description":"Filtra por estado de la entrega.","disabled":true},{"key":"limit","value":"1","description":"Entregas por página, 1..200 (default 50).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación por offset).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Las entregas del webhook, más recientes primero, con el último status HTTP y el último error. Retención 30 días.\n\nScope: `webhooks:manage`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries"],"query":[{"key":"status","value":"PENDING","description":"Filtra por estado de la entrega.","disabled":true},{"key":"limit","value":"1","description":"Entregas por página, 1..200 (default 50).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación por offset).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Las entregas del webhook, más recientes primero, con el último status HTTP y el último error. Retención 30 días.\n\nScope: `webhooks:manage`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries"],"query":[{"key":"status","value":"PENDING","description":"Filtra por estado de la entrega.","disabled":true},{"key":"limit","value":"1","description":"Entregas por página, 1..200 (default 50).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación por offset).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Las entregas del webhook, más recientes primero, con el último status HTTP y el último error. Retención 30 días.\n\nScope: `webhooks:manage`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · WEBHOOK_NOT_FOUND","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries"],"query":[{"key":"status","value":"PENDING","description":"Filtra por estado de la entrega.","disabled":true},{"key":"limit","value":"1","description":"Entregas por página, 1..200 (default 50).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación por offset).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Las entregas del webhook, más recientes primero, con el último status HTTP y el último error. Retención 30 días.\n\nScope: `webhooks:manage`."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El webhook no existe o no es de esta integración.\",\n  \"code\": \"WEBHOOK_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries"],"query":[{"key":"status","value":"PENDING","description":"Filtra por estado de la entrega.","disabled":true},{"key":"limit","value":"1","description":"Entregas por página, 1..200 (default 50).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación por offset).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Las entregas del webhook, más recientes primero, con el último status HTTP y el último error. Retención 30 días.\n\nScope: `webhooks:manage`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries"],"query":[{"key":"status","value":"PENDING","description":"Filtra por estado de la entrega.","disabled":true},{"key":"limit","value":"1","description":"Entregas por página, 1..200 (default 50).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación por offset).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Las entregas del webhook, más recientes primero, con el último status HTTP y el último error. Retención 30 días.\n\nScope: `webhooks:manage`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries"],"query":[{"key":"status","value":"PENDING","description":"Filtra por estado de la entrega.","disabled":true},{"key":"limit","value":"1","description":"Entregas por página, 1..200 (default 50).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación por offset).","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Las entregas del webhook, más recientes primero, con el último status HTTP y el último error. Retención 30 días.\n\nScope: `webhooks:manage`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Reenviar una entrega (redeliverWebhookDelivery)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries/:deliveryId/redeliver","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries",":deliveryId","redeliver"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."},{"key":"deliveryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la entrega (`X-Skalia-Delivery-Id`)."}]},"description":"Vuelve a mandar el MISMO cuerpo (firma nueva) en el acto y devuelve el resultado. Sirve para DELIVERED (el receptor lo perdió), FAILED y DEAD; si vuelve a fallar sigue el ciclo normal. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"response":[{"name":"200 · La entrega tras el reintento.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries/:deliveryId/redeliver","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries",":deliveryId","redeliver"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."},{"key":"deliveryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la entrega (`X-Skalia-Delivery-Id`)."}]},"description":"Vuelve a mandar el MISMO cuerpo (firma nueva) en el acto y devuelve el resultado. Sirve para DELIVERED (el receptor lo perdió), FAILED y DEAD; si vuelve a fallar sigue el ciclo normal. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"delivery\": {\n    \"id\": \"9f8e7d6c-5b4a-4c3d-9e2f-1a0b9c8d7e6f\",\n    \"eventId\": 1042,\n    \"event\": \"booking.created\",\n    \"status\": \"DELIVERED\",\n    \"attempts\": 1,\n    \"nextAttemptAt\": \"2026-09-18T12:00:00.000Z\",\n    \"lastStatus\": 200,\n    \"lastError\": null,\n    \"lastAttemptAt\": \"2026-09-18T12:00:01.000Z\",\n    \"deliveredAt\": \"2026-09-18T12:00:01.000Z\",\n    \"createdAt\": \"2026-09-18T12:00:00.000Z\"\n  }\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries/:deliveryId/redeliver","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries",":deliveryId","redeliver"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."},{"key":"deliveryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la entrega (`X-Skalia-Delivery-Id`)."}]},"description":"Vuelve a mandar el MISMO cuerpo (firma nueva) en el acto y devuelve el resultado. Sirve para DELIVERED (el receptor lo perdió), FAILED y DEAD; si vuelve a fallar sigue el ciclo normal. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries/:deliveryId/redeliver","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries",":deliveryId","redeliver"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."},{"key":"deliveryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la entrega (`X-Skalia-Delivery-Id`)."}]},"description":"Vuelve a mandar el MISMO cuerpo (firma nueva) en el acto y devuelve el resultado. Sirve para DELIVERED (el receptor lo perdió), FAILED y DEAD; si vuelve a fallar sigue el ciclo normal. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries/:deliveryId/redeliver","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries",":deliveryId","redeliver"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."},{"key":"deliveryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la entrega (`X-Skalia-Delivery-Id`)."}]},"description":"Vuelve a mandar el MISMO cuerpo (firma nueva) en el acto y devuelve el resultado. Sirve para DELIVERED (el receptor lo perdió), FAILED y DEAD; si vuelve a fallar sigue el ciclo normal. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · WEBHOOK_NOT_FOUND / WEBHOOK_DELIVERY_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries/:deliveryId/redeliver","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries",":deliveryId","redeliver"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."},{"key":"deliveryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la entrega (`X-Skalia-Delivery-Id`)."}]},"description":"Vuelve a mandar el MISMO cuerpo (firma nueva) en el acto y devuelve el resultado. Sirve para DELIVERED (el receptor lo perdió), FAILED y DEAD; si vuelve a fallar sigue el ciclo normal. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El webhook no existe o no es de esta integración.\",\n  \"code\": \"WEBHOOK_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · WEBHOOK_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries/:deliveryId/redeliver","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries",":deliveryId","redeliver"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."},{"key":"deliveryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la entrega (`X-Skalia-Delivery-Id`)."}]},"description":"Vuelve a mandar el MISMO cuerpo (firma nueva) en el acto y devuelve el resultado. Sirve para DELIVERED (el receptor lo perdió), FAILED y DEAD; si vuelve a fallar sigue el ciclo normal. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El webhook está deshabilitado: habilitalo antes de probar o reenviar.\",\n  \"code\": \"WEBHOOK_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries/:deliveryId/redeliver","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries",":deliveryId","redeliver"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."},{"key":"deliveryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la entrega (`X-Skalia-Delivery-Id`)."}]},"description":"Vuelve a mandar el MISMO cuerpo (firma nueva) en el acto y devuelve el resultado. Sirve para DELIVERED (el receptor lo perdió), FAILED y DEAD; si vuelve a fallar sigue el ciclo normal. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries/:deliveryId/redeliver","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries",":deliveryId","redeliver"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."},{"key":"deliveryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la entrega (`X-Skalia-Delivery-Id`)."}]},"description":"Vuelve a mandar el MISMO cuerpo (firma nueva) en el acto y devuelve el resultado. Sirve para DELIVERED (el receptor lo perdió), FAILED y DEAD; si vuelve a fallar sigue el ciclo normal. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/deliveries/:deliveryId/redeliver","host":["{{baseUrl}}"],"path":["webhooks",":id","deliveries",":deliveryId","redeliver"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."},{"key":"deliveryId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id de la entrega (`X-Skalia-Delivery-Id`)."}]},"description":"Vuelve a mandar el MISMO cuerpo (firma nueva) en el acto y devuelve el resultado. Sirve para DELIVERED (el receptor lo perdió), FAILED y DEAD; si vuelve a fallar sigue el ciclo normal. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Rotar el secreto (rotateWebhookSecret)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/rotate-secret","host":["{{baseUrl}}"],"path":["webhooks",":id","rotate-secret"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Genera un secreto nuevo; el anterior deja de firmar EN EL ACTO (no hay gracia: actualizá el receptor antes de llamar, o aceptá unas entregas con firma inválida y reenvialas). Se devuelve una sola vez. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"response":[{"name":"201 · Secreto nuevo (sólo acá).","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/rotate-secret","host":["{{baseUrl}}"],"path":["webhooks",":id","rotate-secret"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Genera un secreto nuevo; el anterior deja de firmar EN EL ACTO (no hay gracia: actualizá el receptor antes de llamar, o aceptá unas entregas con firma inválida y reenvialas). Se devuelve una sola vez. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"webhook\": {\n    \"id\": \"7c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f\",\n    \"url\": \"https://pos.miclub.uy/skalia/webhook\",\n    \"events\": [\n      \"booking.created\",\n      \"booking.cancelled\"\n    ],\n    \"status\": \"ACTIVE\",\n    \"failuresInARow\": 0,\n    \"lastSuccessAt\": \"2026-09-18T12:00:00.000Z\",\n    \"lastFailureAt\": null,\n    \"disabledAt\": null,\n    \"disabledReason\": null,\n    \"createdAt\": \"2026-09-18T11:00:00.000Z\",\n    \"updatedAt\": \"2026-09-18T12:00:00.000Z\"\n  },\n  \"secret\": \"whsec_Q2xhdmUgZGUgZWplbXBsbywgbm8gbGEgdXNlcw\"\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/rotate-secret","host":["{{baseUrl}}"],"path":["webhooks",":id","rotate-secret"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Genera un secreto nuevo; el anterior deja de firmar EN EL ACTO (no hay gracia: actualizá el receptor antes de llamar, o aceptá unas entregas con firma inválida y reenvialas). Se devuelve una sola vez. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/rotate-secret","host":["{{baseUrl}}"],"path":["webhooks",":id","rotate-secret"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Genera un secreto nuevo; el anterior deja de firmar EN EL ACTO (no hay gracia: actualizá el receptor antes de llamar, o aceptá unas entregas con firma inválida y reenvialas). Se devuelve una sola vez. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/rotate-secret","host":["{{baseUrl}}"],"path":["webhooks",":id","rotate-secret"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Genera un secreto nuevo; el anterior deja de firmar EN EL ACTO (no hay gracia: actualizá el receptor antes de llamar, o aceptá unas entregas con firma inválida y reenvialas). Se devuelve una sola vez. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · WEBHOOK_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/rotate-secret","host":["{{baseUrl}}"],"path":["webhooks",":id","rotate-secret"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Genera un secreto nuevo; el anterior deja de firmar EN EL ACTO (no hay gracia: actualizá el receptor antes de llamar, o aceptá unas entregas con firma inválida y reenvialas). Se devuelve una sola vez. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El webhook no existe o no es de esta integración.\",\n  \"code\": \"WEBHOOK_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/rotate-secret","host":["{{baseUrl}}"],"path":["webhooks",":id","rotate-secret"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Genera un secreto nuevo; el anterior deja de firmar EN EL ACTO (no hay gracia: actualizá el receptor antes de llamar, o aceptá unas entregas con firma inválida y reenvialas). Se devuelve una sola vez. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/rotate-secret","host":["{{baseUrl}}"],"path":["webhooks",":id","rotate-secret"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Genera un secreto nuevo; el anterior deja de firmar EN EL ACTO (no hay gracia: actualizá el receptor antes de llamar, o aceptá unas entregas con firma inválida y reenvialas). Se devuelve una sola vez. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED / WEBHOOKS_UNAVAILABLE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/rotate-secret","host":["{{baseUrl}}"],"path":["webhooks",":id","rotate-secret"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Genera un secreto nuevo; el anterior deja de firmar EN EL ACTO (no hay gracia: actualizá el receptor antes de llamar, o aceptá unas entregas con firma inválida y reenvialas). Se devuelve una sola vez. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Mandar un evento de prueba (testWebhook)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/test","host":["{{baseUrl}}"],"path":["webhooks",":id","test"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Manda en el acto un evento `webhook.test` firmado con el secreto vigente y devuelve la entrega con `lastStatus` / `lastError`. No se reintenta ni cuenta para apagar el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"response":[{"name":"200 · La entrega de prueba (mirá `status`).","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/test","host":["{{baseUrl}}"],"path":["webhooks",":id","test"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Manda en el acto un evento `webhook.test` firmado con el secreto vigente y devuelve la entrega con `lastStatus` / `lastError`. No se reintenta ni cuenta para apagar el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"delivery\": {\n    \"id\": \"9f8e7d6c-5b4a-4c3d-9e2f-1a0b9c8d7e6f\",\n    \"eventId\": 1042,\n    \"event\": \"booking.created\",\n    \"status\": \"DELIVERED\",\n    \"attempts\": 1,\n    \"nextAttemptAt\": \"2026-09-18T12:00:00.000Z\",\n    \"lastStatus\": 200,\n    \"lastError\": null,\n    \"lastAttemptAt\": \"2026-09-18T12:00:01.000Z\",\n    \"deliveredAt\": \"2026-09-18T12:00:01.000Z\",\n    \"createdAt\": \"2026-09-18T12:00:00.000Z\"\n  }\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/test","host":["{{baseUrl}}"],"path":["webhooks",":id","test"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Manda en el acto un evento `webhook.test` firmado con el secreto vigente y devuelve la entrega con `lastStatus` / `lastError`. No se reintenta ni cuenta para apagar el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/test","host":["{{baseUrl}}"],"path":["webhooks",":id","test"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Manda en el acto un evento `webhook.test` firmado con el secreto vigente y devuelve la entrega con `lastStatus` / `lastError`. No se reintenta ni cuenta para apagar el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/test","host":["{{baseUrl}}"],"path":["webhooks",":id","test"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Manda en el acto un evento `webhook.test` firmado con el secreto vigente y devuelve la entrega con `lastStatus` / `lastError`. No se reintenta ni cuenta para apagar el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · WEBHOOK_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/test","host":["{{baseUrl}}"],"path":["webhooks",":id","test"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Manda en el acto un evento `webhook.test` firmado con el secreto vigente y devuelve la entrega con `lastStatus` / `lastError`. No se reintenta ni cuenta para apagar el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El webhook no existe o no es de esta integración.\",\n  \"code\": \"WEBHOOK_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · WEBHOOK_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/test","host":["{{baseUrl}}"],"path":["webhooks",":id","test"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Manda en el acto un evento `webhook.test` firmado con el secreto vigente y devuelve la entrega con `lastStatus` / `lastError`. No se reintenta ni cuenta para apagar el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El webhook está deshabilitado: habilitalo antes de probar o reenviar.\",\n  \"code\": \"WEBHOOK_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/test","host":["{{baseUrl}}"],"path":["webhooks",":id","test"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Manda en el acto un evento `webhook.test` firmado con el secreto vigente y devuelve la entrega con `lastStatus` / `lastError`. No se reintenta ni cuenta para apagar el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/test","host":["{{baseUrl}}"],"path":["webhooks",":id","test"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Manda en el acto un evento `webhook.test` firmado con el secreto vigente y devuelve la entrega con `lastStatus` / `lastError`. No se reintenta ni cuenta para apagar el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/webhooks/:id/test","host":["{{baseUrl}}"],"path":["webhooks",":id","test"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del webhook."}]},"description":"Manda en el acto un evento `webhook.test` firmado con el secreto vigente y devuelve la entrega con `lastStatus` / `lastError`. No se reintenta ni cuenta para apagar el webhook. Consume cuota de escritura.\n\nScope: `webhooks:manage`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]}]},{"name":"Partidos","description":"Partidos públicos del club: el cartel \"sumate\" y publicar un turno muerto en Skalia. Sólo contadores, nunca jugadores.","item":[{"name":"Listar partidos públicos (listMatches)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado público. Sin filtro: todos (`OPEN`, `FULL`, `IN_PROGRESS`, `COMPLETED`, `CANCELLED`).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-30","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los partidos de esta cancha.","disabled":true},{"key":"sport","value":"PADEL","description":"Sólo los de este deporte (`PADEL`, `TENNIS`, …; sin distinguir mayúsculas).","disabled":true},{"key":"isCompetitive","value":"true","description":"`true` sólo los competitivos, `false` sólo los amistosos.","disabled":true}]},"description":"Los partidos PÚBLICOS del club (los mismos que ve la app en \"Buscar partido\" y en resultados): nunca privados ni a la espera de aprobación; `COMPLETED` sólo con resultado confirmado. Todos los orígenes (app, panel, API), anónimos: cupo por contadores, nunca jugadores. Orden: fecha y hora, id. `limit` ≤ 200 (default 100).\n\nScope: `matches:read`."},"response":[{"name":"200 · Página de partidos.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado público. Sin filtro: todos (`OPEN`, `FULL`, `IN_PROGRESS`, `COMPLETED`, `CANCELLED`).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-30","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los partidos de esta cancha.","disabled":true},{"key":"sport","value":"PADEL","description":"Sólo los de este deporte (`PADEL`, `TENNIS`, …; sin distinguir mayúsculas).","disabled":true},{"key":"isCompetitive","value":"true","description":"`true` sólo los competitivos, `false` sólo los amistosos.","disabled":true}]},"description":"Los partidos PÚBLICOS del club (los mismos que ve la app en \"Buscar partido\" y en resultados): nunca privados ni a la espera de aprobación; `COMPLETED` sólo con resultado confirmado. Todos los orígenes (app, panel, API), anónimos: cupo por contadores, nunca jugadores. Orden: fecha y hora, id. `limit` ≤ 200 (default 100).\n\nScope: `matches:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"matches\": [\n    {\n      \"id\": \"9c1d2e3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f\",\n      \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n      \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n      \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n      \"sport\": \"PADEL\",\n      \"matchType\": \"DOUBLES\",\n      \"status\": \"OPEN\",\n      \"isCompetitive\": false,\n      \"genderType\": \"MIXED\",\n      \"categories\": [\n        \"4ta\",\n        \"5ta\"\n      ],\n      \"date\": \"2026-09-15\",\n      \"startTime\": \"21:00\",\n      \"durationMinutes\": 90,\n      \"spots\": {\n        \"total\": 4,\n        \"taken\": 2\n      },\n      \"owned\": true,\n      \"result\": null,\n      \"cancellationReason\": null,\n      \"joinUrl\": \"https://www.skaliasports.com/partidos/9c1d2e3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f\",\n      \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n    }\n  ],\n  \"total\": 1,\n  \"limit\": 100,\n  \"offset\": 0\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado público. Sin filtro: todos (`OPEN`, `FULL`, `IN_PROGRESS`, `COMPLETED`, `CANCELLED`).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-30","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los partidos de esta cancha.","disabled":true},{"key":"sport","value":"PADEL","description":"Sólo los de este deporte (`PADEL`, `TENNIS`, …; sin distinguir mayúsculas).","disabled":true},{"key":"isCompetitive","value":"true","description":"`true` sólo los competitivos, `false` sólo los amistosos.","disabled":true}]},"description":"Los partidos PÚBLICOS del club (los mismos que ve la app en \"Buscar partido\" y en resultados): nunca privados ni a la espera de aprobación; `COMPLETED` sólo con resultado confirmado. Todos los orígenes (app, panel, API), anónimos: cupo por contadores, nunca jugadores. Orden: fecha y hora, id. `limit` ≤ 200 (default 100).\n\nScope: `matches:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado público. Sin filtro: todos (`OPEN`, `FULL`, `IN_PROGRESS`, `COMPLETED`, `CANCELLED`).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-30","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los partidos de esta cancha.","disabled":true},{"key":"sport","value":"PADEL","description":"Sólo los de este deporte (`PADEL`, `TENNIS`, …; sin distinguir mayúsculas).","disabled":true},{"key":"isCompetitive","value":"true","description":"`true` sólo los competitivos, `false` sólo los amistosos.","disabled":true}]},"description":"Los partidos PÚBLICOS del club (los mismos que ve la app en \"Buscar partido\" y en resultados): nunca privados ni a la espera de aprobación; `COMPLETED` sólo con resultado confirmado. Todos los orígenes (app, panel, API), anónimos: cupo por contadores, nunca jugadores. Orden: fecha y hora, id. `limit` ≤ 200 (default 100).\n\nScope: `matches:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado público. Sin filtro: todos (`OPEN`, `FULL`, `IN_PROGRESS`, `COMPLETED`, `CANCELLED`).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-30","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los partidos de esta cancha.","disabled":true},{"key":"sport","value":"PADEL","description":"Sólo los de este deporte (`PADEL`, `TENNIS`, …; sin distinguir mayúsculas).","disabled":true},{"key":"isCompetitive","value":"true","description":"`true` sólo los competitivos, `false` sólo los amistosos.","disabled":true}]},"description":"Los partidos PÚBLICOS del club (los mismos que ve la app en \"Buscar partido\" y en resultados): nunca privados ni a la espera de aprobación; `COMPLETED` sólo con resultado confirmado. Todos los orígenes (app, panel, API), anónimos: cupo por contadores, nunca jugadores. Orden: fecha y hora, id. `limit` ≤ 200 (default 100).\n\nScope: `matches:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado público. Sin filtro: todos (`OPEN`, `FULL`, `IN_PROGRESS`, `COMPLETED`, `CANCELLED`).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-30","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los partidos de esta cancha.","disabled":true},{"key":"sport","value":"PADEL","description":"Sólo los de este deporte (`PADEL`, `TENNIS`, …; sin distinguir mayúsculas).","disabled":true},{"key":"isCompetitive","value":"true","description":"`true` sólo los competitivos, `false` sólo los amistosos.","disabled":true}]},"description":"Los partidos PÚBLICOS del club (los mismos que ve la app en \"Buscar partido\" y en resultados): nunca privados ni a la espera de aprobación; `COMPLETED` sólo con resultado confirmado. Todos los orígenes (app, panel, API), anónimos: cupo por contadores, nunca jugadores. Orden: fecha y hora, id. `limit` ≤ 200 (default 100).\n\nScope: `matches:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado público. Sin filtro: todos (`OPEN`, `FULL`, `IN_PROGRESS`, `COMPLETED`, `CANCELLED`).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-30","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los partidos de esta cancha.","disabled":true},{"key":"sport","value":"PADEL","description":"Sólo los de este deporte (`PADEL`, `TENNIS`, …; sin distinguir mayúsculas).","disabled":true},{"key":"isCompetitive","value":"true","description":"`true` sólo los competitivos, `false` sólo los amistosos.","disabled":true}]},"description":"Los partidos PÚBLICOS del club (los mismos que ve la app en \"Buscar partido\" y en resultados): nunca privados ni a la espera de aprobación; `COMPLETED` sólo con resultado confirmado. Todos los orígenes (app, panel, API), anónimos: cupo por contadores, nunca jugadores. Orden: fecha y hora, id. `limit` ≤ 200 (default 100).\n\nScope: `matches:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado público. Sin filtro: todos (`OPEN`, `FULL`, `IN_PROGRESS`, `COMPLETED`, `CANCELLED`).","disabled":true},{"key":"from","value":"2026-09-15","description":"Desde este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"to","value":"2026-09-30","description":"Hasta este día (inclusive), `YYYY-MM-DD` naive del club.","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo los partidos de esta cancha.","disabled":true},{"key":"sport","value":"PADEL","description":"Sólo los de este deporte (`PADEL`, `TENNIS`, …; sin distinguir mayúsculas).","disabled":true},{"key":"isCompetitive","value":"true","description":"`true` sólo los competitivos, `false` sólo los amistosos.","disabled":true}]},"description":"Los partidos PÚBLICOS del club (los mismos que ve la app en \"Buscar partido\" y en resultados): nunca privados ni a la espera de aprobación; `COMPLETED` sólo con resultado confirmado. Todos los orígenes (app, panel, API), anónimos: cupo por contadores, nunca jugadores. Orden: fecha y hora, id. `limit` ≤ 200 (default 100).\n\nScope: `matches:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Publicar un partido sobre una reserva (publishMatch)","request":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"]},"description":"El sistema del club detecta el turno muerto y lo publica en Skalia: el partido nace `OPEN`, público, del club (no se autocancela a las 3 h como los de un jugador: espera el resultado 48 h), sobre una reserva **propia** (o cualquiera del club con `canManageAllBookings`) que ya existe, `CONFIRMED` y con el turno sin terminar, en una cancha. Fecha, hora, duración y cancha salen de la reserva; una publicación viva por reserva. Skalia hace el push por `notifyCategories` (\"{club} abrió un partido para tu categoría\", en background). Emite `booking.updated` (reason `match`) sobre la reserva. Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n  \"matchType\": \"DOUBLES\",\n  \"genderType\": \"MIXED\",\n  \"isCompetitive\": false,\n  \"categories\": [\n    \"4ta\",\n    \"5ta\"\n  ],\n  \"notifyCategories\": [\n    \"4ta\",\n    \"5ta\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"201 · Publicado.","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"]},"description":"El sistema del club detecta el turno muerto y lo publica en Skalia: el partido nace `OPEN`, público, del club (no se autocancela a las 3 h como los de un jugador: espera el resultado 48 h), sobre una reserva **propia** (o cualquiera del club con `canManageAllBookings`) que ya existe, `CONFIRMED` y con el turno sin terminar, en una cancha. Fecha, hora, duración y cancha salen de la reserva; una publicación viva por reserva. Skalia hace el push por `notifyCategories` (\"{club} abrió un partido para tu categoría\", en background). Emite `booking.updated` (reason `match`) sobre la reserva. Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n  \"matchType\": \"DOUBLES\",\n  \"genderType\": \"MIXED\",\n  \"isCompetitive\": false,\n  \"categories\": [\n    \"4ta\",\n    \"5ta\"\n  ],\n  \"notifyCategories\": [\n    \"4ta\",\n    \"5ta\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"match\": {\n    \"id\": \"9c1d2e3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"sport\": \"PADEL\",\n    \"matchType\": \"DOUBLES\",\n    \"status\": \"OPEN\",\n    \"isCompetitive\": false,\n    \"genderType\": \"MIXED\",\n    \"categories\": [\n      \"4ta\",\n      \"5ta\"\n    ],\n    \"date\": \"2026-09-15\",\n    \"startTime\": \"21:00\",\n    \"durationMinutes\": 90,\n    \"spots\": {\n      \"total\": 4,\n      \"taken\": 2\n    },\n    \"owned\": true,\n    \"result\": null,\n    \"cancellationReason\": null,\n    \"joinUrl\": \"https://www.skaliasports.com/partidos/9c1d2e3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f\",\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n  }\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / RESOURCE_NOT_COURT","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"]},"description":"El sistema del club detecta el turno muerto y lo publica en Skalia: el partido nace `OPEN`, público, del club (no se autocancela a las 3 h como los de un jugador: espera el resultado 48 h), sobre una reserva **propia** (o cualquiera del club con `canManageAllBookings`) que ya existe, `CONFIRMED` y con el turno sin terminar, en una cancha. Fecha, hora, duración y cancha salen de la reserva; una publicación viva por reserva. Skalia hace el push por `notifyCategories` (\"{club} abrió un partido para tu categoría\", en background). Emite `booking.updated` (reason `match`) sobre la reserva. Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n  \"matchType\": \"DOUBLES\",\n  \"genderType\": \"MIXED\",\n  \"isCompetitive\": false,\n  \"categories\": [\n    \"4ta\",\n    \"5ta\"\n  ],\n  \"notifyCategories\": [\n    \"4ta\",\n    \"5ta\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"]},"description":"El sistema del club detecta el turno muerto y lo publica en Skalia: el partido nace `OPEN`, público, del club (no se autocancela a las 3 h como los de un jugador: espera el resultado 48 h), sobre una reserva **propia** (o cualquiera del club con `canManageAllBookings`) que ya existe, `CONFIRMED` y con el turno sin terminar, en una cancha. Fecha, hora, duración y cancha salen de la reserva; una publicación viva por reserva. Skalia hace el push por `notifyCategories` (\"{club} abrió un partido para tu categoría\", en background). Emite `booking.updated` (reason `match`) sobre la reserva. Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n  \"matchType\": \"DOUBLES\",\n  \"genderType\": \"MIXED\",\n  \"isCompetitive\": false,\n  \"categories\": [\n    \"4ta\",\n    \"5ta\"\n  ],\n  \"notifyCategories\": [\n    \"4ta\",\n    \"5ta\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED / BOOKING_NOT_OWNED_BY_CLIENT","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"]},"description":"El sistema del club detecta el turno muerto y lo publica en Skalia: el partido nace `OPEN`, público, del club (no se autocancela a las 3 h como los de un jugador: espera el resultado 48 h), sobre una reserva **propia** (o cualquiera del club con `canManageAllBookings`) que ya existe, `CONFIRMED` y con el turno sin terminar, en una cancha. Fecha, hora, duración y cancha salen de la reserva; una publicación viva por reserva. Skalia hace el push por `notifyCategories` (\"{club} abrió un partido para tu categoría\", en background). Emite `booking.updated` (reason `match`) sobre la reserva. Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n  \"matchType\": \"DOUBLES\",\n  \"genderType\": \"MIXED\",\n  \"isCompetitive\": false,\n  \"categories\": [\n    \"4ta\",\n    \"5ta\"\n  ],\n  \"notifyCategories\": [\n    \"4ta\",\n    \"5ta\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · BOOKING_NOT_FOUND","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"]},"description":"El sistema del club detecta el turno muerto y lo publica en Skalia: el partido nace `OPEN`, público, del club (no se autocancela a las 3 h como los de un jugador: espera el resultado 48 h), sobre una reserva **propia** (o cualquiera del club con `canManageAllBookings`) que ya existe, `CONFIRMED` y con el turno sin terminar, en una cancha. Fecha, hora, duración y cancha salen de la reserva; una publicación viva por reserva. Skalia hace el push por `notifyCategories` (\"{club} abrió un partido para tu categoría\", en background). Emite `booking.updated` (reason `match`) sobre la reserva. Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n  \"matchType\": \"DOUBLES\",\n  \"genderType\": \"MIXED\",\n  \"isCompetitive\": false,\n  \"categories\": [\n    \"4ta\",\n    \"5ta\"\n  ],\n  \"notifyCategories\": [\n    \"4ta\",\n    \"5ta\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva no existe o no es de este club.\",\n  \"code\": \"BOOKING_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · MATCH_ALREADY_PUBLISHED / BOOKING_NOT_MODIFIABLE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"]},"description":"El sistema del club detecta el turno muerto y lo publica en Skalia: el partido nace `OPEN`, público, del club (no se autocancela a las 3 h como los de un jugador: espera el resultado 48 h), sobre una reserva **propia** (o cualquiera del club con `canManageAllBookings`) que ya existe, `CONFIRMED` y con el turno sin terminar, en una cancha. Fecha, hora, duración y cancha salen de la reserva; una publicación viva por reserva. Skalia hace el push por `notifyCategories` (\"{club} abrió un partido para tu categoría\", en background). Emite `booking.updated` (reason `match`) sobre la reserva. Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n  \"matchType\": \"DOUBLES\",\n  \"genderType\": \"MIXED\",\n  \"isCompetitive\": false,\n  \"categories\": [\n    \"4ta\",\n    \"5ta\"\n  ],\n  \"notifyCategories\": [\n    \"4ta\",\n    \"5ta\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La reserva ya tiene un partido publicado.\",\n  \"code\": \"MATCH_ALREADY_PUBLISHED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"415 · UNSUPPORTED_MEDIA_TYPE","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"]},"description":"El sistema del club detecta el turno muerto y lo publica en Skalia: el partido nace `OPEN`, público, del club (no se autocancela a las 3 h como los de un jugador: espera el resultado 48 h), sobre una reserva **propia** (o cualquiera del club con `canManageAllBookings`) que ya existe, `CONFIRMED` y con el turno sin terminar, en una cancha. Fecha, hora, duración y cancha salen de la reserva; una publicación viva por reserva. Skalia hace el push por `notifyCategories` (\"{club} abrió un partido para tu categoría\", en background). Emite `booking.updated` (reason `match`) sobre la reserva. Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n  \"matchType\": \"DOUBLES\",\n  \"genderType\": \"MIXED\",\n  \"isCompetitive\": false,\n  \"categories\": [\n    \"4ta\",\n    \"5ta\"\n  ],\n  \"notifyCategories\": [\n    \"4ta\",\n    \"5ta\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Unsupported Media Type","code":415,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El cuerpo tiene que ser JSON (Content-Type: application/json).\",\n  \"code\": \"UNSUPPORTED_MEDIA_TYPE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"]},"description":"El sistema del club detecta el turno muerto y lo publica en Skalia: el partido nace `OPEN`, público, del club (no se autocancela a las 3 h como los de un jugador: espera el resultado 48 h), sobre una reserva **propia** (o cualquiera del club con `canManageAllBookings`) que ya existe, `CONFIRMED` y con el turno sin terminar, en una cancha. Fecha, hora, duración y cancha salen de la reserva; una publicación viva por reserva. Skalia hace el push por `notifyCategories` (\"{club} abrió un partido para tu categoría\", en background). Emite `booking.updated` (reason `match`) sobre la reserva. Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n  \"matchType\": \"DOUBLES\",\n  \"genderType\": \"MIXED\",\n  \"isCompetitive\": false,\n  \"categories\": [\n    \"4ta\",\n    \"5ta\"\n  ],\n  \"notifyCategories\": [\n    \"4ta\",\n    \"5ta\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"]},"description":"El sistema del club detecta el turno muerto y lo publica en Skalia: el partido nace `OPEN`, público, del club (no se autocancela a las 3 h como los de un jugador: espera el resultado 48 h), sobre una reserva **propia** (o cualquiera del club con `canManageAllBookings`) que ya existe, `CONFIRMED` y con el turno sin terminar, en una cancha. Fecha, hora, duración y cancha salen de la reserva; una publicación viva por reserva. Skalia hace el push por `notifyCategories` (\"{club} abrió un partido para tu categoría\", en background). Emite `booking.updated` (reason `match`) sobre la reserva. Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n  \"matchType\": \"DOUBLES\",\n  \"genderType\": \"MIXED\",\n  \"isCompetitive\": false,\n  \"categories\": [\n    \"4ta\",\n    \"5ta\"\n  ],\n  \"notifyCategories\": [\n    \"4ta\",\n    \"5ta\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"POST","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/matches","host":["{{baseUrl}}"],"path":["matches"]},"description":"El sistema del club detecta el turno muerto y lo publica en Skalia: el partido nace `OPEN`, público, del club (no se autocancela a las 3 h como los de un jugador: espera el resultado 48 h), sobre una reserva **propia** (o cualquiera del club con `canManageAllBookings`) que ya existe, `CONFIRMED` y con el turno sin terminar, en una cancha. Fecha, hora, duración y cancha salen de la reserva; una publicación viva por reserva. Skalia hace el push por `notifyCategories` (\"{club} abrió un partido para tu categoría\", en background). Emite `booking.updated` (reason `match`) sobre la reserva. Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura.","body":{"mode":"raw","raw":"{\n  \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n  \"matchType\": \"DOUBLES\",\n  \"genderType\": \"MIXED\",\n  \"isCompetitive\": false,\n  \"categories\": [\n    \"4ta\",\n    \"5ta\"\n  ],\n  \"notifyCategories\": [\n    \"4ta\",\n    \"5ta\"\n  ]\n}","options":{"raw":{"language":"json"}}}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Detalle de un partido (getMatch)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"El destino del `Location` del POST y el refresco del cartel. Un `CANCELLED` sí se devuelve (para que el cartel lo saque); un partido privado, a la espera del club o de un club sin grant es 404 (no se confirma nada).\n\nScope: `matches:read`."},"response":[{"name":"200 · El partido.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"El destino del `Location` del POST y el refresco del cartel. Un `CANCELLED` sí se devuelve (para que el cartel lo saque); un partido privado, a la espera del club o de un club sin grant es 404 (no se confirma nada).\n\nScope: `matches:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"match\": {\n    \"id\": \"9c1d2e3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"sport\": \"PADEL\",\n    \"matchType\": \"DOUBLES\",\n    \"status\": \"OPEN\",\n    \"isCompetitive\": false,\n    \"genderType\": \"MIXED\",\n    \"categories\": [\n      \"4ta\",\n      \"5ta\"\n    ],\n    \"date\": \"2026-09-15\",\n    \"startTime\": \"21:00\",\n    \"durationMinutes\": 90,\n    \"spots\": {\n      \"total\": 4,\n      \"taken\": 2\n    },\n    \"owned\": true,\n    \"result\": null,\n    \"cancellationReason\": null,\n    \"joinUrl\": \"https://www.skaliasports.com/partidos/9c1d2e3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f\",\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n  }\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"El destino del `Location` del POST y el refresco del cartel. Un `CANCELLED` sí se devuelve (para que el cartel lo saque); un partido privado, a la espera del club o de un club sin grant es 404 (no se confirma nada).\n\nScope: `matches:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"El destino del `Location` del POST y el refresco del cartel. Un `CANCELLED` sí se devuelve (para que el cartel lo saque); un partido privado, a la espera del club o de un club sin grant es 404 (no se confirma nada).\n\nScope: `matches:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"El destino del `Location` del POST y el refresco del cartel. Un `CANCELLED` sí se devuelve (para que el cartel lo saque); un partido privado, a la espera del club o de un club sin grant es 404 (no se confirma nada).\n\nScope: `matches:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · MATCH_NOT_FOUND","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"El destino del `Location` del POST y el refresco del cartel. Un `CANCELLED` sí se devuelve (para que el cartel lo saque); un partido privado, a la espera del club o de un club sin grant es 404 (no se confirma nada).\n\nScope: `matches:read`."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El partido no existe o no es de este club.\",\n  \"code\": \"MATCH_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"El destino del `Location` del POST y el refresco del cartel. Un `CANCELLED` sí se devuelve (para que el cartel lo saque); un partido privado, a la espera del club o de un club sin grant es 404 (no se confirma nada).\n\nScope: `matches:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"El destino del `Location` del POST y el refresco del cartel. Un `CANCELLED` sí se devuelve (para que el cartel lo saque); un partido privado, a la espera del club o de un club sin grant es 404 (no se confirma nada).\n\nScope: `matches:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"El destino del `Location` del POST y el refresco del cartel. Un `CANCELLED` sí se devuelve (para que el cartel lo saque); un partido privado, a la espera del club o de un club sin grant es 404 (no se confirma nada).\n\nScope: `matches:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Dar de baja un partido publicado (cancelMatch)","request":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"query":[{"key":"reason","value":"el cliente canceló","description":"Motivo interno (va al audit; el jugador ve \"Cancelado por el club\").","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"Cancela el partido como lo haría el panel (`cancellation_reason` \"Cancelado por el club\", aviso al roster, video del partido cancelado): sólo los que publicó esta integración (o cualquiera del club con `canManageAllBookings`), sólo `OPEN` / `FULL`. Idempotente sobre un `CANCELLED` (`changed: false`). La reserva NO se toca (el club sigue teniendo la cancha vendida): sólo baja su `matchCount` (`booking.updated`). Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura."},"response":[{"name":"200 · Cancelado, o ya lo estaba (`changed: false`).","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"query":[{"key":"reason","value":"el cliente canceló","description":"Motivo interno (va al audit; el jugador ve \"Cancelado por el club\").","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"Cancela el partido como lo haría el panel (`cancellation_reason` \"Cancelado por el club\", aviso al roster, video del partido cancelado): sólo los que publicó esta integración (o cualquiera del club con `canManageAllBookings`), sólo `OPEN` / `FULL`. Idempotente sobre un `CANCELLED` (`changed: false`). La reserva NO se toca (el club sigue teniendo la cancha vendida): sólo baja su `matchCount` (`booking.updated`). Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"match\": {\n    \"id\": \"9c1d2e3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n    \"bookingId\": \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\",\n    \"sport\": \"PADEL\",\n    \"matchType\": \"DOUBLES\",\n    \"status\": \"CANCELLED\",\n    \"isCompetitive\": false,\n    \"genderType\": \"MIXED\",\n    \"categories\": [\n      \"4ta\",\n      \"5ta\"\n    ],\n    \"date\": \"2026-09-15\",\n    \"startTime\": \"21:00\",\n    \"durationMinutes\": 90,\n    \"spots\": {\n      \"total\": 4,\n      \"taken\": 2\n    },\n    \"owned\": true,\n    \"result\": null,\n    \"cancellationReason\": \"Cancelado por el club\",\n    \"joinUrl\": \"https://www.skaliasports.com/partidos/9c1d2e3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f\",\n    \"createdAt\": \"2026-09-14T12:00:00.000Z\"\n  },\n  \"changed\": true\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"query":[{"key":"reason","value":"el cliente canceló","description":"Motivo interno (va al audit; el jugador ve \"Cancelado por el club\").","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"Cancela el partido como lo haría el panel (`cancellation_reason` \"Cancelado por el club\", aviso al roster, video del partido cancelado): sólo los que publicó esta integración (o cualquiera del club con `canManageAllBookings`), sólo `OPEN` / `FULL`. Idempotente sobre un `CANCELLED` (`changed: false`). La reserva NO se toca (el club sigue teniendo la cancha vendida): sólo baja su `matchCount` (`booking.updated`). Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"query":[{"key":"reason","value":"el cliente canceló","description":"Motivo interno (va al audit; el jugador ve \"Cancelado por el club\").","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"Cancela el partido como lo haría el panel (`cancellation_reason` \"Cancelado por el club\", aviso al roster, video del partido cancelado): sólo los que publicó esta integración (o cualquiera del club con `canManageAllBookings`), sólo `OPEN` / `FULL`. Idempotente sobre un `CANCELLED` (`changed: false`). La reserva NO se toca (el club sigue teniendo la cancha vendida): sólo baja su `matchCount` (`booking.updated`). Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED / MATCH_NOT_OWNED_BY_CLIENT","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"query":[{"key":"reason","value":"el cliente canceló","description":"Motivo interno (va al audit; el jugador ve \"Cancelado por el club\").","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"Cancela el partido como lo haría el panel (`cancellation_reason` \"Cancelado por el club\", aviso al roster, video del partido cancelado): sólo los que publicó esta integración (o cualquiera del club con `canManageAllBookings`), sólo `OPEN` / `FULL`. Idempotente sobre un `CANCELLED` (`changed: false`). La reserva NO se toca (el club sigue teniendo la cancha vendida): sólo baja su `matchCount` (`booking.updated`). Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · MATCH_NOT_FOUND","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"query":[{"key":"reason","value":"el cliente canceló","description":"Motivo interno (va al audit; el jugador ve \"Cancelado por el club\").","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"Cancela el partido como lo haría el panel (`cancellation_reason` \"Cancelado por el club\", aviso al roster, video del partido cancelado): sólo los que publicó esta integración (o cualquiera del club con `canManageAllBookings`), sólo `OPEN` / `FULL`. Idempotente sobre un `CANCELLED` (`changed: false`). La reserva NO se toca (el club sigue teniendo la cancha vendida): sólo baja su `matchCount` (`booking.updated`). Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El partido no existe o no es de este club.\",\n  \"code\": \"MATCH_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"409 · MATCH_NOT_MODIFIABLE","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"query":[{"key":"reason","value":"el cliente canceló","description":"Motivo interno (va al audit; el jugador ve \"Cancelado por el club\").","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"Cancela el partido como lo haría el panel (`cancellation_reason` \"Cancelado por el club\", aviso al roster, video del partido cancelado): sólo los que publicó esta integración (o cualquiera del club con `canManageAllBookings`), sólo `OPEN` / `FULL`. Idempotente sobre un `CANCELLED` (`changed: false`). La reserva NO se toca (el club sigue teniendo la cancha vendida): sólo baja su `matchCount` (`booking.updated`). Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura."},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El partido ya no se puede dar de baja: se está jugando, se jugó o ya cerró.\",\n  \"code\": \"MATCH_NOT_MODIFIABLE\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"query":[{"key":"reason","value":"el cliente canceló","description":"Motivo interno (va al audit; el jugador ve \"Cancelado por el club\").","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"Cancela el partido como lo haría el panel (`cancellation_reason` \"Cancelado por el club\", aviso al roster, video del partido cancelado): sólo los que publicó esta integración (o cualquiera del club con `canManageAllBookings`), sólo `OPEN` / `FULL`. Idempotente sobre un `CANCELLED` (`changed: false`). La reserva NO se toca (el club sigue teniendo la cancha vendida): sólo baja su `matchCount` (`booking.updated`). Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"query":[{"key":"reason","value":"el cliente canceló","description":"Motivo interno (va al audit; el jugador ve \"Cancelado por el club\").","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"Cancela el partido como lo haría el panel (`cancellation_reason` \"Cancelado por el club\", aviso al roster, video del partido cancelado): sólo los que publicó esta integración (o cualquiera del club con `canManageAllBookings`), sólo `OPEN` / `FULL`. Idempotente sobre un `CANCELLED` (`changed: false`). La reserva NO se toca (el club sigue teniendo la cancha vendida): sólo baja su `matchCount` (`booking.updated`). Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"DELETE","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/matches/:id","host":["{{baseUrl}}"],"path":["matches",":id"],"query":[{"key":"reason","value":"el cliente canceló","description":"Motivo interno (va al audit; el jugador ve \"Cancelado por el club\").","disabled":true}],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del partido."}]},"description":"Cancela el partido como lo haría el panel (`cancellation_reason` \"Cancelado por el club\", aviso al roster, video del partido cancelado): sólo los que publicó esta integración (o cualquiera del club con `canManageAllBookings`), sólo `OPEN` / `FULL`. Idempotente sobre un `CANCELLED` (`changed: false`). La reserva NO se toca (el club sigue teniendo la cancha vendida): sólo baja su `matchCount` (`booking.updated`). Consume cuota de escritura.\n\nScope: `matches:write`. Consume cuota de escritura."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]}]},{"name":"Reportes","description":"Totales de horas y venta esperada del club, sin personas.","item":[{"name":"Horas y venta esperada del club (getBookingsReport)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/reports/bookings?from=2026-09-01&to=2026-09-30","host":["{{baseUrl}}"],"path":["reports","bookings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-01","description":"Primer día JUGADO del rango (`YYYY-MM-DD` naive del club).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día (inclusive); `to ≥ from` y como mucho 366 días.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esta cancha / recurso del club (404 COURT_NOT_FOUND si no es del club).","disabled":true},{"key":"categoryId","value":"court-implicit","description":"Sólo esta categoría de recurso (F6), o `court-implicit` para las canchas sin categoría (404 CATEGORY_NOT_FOUND si no es del club).","disabled":true},{"key":"kind","value":"COURT","description":"Sólo los recursos de este kind (`COURT`, `CLINIC`, `RESTAURANT`, `OTHER`).","disabled":true},{"key":"groupBy","value":"court","description":"Dimensión de `groups`: `court`, `category`, `type` o `source`. Sin `groupBy`, `groups` es `null`.","disabled":true}]},"description":"Totales de las reservas JUGADAS en `[from, to]` (días naive del club, ≤ 366 días): puntuales y ocurrencias materializadas de fijas, de todos los orígenes (app, panel, QuieroJugar, esta y otras integraciones), `status != CANCELLED`, sin los placeholders del importador de QJ. Es el mismo dataset que el panel exporta a CSV / XLSX. `price` es la venta ESPERADA con la precedencia del panel (`price_override` total → `price` materializado → pro-rata del precio/hora), nunca lo cobrado (`priceIsExpected: true`). Sólo agregados: `totals` (+ `byType`, `bySource`) y, con `groupBy`, un grupo por cancha / categoría / tipo / origen. Ninguna fila por reserva ni por persona. `bySource` identifica sólo a tu integración (`apiClientId`); las demás van sumadas en una fila `api` anónima. Scope `reports:read` (opt-in y sensible: lo emite el dueño del club). No consume cuota de escritura.\n\nScope: `reports:read`."},"response":[{"name":"200 · Totales del rango.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/reports/bookings?from=2026-09-01&to=2026-09-30","host":["{{baseUrl}}"],"path":["reports","bookings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-01","description":"Primer día JUGADO del rango (`YYYY-MM-DD` naive del club).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día (inclusive); `to ≥ from` y como mucho 366 días.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esta cancha / recurso del club (404 COURT_NOT_FOUND si no es del club).","disabled":true},{"key":"categoryId","value":"court-implicit","description":"Sólo esta categoría de recurso (F6), o `court-implicit` para las canchas sin categoría (404 CATEGORY_NOT_FOUND si no es del club).","disabled":true},{"key":"kind","value":"COURT","description":"Sólo los recursos de este kind (`COURT`, `CLINIC`, `RESTAURANT`, `OTHER`).","disabled":true},{"key":"groupBy","value":"court","description":"Dimensión de `groups`: `court`, `category`, `type` o `source`. Sin `groupBy`, `groups` es `null`.","disabled":true}]},"description":"Totales de las reservas JUGADAS en `[from, to]` (días naive del club, ≤ 366 días): puntuales y ocurrencias materializadas de fijas, de todos los orígenes (app, panel, QuieroJugar, esta y otras integraciones), `status != CANCELLED`, sin los placeholders del importador de QJ. Es el mismo dataset que el panel exporta a CSV / XLSX. `price` es la venta ESPERADA con la precedencia del panel (`price_override` total → `price` materializado → pro-rata del precio/hora), nunca lo cobrado (`priceIsExpected: true`). Sólo agregados: `totals` (+ `byType`, `bySource`) y, con `groupBy`, un grupo por cancha / categoría / tipo / origen. Ninguna fila por reserva ni por persona. `bySource` identifica sólo a tu integración (`apiClientId`); las demás van sumadas en una fila `api` anónima. Scope `reports:read` (opt-in y sensible: lo emite el dueño del club). No consume cuota de escritura.\n\nScope: `reports:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n  \"from\": \"2026-09-01\",\n  \"to\": \"2026-09-30\",\n  \"timezone\": \"America/Montevideo\",\n  \"currency\": \"UYU\",\n  \"totals\": {\n    \"count\": 42,\n    \"durationMinutes\": 3780,\n    \"price\": 58800,\n    \"priceIsExpected\": true,\n    \"byType\": [\n      {\n        \"type\": \"normal\",\n        \"count\": 38,\n        \"durationMinutes\": 3420,\n        \"price\": 54600\n      },\n      {\n        \"type\": \"profe\",\n        \"count\": 4,\n        \"durationMinutes\": 360,\n        \"price\": 4200\n      }\n    ],\n    \"bySource\": [\n      {\n        \"source\": \"api\",\n        \"apiClientId\": \"2b4c6d8e-0f1a-4b2c-9d3e-4f5a6b7c8d9e\",\n        \"count\": 20,\n        \"durationMinutes\": 1800,\n        \"price\": 28000\n      },\n      {\n        \"source\": \"android\",\n        \"apiClientId\": null,\n        \"count\": 12,\n        \"durationMinutes\": 1080,\n        \"price\": 16800\n      },\n      {\n        \"source\": \"admin\",\n        \"apiClientId\": null,\n        \"count\": 6,\n        \"durationMinutes\": 540,\n        \"price\": 8400\n      },\n      {\n        \"source\": \"api\",\n        \"apiClientId\": null,\n        \"count\": 4,\n        \"durationMinutes\": 360,\n        \"price\": 5600\n      }\n    ]\n  },\n  \"groups\": [\n    {\n      \"key\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n      \"label\": \"Cancha 1\",\n      \"count\": 24,\n      \"durationMinutes\": 2160,\n      \"price\": 33600\n    },\n    {\n      \"key\": \"7c8d9e0f-1a2b-4c3d-8e4f-5a6b7c8d9e0f\",\n      \"label\": \"Cancha 2\",\n      \"count\": 18,\n      \"durationMinutes\": 1620,\n      \"price\": 25200\n    }\n  ]\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/reports/bookings?from=2026-09-01&to=2026-09-30","host":["{{baseUrl}}"],"path":["reports","bookings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-01","description":"Primer día JUGADO del rango (`YYYY-MM-DD` naive del club).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día (inclusive); `to ≥ from` y como mucho 366 días.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esta cancha / recurso del club (404 COURT_NOT_FOUND si no es del club).","disabled":true},{"key":"categoryId","value":"court-implicit","description":"Sólo esta categoría de recurso (F6), o `court-implicit` para las canchas sin categoría (404 CATEGORY_NOT_FOUND si no es del club).","disabled":true},{"key":"kind","value":"COURT","description":"Sólo los recursos de este kind (`COURT`, `CLINIC`, `RESTAURANT`, `OTHER`).","disabled":true},{"key":"groupBy","value":"court","description":"Dimensión de `groups`: `court`, `category`, `type` o `source`. Sin `groupBy`, `groups` es `null`.","disabled":true}]},"description":"Totales de las reservas JUGADAS en `[from, to]` (días naive del club, ≤ 366 días): puntuales y ocurrencias materializadas de fijas, de todos los orígenes (app, panel, QuieroJugar, esta y otras integraciones), `status != CANCELLED`, sin los placeholders del importador de QJ. Es el mismo dataset que el panel exporta a CSV / XLSX. `price` es la venta ESPERADA con la precedencia del panel (`price_override` total → `price` materializado → pro-rata del precio/hora), nunca lo cobrado (`priceIsExpected: true`). Sólo agregados: `totals` (+ `byType`, `bySource`) y, con `groupBy`, un grupo por cancha / categoría / tipo / origen. Ninguna fila por reserva ni por persona. `bySource` identifica sólo a tu integración (`apiClientId`); las demás van sumadas en una fila `api` anónima. Scope `reports:read` (opt-in y sensible: lo emite el dueño del club). No consume cuota de escritura.\n\nScope: `reports:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/reports/bookings?from=2026-09-01&to=2026-09-30","host":["{{baseUrl}}"],"path":["reports","bookings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-01","description":"Primer día JUGADO del rango (`YYYY-MM-DD` naive del club).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día (inclusive); `to ≥ from` y como mucho 366 días.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esta cancha / recurso del club (404 COURT_NOT_FOUND si no es del club).","disabled":true},{"key":"categoryId","value":"court-implicit","description":"Sólo esta categoría de recurso (F6), o `court-implicit` para las canchas sin categoría (404 CATEGORY_NOT_FOUND si no es del club).","disabled":true},{"key":"kind","value":"COURT","description":"Sólo los recursos de este kind (`COURT`, `CLINIC`, `RESTAURANT`, `OTHER`).","disabled":true},{"key":"groupBy","value":"court","description":"Dimensión de `groups`: `court`, `category`, `type` o `source`. Sin `groupBy`, `groups` es `null`.","disabled":true}]},"description":"Totales de las reservas JUGADAS en `[from, to]` (días naive del club, ≤ 366 días): puntuales y ocurrencias materializadas de fijas, de todos los orígenes (app, panel, QuieroJugar, esta y otras integraciones), `status != CANCELLED`, sin los placeholders del importador de QJ. Es el mismo dataset que el panel exporta a CSV / XLSX. `price` es la venta ESPERADA con la precedencia del panel (`price_override` total → `price` materializado → pro-rata del precio/hora), nunca lo cobrado (`priceIsExpected: true`). Sólo agregados: `totals` (+ `byType`, `bySource`) y, con `groupBy`, un grupo por cancha / categoría / tipo / origen. Ninguna fila por reserva ni por persona. `bySource` identifica sólo a tu integración (`apiClientId`); las demás van sumadas en una fila `api` anónima. Scope `reports:read` (opt-in y sensible: lo emite el dueño del club). No consume cuota de escritura.\n\nScope: `reports:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/reports/bookings?from=2026-09-01&to=2026-09-30","host":["{{baseUrl}}"],"path":["reports","bookings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-01","description":"Primer día JUGADO del rango (`YYYY-MM-DD` naive del club).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día (inclusive); `to ≥ from` y como mucho 366 días.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esta cancha / recurso del club (404 COURT_NOT_FOUND si no es del club).","disabled":true},{"key":"categoryId","value":"court-implicit","description":"Sólo esta categoría de recurso (F6), o `court-implicit` para las canchas sin categoría (404 CATEGORY_NOT_FOUND si no es del club).","disabled":true},{"key":"kind","value":"COURT","description":"Sólo los recursos de este kind (`COURT`, `CLINIC`, `RESTAURANT`, `OTHER`).","disabled":true},{"key":"groupBy","value":"court","description":"Dimensión de `groups`: `court`, `category`, `type` o `source`. Sin `groupBy`, `groups` es `null`.","disabled":true}]},"description":"Totales de las reservas JUGADAS en `[from, to]` (días naive del club, ≤ 366 días): puntuales y ocurrencias materializadas de fijas, de todos los orígenes (app, panel, QuieroJugar, esta y otras integraciones), `status != CANCELLED`, sin los placeholders del importador de QJ. Es el mismo dataset que el panel exporta a CSV / XLSX. `price` es la venta ESPERADA con la precedencia del panel (`price_override` total → `price` materializado → pro-rata del precio/hora), nunca lo cobrado (`priceIsExpected: true`). Sólo agregados: `totals` (+ `byType`, `bySource`) y, con `groupBy`, un grupo por cancha / categoría / tipo / origen. Ninguna fila por reserva ni por persona. `bySource` identifica sólo a tu integración (`apiClientId`); las demás van sumadas en una fila `api` anónima. Scope `reports:read` (opt-in y sensible: lo emite el dueño del club). No consume cuota de escritura.\n\nScope: `reports:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · COURT_NOT_FOUND / CATEGORY_NOT_FOUND","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/reports/bookings?from=2026-09-01&to=2026-09-30","host":["{{baseUrl}}"],"path":["reports","bookings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-01","description":"Primer día JUGADO del rango (`YYYY-MM-DD` naive del club).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día (inclusive); `to ≥ from` y como mucho 366 días.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esta cancha / recurso del club (404 COURT_NOT_FOUND si no es del club).","disabled":true},{"key":"categoryId","value":"court-implicit","description":"Sólo esta categoría de recurso (F6), o `court-implicit` para las canchas sin categoría (404 CATEGORY_NOT_FOUND si no es del club).","disabled":true},{"key":"kind","value":"COURT","description":"Sólo los recursos de este kind (`COURT`, `CLINIC`, `RESTAURANT`, `OTHER`).","disabled":true},{"key":"groupBy","value":"court","description":"Dimensión de `groups`: `court`, `category`, `type` o `source`. Sin `groupBy`, `groups` es `null`.","disabled":true}]},"description":"Totales de las reservas JUGADAS en `[from, to]` (días naive del club, ≤ 366 días): puntuales y ocurrencias materializadas de fijas, de todos los orígenes (app, panel, QuieroJugar, esta y otras integraciones), `status != CANCELLED`, sin los placeholders del importador de QJ. Es el mismo dataset que el panel exporta a CSV / XLSX. `price` es la venta ESPERADA con la precedencia del panel (`price_override` total → `price` materializado → pro-rata del precio/hora), nunca lo cobrado (`priceIsExpected: true`). Sólo agregados: `totals` (+ `byType`, `bySource`) y, con `groupBy`, un grupo por cancha / categoría / tipo / origen. Ninguna fila por reserva ni por persona. `bySource` identifica sólo a tu integración (`apiClientId`); las demás van sumadas en una fila `api` anónima. Scope `reports:read` (opt-in y sensible: lo emite el dueño del club). No consume cuota de escritura.\n\nScope: `reports:read`."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La cancha no existe o no es de este club.\",\n  \"code\": \"COURT_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/reports/bookings?from=2026-09-01&to=2026-09-30","host":["{{baseUrl}}"],"path":["reports","bookings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-01","description":"Primer día JUGADO del rango (`YYYY-MM-DD` naive del club).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día (inclusive); `to ≥ from` y como mucho 366 días.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esta cancha / recurso del club (404 COURT_NOT_FOUND si no es del club).","disabled":true},{"key":"categoryId","value":"court-implicit","description":"Sólo esta categoría de recurso (F6), o `court-implicit` para las canchas sin categoría (404 CATEGORY_NOT_FOUND si no es del club).","disabled":true},{"key":"kind","value":"COURT","description":"Sólo los recursos de este kind (`COURT`, `CLINIC`, `RESTAURANT`, `OTHER`).","disabled":true},{"key":"groupBy","value":"court","description":"Dimensión de `groups`: `court`, `category`, `type` o `source`. Sin `groupBy`, `groups` es `null`.","disabled":true}]},"description":"Totales de las reservas JUGADAS en `[from, to]` (días naive del club, ≤ 366 días): puntuales y ocurrencias materializadas de fijas, de todos los orígenes (app, panel, QuieroJugar, esta y otras integraciones), `status != CANCELLED`, sin los placeholders del importador de QJ. Es el mismo dataset que el panel exporta a CSV / XLSX. `price` es la venta ESPERADA con la precedencia del panel (`price_override` total → `price` materializado → pro-rata del precio/hora), nunca lo cobrado (`priceIsExpected: true`). Sólo agregados: `totals` (+ `byType`, `bySource`) y, con `groupBy`, un grupo por cancha / categoría / tipo / origen. Ninguna fila por reserva ni por persona. `bySource` identifica sólo a tu integración (`apiClientId`); las demás van sumadas en una fila `api` anónima. Scope `reports:read` (opt-in y sensible: lo emite el dueño del club). No consume cuota de escritura.\n\nScope: `reports:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/reports/bookings?from=2026-09-01&to=2026-09-30","host":["{{baseUrl}}"],"path":["reports","bookings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-01","description":"Primer día JUGADO del rango (`YYYY-MM-DD` naive del club).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día (inclusive); `to ≥ from` y como mucho 366 días.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esta cancha / recurso del club (404 COURT_NOT_FOUND si no es del club).","disabled":true},{"key":"categoryId","value":"court-implicit","description":"Sólo esta categoría de recurso (F6), o `court-implicit` para las canchas sin categoría (404 CATEGORY_NOT_FOUND si no es del club).","disabled":true},{"key":"kind","value":"COURT","description":"Sólo los recursos de este kind (`COURT`, `CLINIC`, `RESTAURANT`, `OTHER`).","disabled":true},{"key":"groupBy","value":"court","description":"Dimensión de `groups`: `court`, `category`, `type` o `source`. Sin `groupBy`, `groups` es `null`.","disabled":true}]},"description":"Totales de las reservas JUGADAS en `[from, to]` (días naive del club, ≤ 366 días): puntuales y ocurrencias materializadas de fijas, de todos los orígenes (app, panel, QuieroJugar, esta y otras integraciones), `status != CANCELLED`, sin los placeholders del importador de QJ. Es el mismo dataset que el panel exporta a CSV / XLSX. `price` es la venta ESPERADA con la precedencia del panel (`price_override` total → `price` materializado → pro-rata del precio/hora), nunca lo cobrado (`priceIsExpected: true`). Sólo agregados: `totals` (+ `byType`, `bySource`) y, con `groupBy`, un grupo por cancha / categoría / tipo / origen. Ninguna fila por reserva ni por persona. `bySource` identifica sólo a tu integración (`apiClientId`); las demás van sumadas en una fila `api` anónima. Scope `reports:read` (opt-in y sensible: lo emite el dueño del club). No consume cuota de escritura.\n\nScope: `reports:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/reports/bookings?from=2026-09-01&to=2026-09-30","host":["{{baseUrl}}"],"path":["reports","bookings"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"from","value":"2026-09-01","description":"Primer día JUGADO del rango (`YYYY-MM-DD` naive del club).","disabled":false},{"key":"to","value":"2026-09-30","description":"Último día (inclusive); `to ≥ from` y como mucho 366 días.","disabled":false},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esta cancha / recurso del club (404 COURT_NOT_FOUND si no es del club).","disabled":true},{"key":"categoryId","value":"court-implicit","description":"Sólo esta categoría de recurso (F6), o `court-implicit` para las canchas sin categoría (404 CATEGORY_NOT_FOUND si no es del club).","disabled":true},{"key":"kind","value":"COURT","description":"Sólo los recursos de este kind (`COURT`, `CLINIC`, `RESTAURANT`, `OTHER`).","disabled":true},{"key":"groupBy","value":"court","description":"Dimensión de `groups`: `court`, `category`, `type` o `source`. Sin `groupBy`, `groups` es `null`.","disabled":true}]},"description":"Totales de las reservas JUGADAS en `[from, to]` (días naive del club, ≤ 366 días): puntuales y ocurrencias materializadas de fijas, de todos los orígenes (app, panel, QuieroJugar, esta y otras integraciones), `status != CANCELLED`, sin los placeholders del importador de QJ. Es el mismo dataset que el panel exporta a CSV / XLSX. `price` es la venta ESPERADA con la precedencia del panel (`price_override` total → `price` materializado → pro-rata del precio/hora), nunca lo cobrado (`priceIsExpected: true`). Sólo agregados: `totals` (+ `byType`, `bySource`) y, con `groupBy`, un grupo por cancha / categoría / tipo / origen. Ninguna fila por reserva ni por persona. `bySource` identifica sólo a tu integración (`apiClientId`); las demás van sumadas en una fila `api` anónima. Scope `reports:read` (opt-in y sensible: lo emite el dueño del club). No consume cuota de escritura.\n\nScope: `reports:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]}]},{"name":"Americanos","description":"Americanos publicados por el club: cupos y estado. Sólo lectura; nunca los inscriptos. El `AmericanoDto` no trae URL: el enlace a Skalia se arma con el `id` (`https://www.skaliasports.com/americanos/<id>`).","item":[{"name":"Listar americanos del club (listAmericanos)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos","host":["{{baseUrl}}"],"path":["americanos"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado.","disabled":true},{"key":"from","value":"2026-09-18","description":"Americanos cuyo `startsAt` es ≥ `from` (`YYYY-MM-DD` naive del club).","disabled":true},{"key":"to","value":"2026-10-18","description":"Americanos cuyo `startsAt` es ≤ `to` (`YYYY-MM-DD` naive del club).","disabled":true}]},"description":"Americanos CLUB_PUBLIC del club (los que la app lista y a los que cualquier jugador puede sumarse), con cupos y estado, para publicarlos en la web del club. No hay campo de enlace: la web del club lo arma con el `id` (`https://www.skaliasports.com/americanos/<id>`: detalle público, sin login; en el celular abre la app). Orden: `startsAt` asc, alta asc. Con el flag `americano_tournaments_enabled` apagado en la plataforma responde `americanos: []`. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"response":[{"name":"200 · Página de americanos.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos","host":["{{baseUrl}}"],"path":["americanos"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado.","disabled":true},{"key":"from","value":"2026-09-18","description":"Americanos cuyo `startsAt` es ≥ `from` (`YYYY-MM-DD` naive del club).","disabled":true},{"key":"to","value":"2026-10-18","description":"Americanos cuyo `startsAt` es ≤ `to` (`YYYY-MM-DD` naive del club).","disabled":true}]},"description":"Americanos CLUB_PUBLIC del club (los que la app lista y a los que cualquier jugador puede sumarse), con cupos y estado, para publicarlos en la web del club. No hay campo de enlace: la web del club lo arma con el `id` (`https://www.skaliasports.com/americanos/<id>`: detalle público, sin login; en el celular abre la app). Orden: `startsAt` asc, alta asc. Con el flag `americano_tournaments_enabled` apagado en la plataforma responde `americanos: []`. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"americanos\": [\n    {\n      \"id\": \"6d5e4f3a-2b1c-4d0e-9f8a-7b6c5d4e3f2a\",\n      \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n      \"name\": \"Americano de los viernes\",\n      \"status\": \"OPEN\",\n      \"startsAt\": \"2026-09-25T20:00:00\",\n      \"maxPlayers\": 8,\n      \"confirmedCount\": 6,\n      \"isFull\": false,\n      \"registrationOpen\": true,\n      \"roundsPlanned\": 3,\n      \"currentRound\": 0,\n      \"gamesPerMatch\": 8,\n      \"matchMinutes\": 20,\n      \"courtIds\": [\n        \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\"\n      ],\n      \"price\": 500,\n      \"description\": \"Trae paleta. Se juega con lluvia.\",\n      \"location\": null,\n      \"finishedAt\": null,\n      \"cancelledAt\": null,\n      \"cancellationReason\": null,\n      \"createdAt\": \"2026-09-14T12:00:00Z\",\n      \"updatedAt\": \"2026-09-14T12:00:00Z\"\n    }\n  ],\n  \"total\": 1,\n  \"limit\": 100,\n  \"offset\": 0\n}"},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos","host":["{{baseUrl}}"],"path":["americanos"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado.","disabled":true},{"key":"from","value":"2026-09-18","description":"Americanos cuyo `startsAt` es ≥ `from` (`YYYY-MM-DD` naive del club).","disabled":true},{"key":"to","value":"2026-10-18","description":"Americanos cuyo `startsAt` es ≤ `to` (`YYYY-MM-DD` naive del club).","disabled":true}]},"description":"Americanos CLUB_PUBLIC del club (los que la app lista y a los que cualquier jugador puede sumarse), con cupos y estado, para publicarlos en la web del club. No hay campo de enlace: la web del club lo arma con el `id` (`https://www.skaliasports.com/americanos/<id>`: detalle público, sin login; en el celular abre la app). Orden: `startsAt` asc, alta asc. Con el flag `americano_tournaments_enabled` apagado en la plataforma responde `americanos: []`. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos","host":["{{baseUrl}}"],"path":["americanos"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado.","disabled":true},{"key":"from","value":"2026-09-18","description":"Americanos cuyo `startsAt` es ≥ `from` (`YYYY-MM-DD` naive del club).","disabled":true},{"key":"to","value":"2026-10-18","description":"Americanos cuyo `startsAt` es ≤ `to` (`YYYY-MM-DD` naive del club).","disabled":true}]},"description":"Americanos CLUB_PUBLIC del club (los que la app lista y a los que cualquier jugador puede sumarse), con cupos y estado, para publicarlos en la web del club. No hay campo de enlace: la web del club lo arma con el `id` (`https://www.skaliasports.com/americanos/<id>`: detalle público, sin login; en el celular abre la app). Orden: `startsAt` asc, alta asc. Con el flag `americano_tournaments_enabled` apagado en la plataforma responde `americanos: []`. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos","host":["{{baseUrl}}"],"path":["americanos"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado.","disabled":true},{"key":"from","value":"2026-09-18","description":"Americanos cuyo `startsAt` es ≥ `from` (`YYYY-MM-DD` naive del club).","disabled":true},{"key":"to","value":"2026-10-18","description":"Americanos cuyo `startsAt` es ≤ `to` (`YYYY-MM-DD` naive del club).","disabled":true}]},"description":"Americanos CLUB_PUBLIC del club (los que la app lista y a los que cualquier jugador puede sumarse), con cupos y estado, para publicarlos en la web del club. No hay campo de enlace: la web del club lo arma con el `id` (`https://www.skaliasports.com/americanos/<id>`: detalle público, sin login; en el celular abre la app). Orden: `startsAt` asc, alta asc. Con el flag `americano_tournaments_enabled` apagado en la plataforma responde `americanos: []`. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos","host":["{{baseUrl}}"],"path":["americanos"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado.","disabled":true},{"key":"from","value":"2026-09-18","description":"Americanos cuyo `startsAt` es ≥ `from` (`YYYY-MM-DD` naive del club).","disabled":true},{"key":"to","value":"2026-10-18","description":"Americanos cuyo `startsAt` es ≤ `to` (`YYYY-MM-DD` naive del club).","disabled":true}]},"description":"Americanos CLUB_PUBLIC del club (los que la app lista y a los que cualquier jugador puede sumarse), con cupos y estado, para publicarlos en la web del club. No hay campo de enlace: la web del club lo arma con el `id` (`https://www.skaliasports.com/americanos/<id>`: detalle público, sin login; en el celular abre la app). Orden: `startsAt` asc, alta asc. Con el flag `americano_tournaments_enabled` apagado en la plataforma responde `americanos: []`. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos","host":["{{baseUrl}}"],"path":["americanos"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado.","disabled":true},{"key":"from","value":"2026-09-18","description":"Americanos cuyo `startsAt` es ≥ `from` (`YYYY-MM-DD` naive del club).","disabled":true},{"key":"to","value":"2026-10-18","description":"Americanos cuyo `startsAt` es ≤ `to` (`YYYY-MM-DD` naive del club).","disabled":true}]},"description":"Americanos CLUB_PUBLIC del club (los que la app lista y a los que cualquier jugador puede sumarse), con cupos y estado, para publicarlos en la web del club. No hay campo de enlace: la web del club lo arma con el `id` (`https://www.skaliasports.com/americanos/<id>`: detalle público, sin login; en el celular abre la app). Orden: `startsAt` asc, alta asc. Con el flag `americano_tournaments_enabled` apagado en la plataforma responde `americanos: []`. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos","host":["{{baseUrl}}"],"path":["americanos"],"query":[{"key":"limit","value":"1","description":"Tamaño de página, 1..200 (default 100).","disabled":true},{"key":"offset","value":"1","description":"Desplazamiento (paginación offset/limit).","disabled":true},{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"status","value":"OPEN","description":"Filtra por estado.","disabled":true},{"key":"from","value":"2026-09-18","description":"Americanos cuyo `startsAt` es ≥ `from` (`YYYY-MM-DD` naive del club).","disabled":true},{"key":"to","value":"2026-10-18","description":"Americanos cuyo `startsAt` es ≤ `to` (`YYYY-MM-DD` naive del club).","disabled":true}]},"description":"Americanos CLUB_PUBLIC del club (los que la app lista y a los que cualquier jugador puede sumarse), con cupos y estado, para publicarlos en la web del club. No hay campo de enlace: la web del club lo arma con el `id` (`https://www.skaliasports.com/americanos/<id>`: detalle público, sin login; en el celular abre la app). Orden: `startsAt` asc, alta asc. Con el flag `americano_tournaments_enabled` apagado en la plataforma responde `americanos: []`. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]},{"name":"Detalle de un americano (getAmericano)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos/:id","host":["{{baseUrl}}"],"path":["americanos",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del americano."}]},"description":"El mismo `AmericanoDto` del listado (cupos, estado, canchas), para refrescar el cartel. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"response":[{"name":"200 · El americano.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos/:id","host":["{{baseUrl}}"],"path":["americanos",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del americano."}]},"description":"El mismo `AmericanoDto` del listado (cupos, estado, canchas), para refrescar el cartel. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"americano\": {\n    \"id\": \"6d5e4f3a-2b1c-4d0e-9f8a-7b6c5d4e3f2a\",\n    \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n    \"name\": \"Americano de los viernes\",\n    \"status\": \"OPEN\",\n    \"startsAt\": \"2026-09-25T20:00:00\",\n    \"maxPlayers\": 8,\n    \"confirmedCount\": 6,\n    \"isFull\": false,\n    \"registrationOpen\": true,\n    \"roundsPlanned\": 3,\n    \"currentRound\": 0,\n    \"gamesPerMatch\": 8,\n    \"matchMinutes\": 20,\n    \"courtIds\": [\n      \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\"\n    ],\n    \"price\": 500,\n    \"description\": \"Trae paleta. Se juega con lluvia.\",\n    \"location\": null,\n    \"finishedAt\": null,\n    \"cancelledAt\": null,\n    \"cancellationReason\": null,\n    \"createdAt\": \"2026-09-14T12:00:00Z\",\n    \"updatedAt\": \"2026-09-14T12:00:00Z\"\n  }\n}"},{"name":"400 · MALFORMED_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos/:id","host":["{{baseUrl}}"],"path":["americanos",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del americano."}]},"description":"El mismo `AmericanoDto` del listado (cupos, estado, canchas), para refrescar el cartel. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos/:id","host":["{{baseUrl}}"],"path":["americanos",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del americano."}]},"description":"El mismo `AmericanoDto` del listado (cupos, estado, canchas), para refrescar el cartel. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos/:id","host":["{{baseUrl}}"],"path":["americanos",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del americano."}]},"description":"El mismo `AmericanoDto` del listado (cupos, estado, canchas), para refrescar el cartel. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"404 · AMERICANO_NOT_FOUND","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos/:id","host":["{{baseUrl}}"],"path":["americanos",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del americano."}]},"description":"El mismo `AmericanoDto` del listado (cupos, estado, canchas), para refrescar el cartel. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"El americano no existe o no es de este club.\",\n  \"code\": \"AMERICANO_NOT_FOUND\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos/:id","host":["{{baseUrl}}"],"path":["americanos",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del americano."}]},"description":"El mismo `AmericanoDto` del listado (cupos, estado, canchas), para refrescar el cartel. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos/:id","host":["{{baseUrl}}"],"path":["americanos",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del americano."}]},"description":"El mismo `AmericanoDto` del listado (cupos, estado, canchas), para refrescar el cartel. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/americanos/:id","host":["{{baseUrl}}"],"path":["americanos",":id"],"variable":[{"key":"id","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Id del americano."}]},"description":"El mismo `AmericanoDto` del listado (cupos, estado, canchas), para refrescar el cartel. Nunca datos de personas: ni quién lo creó ni quiénes juegan (`players` no existe en esta API); tampoco rondas, mesas ni tabla.\n\nScope: `americanos:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]}]},{"name":"Streaming","description":"Qué cancha está en vivo ahora (TV del hall, web del torneo).","item":[{"name":"Qué cancha está en vivo (listStreams)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/streams","host":["{{baseUrl}}"],"path":["streams"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esa cancha (`GET /courts`). Una cancha de otro club no filtra nada: la lista sale vacía.","disabled":true}]},"description":"Los vivos del club por cancha: broadcasts armados (`SCHEDULED`) o al aire (`LIVE`), una fila por cancha, sin PII. `url` / `embedUrl` sólo para lo `STANDALONE`, lo `TOURNAMENT` (público por diseño) y lo `BOOKING` de una reserva creada por TU integración; el turno de una reserva ajena sólo dice \"esta cancha está en vivo\" (`url`, `embedUrl` y `bookingId` en `null`), porque el título del video lleva el nombre del titular. Con el streaming del club apagado la lista es `[]`. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue). No consume cuota de escritura ni emite eventos; el VOD de un turno terminado es `recording` de la reserva (`recordings:read`) y su momento real de \"ya se puede mirar\" es el evento `booking.recording_ready`.\n\nScope: `recordings:read`."},"response":[{"name":"200 · Vivos por cancha.","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/streams","host":["{{baseUrl}}"],"path":["streams"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esa cancha (`GET /courts`). Una cancha de otro club no filtra nada: la lista sale vacía.","disabled":true}]},"description":"Los vivos del club por cancha: broadcasts armados (`SCHEDULED`) o al aire (`LIVE`), una fila por cancha, sin PII. `url` / `embedUrl` sólo para lo `STANDALONE`, lo `TOURNAMENT` (público por diseño) y lo `BOOKING` de una reserva creada por TU integración; el turno de una reserva ajena sólo dice \"esta cancha está en vivo\" (`url`, `embedUrl` y `bookingId` en `null`), porque el título del video lleva el nombre del titular. Con el streaming del club apagado la lista es `[]`. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue). No consume cuota de escritura ni emite eventos; el VOD de un turno terminado es `recording` de la reserva (`recordings:read`) y su momento real de \"ya se puede mirar\" es el evento `booking.recording_ready`.\n\nScope: `recordings:read`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"clubId\": \"0d6a1f3e-2b4c-4d5e-9f7a-8b9c0d1e2f3a\",\n  \"streams\": [\n    {\n      \"courtId\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\",\n      \"courtName\": \"Cancha 1\",\n      \"kind\": \"STANDALONE\",\n      \"status\": \"LIVE\",\n      \"url\": \"https://www.youtube.com/watch?v=dQw4w9WgXcQ\",\n      \"embedUrl\": \"https://www.youtube.com/embed/dQw4w9WgXcQ\",\n      \"bookingId\": null,\n      \"tournamentId\": null,\n      \"startedAt\": \"2026-09-15T13:02:11.000Z\"\n    },\n    {\n      \"courtId\": \"6f7a8b9c-0d1e-4f2a-b3c4-d5e6f7a8b9c0\",\n      \"courtName\": \"Cancha 2\",\n      \"kind\": \"BOOKING\",\n      \"status\": \"LIVE\",\n      \"url\": null,\n      \"embedUrl\": null,\n      \"bookingId\": null,\n      \"tournamentId\": null,\n      \"startedAt\": \"2026-09-15T13:00:40.000Z\"\n    },\n    {\n      \"courtId\": \"7a8b9c0d-1e2f-4a3b-c4d5-e6f7a8b9c0d1\",\n      \"courtName\": \"Cancha 3\",\n      \"kind\": \"TOURNAMENT\",\n      \"status\": \"SCHEDULED\",\n      \"url\": \"https://www.youtube.com/watch?v=Xy12AbCdEfG\",\n      \"embedUrl\": \"https://www.youtube.com/embed/Xy12AbCdEfG\",\n      \"bookingId\": \"2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e\",\n      \"tournamentId\": \"8c9d0e1f-2a3b-4c4d-9e5f-6a7b8c9d0e1f\",\n      \"startedAt\": null\n    }\n  ]\n}"},{"name":"304 · Nada cambió (ETag)","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/streams","host":["{{baseUrl}}"],"path":["streams"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esa cancha (`GET /courts`). Una cancha de otro club no filtra nada: la lista sale vacía.","disabled":true}]},"description":"Los vivos del club por cancha: broadcasts armados (`SCHEDULED`) o al aire (`LIVE`), una fila por cancha, sin PII. `url` / `embedUrl` sólo para lo `STANDALONE`, lo `TOURNAMENT` (público por diseño) y lo `BOOKING` de una reserva creada por TU integración; el turno de una reserva ajena sólo dice \"esta cancha está en vivo\" (`url`, `embedUrl` y `bookingId` en `null`), porque el título del video lleva el nombre del titular. Con el streaming del club apagado la lista es `[]`. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue). No consume cuota de escritura ni emite eventos; el VOD de un turno terminado es `recording` de la reserva (`recordings:read`) y su momento real de \"ya se puede mirar\" es el evento `booking.recording_ready`.\n\nScope: `recordings:read`."},"status":"Not Modified","code":304,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":""},{"name":"400 · MALFORMED_API_KEY / VALIDATION / CLUB_REQUIRED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/streams","host":["{{baseUrl}}"],"path":["streams"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esa cancha (`GET /courts`). Una cancha de otro club no filtra nada: la lista sale vacía.","disabled":true}]},"description":"Los vivos del club por cancha: broadcasts armados (`SCHEDULED`) o al aire (`LIVE`), una fila por cancha, sin PII. `url` / `embedUrl` sólo para lo `STANDALONE`, lo `TOURNAMENT` (público por diseño) y lo `BOOKING` de una reserva creada por TU integración; el turno de una reserva ajena sólo dice \"esta cancha está en vivo\" (`url`, `embedUrl` y `bookingId` en `null`), porque el título del video lleva el nombre del titular. Con el streaming del club apagado la lista es `[]`. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue). No consume cuota de escritura ni emite eventos; el VOD de un turno terminado es `recording` de la reserva (`recordings:read`) y su momento real de \"ya se puede mirar\" es el evento `booking.recording_ready`.\n\nScope: `recordings:read`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La API key no tiene el formato esperado (sk_live_… / sk_test_…).\",\n  \"code\": \"MALFORMED_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"401 · MISSING_API_KEY / API_KEY_WRONG_ENV / INVALID_API_KEY","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/streams","host":["{{baseUrl}}"],"path":["streams"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esa cancha (`GET /courts`). Una cancha de otro club no filtra nada: la lista sale vacía.","disabled":true}]},"description":"Los vivos del club por cancha: broadcasts armados (`SCHEDULED`) o al aire (`LIVE`), una fila por cancha, sin PII. `url` / `embedUrl` sólo para lo `STANDALONE`, lo `TOURNAMENT` (público por diseño) y lo `BOOKING` de una reserva creada por TU integración; el turno de una reserva ajena sólo dice \"esta cancha está en vivo\" (`url`, `embedUrl` y `bookingId` en `null`), porque el título del video lleva el nombre del titular. Con el streaming del club apagado la lista es `[]`. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue). No consume cuota de escritura ni emite eventos; el VOD de un turno terminado es `recording` de la reserva (`recordings:read`) y su momento real de \"ya se puede mirar\" es el evento `booking.recording_ready`.\n\nScope: `recordings:read`."},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Falta la API key: mandala en Authorization: Bearer sk_….\",\n  \"code\": \"MISSING_API_KEY\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"403 · CLIENT_DISABLED / MODULE_DISABLED / CLUB_NOT_GRANTED / SCOPE_DENIED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/streams","host":["{{baseUrl}}"],"path":["streams"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esa cancha (`GET /courts`). Una cancha de otro club no filtra nada: la lista sale vacía.","disabled":true}]},"description":"Los vivos del club por cancha: broadcasts armados (`SCHEDULED`) o al aire (`LIVE`), una fila por cancha, sin PII. `url` / `embedUrl` sólo para lo `STANDALONE`, lo `TOURNAMENT` (público por diseño) y lo `BOOKING` de una reserva creada por TU integración; el turno de una reserva ajena sólo dice \"esta cancha está en vivo\" (`url`, `embedUrl` y `bookingId` en `null`), porque el título del video lleva el nombre del titular. Con el streaming del club apagado la lista es `[]`. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue). No consume cuota de escritura ni emite eventos; el VOD de un turno terminado es `recording` de la reserva (`recordings:read`) y su momento real de \"ya se puede mirar\" es el evento `booking.recording_ready`.\n\nScope: `recordings:read`."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La integración está deshabilitada.\",\n  \"code\": \"CLIENT_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"429 · RATE_LIMITED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/streams","host":["{{baseUrl}}"],"path":["streams"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esa cancha (`GET /courts`). Una cancha de otro club no filtra nada: la lista sale vacía.","disabled":true}]},"description":"Los vivos del club por cancha: broadcasts armados (`SCHEDULED`) o al aire (`LIVE`), una fila por cancha, sin PII. `url` / `embedUrl` sólo para lo `STANDALONE`, lo `TOURNAMENT` (público por diseño) y lo `BOOKING` de una reserva creada por TU integración; el turno de una reserva ajena sólo dice \"esta cancha está en vivo\" (`url`, `embedUrl` y `bookingId` en `null`), porque el título del video lleva el nombre del titular. Con el streaming del club apagado la lista es `[]`. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue). No consume cuota de escritura ni emite eventos; el VOD de un turno terminado es `recording` de la reserva (`recordings:read`) y su momento real de \"ya se puede mirar\" es el evento `booking.recording_ready`.\n\nScope: `recordings:read`."},"status":"Too Many Requests","code":429,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Superaste la cuota de requests. Esperá y reintentá.\",\n  \"code\": \"RATE_LIMITED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"500 · INTERNAL_ERROR","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/streams","host":["{{baseUrl}}"],"path":["streams"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esa cancha (`GET /courts`). Una cancha de otro club no filtra nada: la lista sale vacía.","disabled":true}]},"description":"Los vivos del club por cancha: broadcasts armados (`SCHEDULED`) o al aire (`LIVE`), una fila por cancha, sin PII. `url` / `embedUrl` sólo para lo `STANDALONE`, lo `TOURNAMENT` (público por diseño) y lo `BOOKING` de una reserva creada por TU integración; el turno de una reserva ajena sólo dice \"esta cancha está en vivo\" (`url`, `embedUrl` y `bookingId` en `null`), porque el título del video lleva el nombre del titular. Con el streaming del club apagado la lista es `[]`. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue). No consume cuota de escritura ni emite eventos; el VOD de un turno terminado es `recording` de la reserva (`recordings:read`) y su momento real de \"ya se puede mirar\" es el evento `booking.recording_ready`.\n\nScope: `recordings:read`."},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"Ocurrió un error inesperado. Reintentá; si persiste, reportá el requestId.\",\n  \"code\": \"INTERNAL_ERROR\",\n  \"requestId\": \"mi-sistema-0001\"\n}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."},{"key":"If-None-Match","value":"texto","description":"El `ETag` de la respuesta anterior: si nada cambió recibís 304 sin cuerpo.","disabled":true}],"url":{"raw":"{{baseUrl}}/streams","host":["{{baseUrl}}"],"path":["streams"],"query":[{"key":"clubId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Club sobre el que opera la request. Opcional: se infiere cuando la integración tiene un solo grant (kind CLUB, v1).","disabled":true},{"key":"courtId","value":"9c1b2a3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d","description":"Sólo esa cancha (`GET /courts`). Una cancha de otro club no filtra nada: la lista sale vacía.","disabled":true}]},"description":"Los vivos del club por cancha: broadcasts armados (`SCHEDULED`) o al aire (`LIVE`), una fila por cancha, sin PII. `url` / `embedUrl` sólo para lo `STANDALONE`, lo `TOURNAMENT` (público por diseño) y lo `BOOKING` de una reserva creada por TU integración; el turno de una reserva ajena sólo dice \"esta cancha está en vivo\" (`url`, `embedUrl` y `bookingId` en `null`), porque el título del video lleva el nombre del titular. Con el streaming del club apagado la lista es `[]`. Con ETag fuerte: mandá `If-None-Match` y recibís 304 sin cuerpo si nada cambió (el `Cache-Control: no-store` sigue). No consume cuota de escritura ni emite eventos; el VOD de un turno terminado es `recording` de la reserva (`recordings:read`) y su momento real de \"ya se puede mirar\" es el evento `booking.recording_ready`.\n\nScope: `recordings:read`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]}]},{"name":"Meta","description":"Esta spec.","item":[{"name":"Esta spec (getOpenApi)","request":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/openapi.json","host":["{{baseUrl}}"],"path":["openapi.json"]},"description":"Documento OpenAPI 3.1.0 de la Partner API v1, generado del código en cada deploy. Es una de las DOS rutas del namespace sin API key y con CORS abierto (`Access-Control-Allow-Origin: *`); la otra es `GET /postman.json`, la colección Postman generada de esta misma spec. Cualquier otro método sobre esas rutas sigue el pipeline normal (401 sin key, 404 con key). Importalo en Postman / Insomnia / Swagger UI o generá un cliente. Las horas de FIN (`endTime`, `close`, `end`) admiten `24:00` como medianoche; las de comienzo, no.\n\nScope: ninguno (ruta pública, sin key).","auth":{"type":"noauth"}},"response":[{"name":"200 · El documento. `Cache-Control: public, max-age=3600` y `Access-Control-Allow-Origin: *` (se puede cargar desde Swagger UI / Redoc / Postman web en cualquier origen).","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/openapi.json","host":["{{baseUrl}}"],"path":["openapi.json"]},"description":"Documento OpenAPI 3.1.0 de la Partner API v1, generado del código en cada deploy. Es una de las DOS rutas del namespace sin API key y con CORS abierto (`Access-Control-Allow-Origin: *`); la otra es `GET /postman.json`, la colección Postman generada de esta misma spec. Cualquier otro método sobre esas rutas sigue el pipeline normal (401 sin key, 404 con key). Importalo en Postman / Insomnia / Swagger UI o generá un cliente. Las horas de FIN (`endTime`, `close`, `end`) admiten `24:00` como medianoche; las de comienzo, no.\n\nScope: ninguno (ruta pública, sin key).","auth":{"type":"noauth"}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{}"},{"name":"503 · PARTNER_API_DISABLED","originalRequest":{"method":"GET","header":[{"key":"X-Request-Id","value":"mi-sistema-0001","description":"Tu propio id de request: vuelve en la respuesta y en el requestId de todo error."}],"url":{"raw":"{{baseUrl}}/openapi.json","host":["{{baseUrl}}"],"path":["openapi.json"]},"description":"Documento OpenAPI 3.1.0 de la Partner API v1, generado del código en cada deploy. Es una de las DOS rutas del namespace sin API key y con CORS abierto (`Access-Control-Allow-Origin: *`); la otra es `GET /postman.json`, la colección Postman generada de esta misma spec. Cualquier otro método sobre esas rutas sigue el pipeline normal (401 sin key, 404 con key). Importalo en Postman / Insomnia / Swagger UI o generá un cliente. Las horas de FIN (`endTime`, `close`, `end`) admiten `24:00` como medianoche; las de comienzo, no.\n\nScope: ninguno (ruta pública, sin key).","auth":{"type":"noauth"}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Request-Id","value":"mi-sistema-0001"}],"body":"{\n  \"error\": \"La Partner API está deshabilitada temporalmente.\",\n  \"code\": \"PARTNER_API_DISABLED\",\n  \"requestId\": \"mi-sistema-0001\"\n}"}]}]}]}