Incoming webhook contract
Exact HTTP, signature, timestamp, idempotency, payload, response, and delivery semantics for an Infra One Automation endpoint.
Endpoint
POST https://venture.infra.one/api/webhooks/automations/ENDPOINT_UUID
The endpoint UUID selects the organization and Automation. Authentication still requires the endpoint’s one-time signing secret.
Headers
| Header | Required | Contract |
|---|---|---|
Content-Type | Yes | application/json or an application/*+json media type. |
X-Infra-One-Timestamp | Yes | Unix seconds within five minutes of receipt. |
X-Infra-One-Signature | Yes | sha256= followed by the hexadecimal HMAC-SHA256 digest. |
Idempotency-Key | Yes | Stable printable value, one through 200 bytes. |
Signature
Let raw_body be the exact bytes sent after the HTTP headers. Sign:
message = ascii(timestamp) + "." + raw_body
digest = HMAC-SHA256(signing_secret, message)
header = "sha256=" + hex(digest)
Do not sign a parsed JSON object. Serialization, whitespace, key order, and Unicode encoding affect the digest.
Body
- UTF-8 JSON
- exactly one object at the top level
- maximum 256 KiB
Arrays, scalar JSON, invalid JSON, and oversized bodies are rejected before execution.
Idempotency
The key is scoped to one endpoint.
- First valid key and body: create and enqueue one durable delivery.
- Same key and same body: return the original delivery.
- Same key and different body: return
409 idempotency_conflict.
Retain the key across network and runner retries. Use a new key only for a new logical event.
Responses
| HTTP | Body | Meaning |
|---|---|---|
202 | {"status":"accepted","delivery_id":"…"} | Request is persisted. Execution continues asynchronously. |
400 | {"error":"invalid_content_type"}, invalid_json_object, invalid_timestamp, stale_timestamp, or invalid_idempotency_key | Correct the request. |
401 | empty | Endpoint, enabled state, or signature authentication failed. |
409 | {"error":"idempotency_conflict"} | The key was reused with different bytes. |
413 | {"error":"payload_too_large"} | Reduce the body below 256 KiB. |
500 | {"error":"acceptance_failed"} | Infra One could not persist acceptance. Retry the same body and key. |
202 is durable acceptance, not action completion. Use Run history to determine the final state.
Delivery lifecycle
accepted → processing → generated → posting → succeeded
Terminal failure classes are failed_before_post and failed_after_claim. Only the former is automatically safe to retry without first inspecting the external destination.