{"contractVersion":"ncp-1.0.0","probes":[{"id":"discovery.openapi-json","name":"GET /openapi.json returns a valid OpenAPI 3.1 document","description":"The server must publish a machine-readable OpenAPI 3.1 spec at /openapi.json with info.title, info.version, and paths.","category":"discovery","required":true,"method":"GET","path":"/openapi.json","requiresAuth":false},{"id":"discovery.openapi-yaml","name":"GET /openapi.yaml serves the same spec as YAML","description":"The server must also publish the spec as YAML so tooling without a JSON OpenAPI loader can consume it.","category":"discovery","required":false,"method":"GET","path":"/openapi.yaml","requiresAuth":false},{"id":"discovery.state","name":"GET /state returns a marketplace snapshot","description":"Public marketplace state is the anchor for external agents to detect health before issuing expensive calls.","category":"discovery","required":true,"method":"GET","path":"/state","requiresAuth":false},{"id":"discovery.conformance-catalogue","name":"GET /conformance returns the probe catalogue","description":"The server must publish its own conformance catalogue so external agents can self-test against the contract version they speak.","category":"discovery","required":true,"method":"GET","path":"/conformance","requiresAuth":false},{"id":"auth.missing-headers-rejects","name":"POST /rank without any auth headers rejects with 400/401","description":"Agent endpoints must reject callers that supply no auth. The status code is 401 with error envelope.","category":"auth","required":true,"method":"POST","path":"/rank","requiresAuth":false},{"id":"auth.partial-headers-rejects","name":"POST /rank with only NCP-Agent-ID rejects 400/401","description":"A request with an agent id but no signature or api key must fail loudly rather than silently fall through.","category":"auth","required":true,"method":"POST","path":"/rank","requiresAuth":false},{"id":"auth.stale-timestamp-rejects","name":"POST /rank with a far-past timestamp rejects","description":"Stale timestamps must be rejected to prevent replay attacks. 5-minute skew window per NCP v1.","category":"auth","required":true,"method":"POST","path":"/rank","requiresAuth":false},{"id":"error-envelope.not-found","name":"Unknown paths respond with the NCP error envelope","description":"Every non-2xx response must carry { success: false, error: { code, message } } so agents can parse failures uniformly.","category":"error-envelope","required":true,"method":"GET","path":"/__definitely_not_a_real_path__","requiresAuth":false},{"id":"stays.search-listings-array","name":"GET /stays returns a listings array","description":"Authenticated GET /stays must respond with { success: true, data: { listings: [...] } } when the stays domain is enabled. 404 is tolerated for deployments where the stays router is not mounted.","category":"contract","required":false,"method":"GET","path":"/stays?limit=5","requiresAuth":true},{"id":"contract.rank-contract-version","name":"Authenticated /rank call echoes contractVersion","description":"Every shaped response from /rank must include `contractVersion`. Requires valid agent credentials; skipped otherwise.","category":"contract","required":false,"method":"POST","path":"/rank","requiresAuth":true}],"totalProbes":10,"requiredProbes":7}