{"openapi":"3.1.0","info":{"title":"Braith integration API","version":"1","description":"Existing coding-agent setup and event-ingestion endpoints. Prefer the official braith CLI and @braith/sdk. Authentication scopes remain enforced. No incident-reading, account-management or MCP API is offered. Cross-field validation and plan limits apply beyond this specification."},"servers":[{"url":"https://app.braith.dev"}],"externalDocs":{"description":"Coding-agent workflow, review and verification","url":"https://app.braith.dev/docs/agents"},"paths":{"/api/v1/setup":{"post":{"operationId":"connectCodingTool","summary":"Request or poll a coding-tool connection","description":"Start returns a 15-minute authorization URL, user code and private device token. The owner signs in and approves the matching code. Poll no faster than every five seconds with the device token; a pending response is 202. Successful redemption is one-use and returns scoped credentials. Never log device tokens or keys.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"start"}},"required":["action"]},{"type":"object","properties":{"action":{"const":"poll"},"deviceToken":{"type":"string","pattern":"^br_device_[A-Za-z0-9_-]{32}$"}},"required":["action","deviceToken"]}]}}}},"responses":{"200":{"description":"Connection started, or approved scoped credentials returned. Sensitive response.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"deviceToken":{"type":"string"},"userCode":{"type":"string"},"verificationUrl":{"type":"string"},"expiresIn":{"type":"integer","maximum":900},"interval":{"type":"integer","minimum":5}},"required":["deviceToken","userCode","verificationUrl","expiresIn","interval"]},{"type":"object","properties":{"projectId":{"type":"string"},"browserKey":{"type":"string"},"serverKey":{"type":"string"},"managementKey":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"}},"required":["projectId","browserKey","serverKey","managementKey","expiresAt"]}]}}}},"202":{"description":"Waiting for owner approval.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"const":"pending"}},"required":["status"]}}}},"400":{"description":"Invalid request. Correct the request before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, expired, revoked or incorrect credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request exceeds the documented limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or processing limit reached. Use bounded retries and check account capacity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait when supplied.","schema":{"type":"integer"}}}},"500":{"description":"Service error. Use bounded retries; do not repeat writes blindly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/enrollment/redeem":{"post":{"operationId":"redeemSetupEnrollment","summary":"Redeem a private one-use setup token","description":"Legacy one-use enrollment. New setup uses braith connect and /api/v1/setup. The response contains secrets: store locally in ignored files; never print, log or commit it. Temporary management credentials expire after 30 minutes.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","pattern":"^br_enroll_[A-Za-z0-9_-]{32}$"}},"required":["token"]}}}},"responses":{"200":{"description":"Enrollment credentials. Sensitive response.","content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string"},"browserKey":{"type":"string"},"serverKey":{"type":"string"},"managementKey":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"}},"required":["projectId","browserKey","serverKey","managementKey","expiresAt"]}}}},"400":{"description":"Invalid request. Correct the request before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, expired, revoked or incorrect credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request exceeds the documented limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or processing limit reached. Use bounded retries and check account capacity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait when supplied.","schema":{"type":"integer"}}}},"500":{"description":"Service error. Use bounded retries; do not repeat writes blindly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/manifest":{"post":{"operationId":"publishReviewedManifest","summary":"Publish a validated customer-task manifest","description":"Use the CLI validate/review/push workflow. Publishes configuration but does not silently activate a release. Raw body limit 256 KiB; the validated manifest has a 64 KiB delivery limit. Unique names, allowlists, signal references, timing and other cross-field checks apply.","security":[{"managementKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectManifest"}}}},"responses":{"200":{"description":"Identical manifest version already exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManifestReceipt"}}}},"201":{"description":"Manifest version created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManifestReceipt"}}}},"400":{"description":"Invalid request. Correct the request before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, expired, revoked or incorrect credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Version already has different content. Review and use a new manifest version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request exceeds the documented limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or processing limit reached. Use bounded retries and check account capacity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait when supplied.","schema":{"type":"integer"}}}},"500":{"description":"Service error. Use bounded retries; do not repeat writes blindly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/releases":{"post":{"operationId":"bindReviewedRelease","summary":"Bind a release to a published manifest","description":"After review, bind the build ID used in the SDK to the manifest. Existing named release bindings cannot be reassigned to another manifest. The explicit release value default changes fallback activation and should be used only when build IDs are unavailable. Body limit 4 KiB.","security":[{"managementKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"release":{"type":"string","pattern":"^[a-zA-Z0-9][a-zA-Z0-9._-]{0,119}$"},"manifestVersion":{"type":"string","pattern":"^[a-zA-Z0-9][a-zA-Z0-9._-]{0,119}$"},"environment":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,40}$","default":"production"}},"required":["release","manifestVersion"]}}}},"responses":{"200":{"description":"Release binding confirmed.","content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string"},"release":{"type":"string"},"environment":{"type":"string"},"manifestVersion":{"type":"string"}},"required":["projectId","release","environment","manifestVersion"]}}}},"400":{"description":"Invalid request. Correct the request before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, expired, revoked or incorrect credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Manifest has not been published.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Release is already bound to a different manifest.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request exceeds the documented limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or processing limit reached. Use bounded retries and check account capacity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait when supplied.","schema":{"type":"integer"}}}},"500":{"description":"Service error. Use bounded retries; do not repeat writes blindly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/events":{"post":{"operationId":"ingestOutcomeEvents","summary":"Submit scoped outcome evidence","description":"Prefer @braith/sdk. Accepts 1–100 events, body limit 1 MiB. Each event allows at most 24 properties, 1 KiB of properties and 4 KiB total. At least one subject identifier is required. Names/properties must match the published manifest and release binding. Browser credentials cannot establish authoritative server facts. Never submit credentials or arbitrary private payloads. Inspect each result: a 200 response can contain rejections. An allowance exhaustion requires a capacity decision, not an unbounded retry loop.","security":[{"ingestKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"events":{"type":"array","minItems":1,"maxItems":100,"items":{"$ref":"#/components/schemas/EventInput"}}},"required":["events"]}}}},"responses":{"200":{"description":"Per-event ingest results.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestReceipt"}}}},"400":{"description":"Invalid request. Correct the request before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Credential rejected, either before parsing or for all events.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/IngestReceipt"}]}}}},"413":{"description":"Request exceeds the documented limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Content-Type must be application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request or event processing is throttled. Inspect any per-event receipt and respect Retry-After.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/IngestReceipt"}]}}},"headers":{"Retry-After":{"description":"Seconds to wait when supplied.","schema":{"type":"integer"}}}},"500":{"description":"Service error. Use bounded retries; do not repeat writes blindly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Ingestion temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestReceipt"}}}}}}},"/api/v1/test":{"post":{"operationId":"startConfiguredIntegrationCheck","summary":"Start an isolated integration check","description":"For an authorised coding integration, not a public lead-generation endpoint. Creates isolated test evidence, not proof of deployed connectivity. Semantic checks are bounded by server safeguards; never run unbounded retries. Body limit 4 KiB.","security":[{"managementKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"manifestVersion":{"type":"string"},"mode":{"type":"string","enum":["deterministic","semantic"]}},"required":["manifestVersion"]}}}},"responses":{"202":{"description":"Integration check created; inspect the returned test evidence.","content":{"application/json":{"schema":{"type":"object","properties":{"test":{"const":true}},"additionalProperties":true}}}},"400":{"description":"Invalid request. Correct the request before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, expired, revoked or incorrect credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Configured integration check cannot proceed in its current state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request exceeds the documented limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Configured check could not run. Inspect error code and correct the integration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or processing limit reached. Use bounded retries and check account capacity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait when supplied.","schema":{"type":"integer"}}}},"500":{"description":"Service error. Use bounded retries; do not repeat writes blindly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"readIntegrationCheck","summary":"Read an integration check result","description":"Reads only the authorised project’s isolated test run; not a production incident-reading API.","security":[{"managementKey":[]}],"parameters":[{"name":"runId","in":"query","required":true,"schema":{"type":"string","pattern":"^[0-9a-fA-F-]{36}$"}}],"responses":{"200":{"description":"Isolated integration check result.","content":{"application/json":{"schema":{"type":"object","properties":{"test":{"const":true}},"additionalProperties":true}}}},"400":{"description":"Invalid request. Correct the request before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, expired, revoked or incorrect credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Test run not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request exceeds the documented limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or processing limit reached. Use bounded retries and check account capacity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait when supplied.","schema":{"type":"integer"}}}},"500":{"description":"Service error. Use bounded retries; do not repeat writes blindly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"managementKey":{"type":"http","scheme":"bearer","description":"Private project-scoped temporary setup-management key, issued by enrollment. Keep out of browser code. Expires/revokes independently of ingestion keys."},"ingestKey":{"type":"http","scheme":"bearer","description":"Project-scoped browser or server ingest key. The service enforces source trust; server keys must remain private."}},"schemas":{"EventInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"schemaVersion":{"type":"number","const":1},"eventId":{"type":"string","minLength":1,"maxLength":256},"eventName":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"occurredAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"userId":{"type":"string","minLength":1,"maxLength":256},"anonymousId":{"type":"string","minLength":1,"maxLength":256},"sessionId":{"type":"string","minLength":1,"maxLength":256},"attemptId":{"type":"string","minLength":1,"maxLength":256},"properties":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":128},"additionalProperties":{"anyOf":[{"type":"string","maxLength":2048},{"type":"number"},{"type":"boolean"},{"type":"null"}]}},"release":{"type":"string","minLength":1,"maxLength":256}},"required":["schemaVersion","eventId","eventName","occurredAt","properties"]},"ProjectManifest":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"schemaVersion":{"type":"number","const":1},"manifestVersion":{"type":"string","minLength":1,"maxLength":128},"projectKey":{"type":"string","minLength":1,"maxLength":256},"eventDefinitions":{"maxItems":250,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"description":{"type":"string","minLength":10,"maxLength":500},"sourceTrust":{"type":"string","enum":["browser","server"]},"allowedProperties":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"additionalProperties":{"type":"string","enum":["string","number","boolean"]}},"requiredProperties":{"maxItems":24,"type":"array","items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"}}},"required":["name","description","sourceTrust","allowedProperties","requiredProperties"]}},"intents":{"maxItems":15,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"name":{"type":"string","minLength":3,"maxLength":100},"description":{"type":"string","minLength":10,"maxLength":500},"completionBoundary":{"type":"string","minLength":20,"maxLength":1000},"correlation":{"oneOf":[{"type":"object","properties":{"strategy":{"type":"string","const":"attempt_id"}},"required":["strategy"]},{"type":"object","properties":{"strategy":{"type":"string","const":"subject_intent_window"},"windowSeconds":{"type":"integer","exclusiveMinimum":0,"maximum":86400}},"required":["strategy","windowSeconds"]}]},"entrySignals":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"object","properties":{"eventName":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"conditions":{"maxItems":12,"type":"array","items":{"oneOf":[{"type":"object","properties":{"property":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"operator":{"type":"string","const":"equals"},"value":{"anyOf":[{"type":"string","maxLength":2048},{"type":"number"},{"type":"boolean"},{"type":"null"}]}},"required":["property","operator","value"]},{"type":"object","properties":{"property":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"operator":{"type":"string","const":"present"},"expected":{"type":"boolean"}},"required":["property","operator","expected"]}]}}},"required":["eventName","conditions"]}},"progressSignals":{"maxItems":20,"type":"array","items":{"type":"object","properties":{"eventName":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"conditions":{"maxItems":12,"type":"array","items":{"oneOf":[{"type":"object","properties":{"property":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"operator":{"type":"string","const":"equals"},"value":{"anyOf":[{"type":"string","maxLength":2048},{"type":"number"},{"type":"boolean"},{"type":"null"}]}},"required":["property","operator","value"]},{"type":"object","properties":{"property":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"operator":{"type":"string","const":"present"},"expected":{"type":"boolean"}},"required":["property","operator","expected"]}]}}},"required":["eventName","conditions"]}},"successSignals":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"object","properties":{"eventName":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"conditions":{"maxItems":12,"type":"array","items":{"oneOf":[{"type":"object","properties":{"property":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"operator":{"type":"string","const":"equals"},"value":{"anyOf":[{"type":"string","maxLength":2048},{"type":"number"},{"type":"boolean"},{"type":"null"}]}},"required":["property","operator","value"]},{"type":"object","properties":{"property":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"operator":{"type":"string","const":"present"},"expected":{"type":"boolean"}},"required":["property","operator","expected"]}]}}},"required":["eventName","conditions"]}},"recoverySignals":{"maxItems":20,"type":"array","items":{"type":"object","properties":{"eventName":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"conditions":{"maxItems":12,"type":"array","items":{"oneOf":[{"type":"object","properties":{"property":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"operator":{"type":"string","const":"equals"},"value":{"anyOf":[{"type":"string","maxLength":2048},{"type":"number"},{"type":"boolean"},{"type":"null"}]}},"required":["property","operator","value"]},{"type":"object","properties":{"property":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"operator":{"type":"string","const":"present"},"expected":{"type":"boolean"}},"required":["property","operator","expected"]}]}}},"required":["eventName","conditions"]}},"successMode":{"type":"string","enum":["any","all"]},"contradictionSignals":{"maxItems":20,"type":"array","items":{"type":"object","properties":{"eventName":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"conditions":{"maxItems":12,"type":"array","items":{"oneOf":[{"type":"object","properties":{"property":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"operator":{"type":"string","const":"equals"},"value":{"anyOf":[{"type":"string","maxLength":2048},{"type":"number"},{"type":"boolean"},{"type":"null"}]}},"required":["property","operator","value"]},{"type":"object","properties":{"property":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"operator":{"type":"string","const":"present"},"expected":{"type":"boolean"}},"required":["property","operator","expected"]}]}}},"required":["eventName","conditions"]}},"cancellationSignals":{"maxItems":20,"type":"array","items":{"type":"object","properties":{"eventName":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"conditions":{"maxItems":12,"type":"array","items":{"oneOf":[{"type":"object","properties":{"property":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"operator":{"type":"string","const":"equals"},"value":{"anyOf":[{"type":"string","maxLength":2048},{"type":"number"},{"type":"boolean"},{"type":"null"}]}},"required":["property","operator","value"]},{"type":"object","properties":{"property":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"operator":{"type":"string","const":"present"},"expected":{"type":"boolean"}},"required":["property","operator","expected"]}]}}},"required":["eventName","conditions"]}},"failureCodes":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"}},"gracePeriodSeconds":{"type":"integer","minimum":0,"maximum":86400},"inactivityTimeoutSeconds":{"type":"integer","exclusiveMinimum":0,"maximum":604800},"maxObservationWindowSeconds":{"type":"integer","exclusiveMinimum":0,"maximum":2592000}},"required":["id","name","description","completionBoundary","correlation","entrySignals","progressSignals","successSignals","recoverySignals","successMode","contradictionSignals","cancellationSignals","failureCodes","gracePeriodSeconds","inactivityTimeoutSeconds","maxObservationWindowSeconds"]}},"discovery":{"type":"object","properties":{"enabled":{"type":"boolean","const":true},"mode":{"default":"review","type":"string","enum":["shadow","review"]},"application":{"type":"string","minLength":10,"maxLength":600},"surfaces":{"default":{},"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"additionalProperties":{"type":"string","minLength":3,"maxLength":160}},"actions":{"default":{},"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"additionalProperties":{"type":"string","minLength":3,"maxLength":160}},"feedback":{"default":{},"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z][a-z0-9_]*$"},"additionalProperties":{"type":"string","minLength":3,"maxLength":160}}},"required":["enabled","application"],"additionalProperties":false}},"required":["schemaVersion","manifestVersion","projectKey","eventDefinitions","intents"]},"IngestReceipt":{"type":"object","properties":{"acceptedCount":{"type":"integer"},"duplicateCount":{"type":"integer"},"rejectedCount":{"type":"integer"},"results":{"type":"array","items":{"type":"object","properties":{"eventId":{"type":"string"},"status":{"type":"string","enum":["accepted","duplicate","rejected","queued"]},"reason":{"type":"string"}},"required":["eventId","status"]}}},"required":["acceptedCount","duplicateCount","rejectedCount","results"]},"Error":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error or validation message."}},"required":["error"],"additionalProperties":true},"ManifestReceipt":{"type":"object","properties":{"manifestVersionId":{"type":"string"},"projectId":{"type":"string"},"version":{"type":"string"},"created":{"type":"boolean"}},"required":["manifestVersionId","projectId","version","created"]}}}}