Skip to content

Record an equipment lifecycle event for a unit

POST
/resources/{resource_id}/equipment-events
curl --request POST \
--url https://quikstik-core.fly.dev/resources/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/equipment-events \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: example' \
--header 'x-tenant-id: 2489E9AD-2EE2-8E00-8EC9-32D5F69181C0' \
--data '{ "resource_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "event": { "event": "acquired" } }'

Appends one event (acquire / capitalize / record-usage / open- or close-maintenance / post-depreciation / transfer-to-sale / sell / dispose) to the unit’s append-only equipment stream. The server loads the unit’s financial fold, runs the lifecycle gate (illegal transitions return 422), and persists the event with its paired status transition atomically. Distinct from setResourceStatus: status is an operational signal, this is the unit’s financial/physical history.

resource_id
required
string format: uuid
x-tenant-id
required
string format: uuid

Tenant identifier (UUID).

Authn/authz semantics are intentionally TBD for this contract slice; this header exists to keep the contract explicitly multi-tenant from day 0.

Idempotency-Key
required
string
>= 1 characters

Idempotency key for the command envelope. A retry with the same key is a no-op.

Media typeapplication/json
object
resource_id
required
string format: uuid
event
required

A tagged equipment event. The event discriminator selects the variant (acquired, capitalized, usage_recorded, maintenance_opened, maintenance_closed, depreciation_posted, transferred_to_sale, sold, disposed); remaining fields are the variant’s payload. The server-side domain type is authoritative for payload shape and money/currency fields.

object
event
required
string
Allowed values: acquired capitalized usage_recorded maintenance_opened maintenance_closed depreciation_posted transferred_to_sale sold disposed

Event recorded; the assigned stream sequence is returned

Media typeapplication/json
object
resource_id
required
string format: uuid
seq
required

The append-only sequence assigned to this event in the unit’s stream.

integer format: int64

Example generated

{
"resource_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"seq": 1
}

Malformed body

Media typeapplication/json
object
reason
required
string

Example generated

{
"reason": "example"
}

Missing or invalid session bearer token

Media typeapplication/json
object
reason
required

Stable, machine-readable reason code (e.g. “sold_out”, “processor_not_configured”, “rail_refused”).

string

Example

{
"reason": "sold_out"
}

The session’s effect authority does not cover this operation

Media typeapplication/json
object
reason
required

Stable, machine-readable reason code (e.g. “sold_out”, “processor_not_configured”, “rail_refused”).

string

Example

{
"reason": "sold_out"
}

Expired, consumed, unknown, or unresolvable — indistinguishable by design

Media typeapplication/json
object
reason
required
string

Example generated

{
"reason": "example"
}

The command is rejected by a domain lifecycle gate (illegal state transition)

Media typeapplication/json
object
code
required

Stable machine-readable error code

string
message
required

Human-readable explanation (never leaks SQL, URLs, or secrets)

string

Example generated

{
"code": "example",
"message": "example"
}

No durable backend is wired for this operation (fail-closed)

Media typeapplication/json
object
reason
required

Stable, machine-readable reason code (e.g. “sold_out”, “processor_not_configured”, “rail_refused”).

string

Example

{
"reason": "sold_out"
}