Saltar al contenido

Transition the engagement state

Módulo Opportunities

POST/engagements/{id}/transitionsengagements.transition

Moves the engagement state machine through its transition RPC, which writes its ledger. Active is refused until every blocking onboarding item passes. Complete narrows external access to money and documents. Requires `Idempotency-Key`; a replay returns the original response. A rule that refuses the request returns 422 with `refusal` and `reason`.

  • Requiere la capacidad opportunities.engagement.write.
  • Alcances de OAuth: opportunities.
  • Envía el encabezado Idempotency-Key. Una repetición con la misma clave devuelve la respuesta original.
  • Estados de error: 400, 401, 404, 409, 422, 429. Los errores son detalles de problema RFC 9457.

Parámetros de ruta y de consulta

engagements.transition: Parámetros de ruta y de consulta
CampoTipoObligatorioDescripción
idstring (uuid)SíIdentifier of the engagement.

Cuerpo de la solicitud: EngagementTransitionRequest

engagements.transition: EngagementTransitionRequest
CampoTipoObligatorioDescripción
expected_state"Onboarding" | "Blocked" | "Active" | "Closing" | "Complete" | "Canceled"SíThe state the caller believes the row is in (compare-and-set).
to_state"Onboarding" | "Blocked" | "Active" | "Closing" | "Complete" | "Canceled"SíTarget state.
reasonstringNoReason, required by some transitions.Restricciones: length 1 to any
{
  "expected_state": "Onboarding",
  "to_state": "Active",
  "reason": "Client approved the revised scope."
}

Respuesta 200: Engagement

engagements.transition: Engagement
CampoTipoObligatorioDescripción
idstring (uuid)SíIdentifier of the engagement.
org_idstring (uuid)SíIdentifier of the owning organization, derived from the parent row and never accepted from the caller.
created_atstring (date-time)SíWhen the row was created.
created_bystring (uuid) | nullSíIdentifier of the person who created the row; null when a seed, platform or system process created it.
updated_atstring (date-time)SíWhen the row was last updated.
updated_bystring (uuid) | nullSíIdentifier of the person who last updated the row; null when a seed, platform or system process updated it.
person_idstring (uuid) | nullSíIdentifier of the engaged person.
organization_idstring (uuid) | nullSíIdentifier of the engaged external account.
project_idstring (uuid) | nullSíIdentifier of the project.
offer_idstring (uuid) | nullSíIdentifier of the accepted offer.
role_typeExternalRoleTypeSíExternal role type (Section 4.4.2).Restricciones: one of "Client", "Vendor", "Contractor", "Crew", "Staff", "Artist", "Artist Representative", "Sponsor"
engagement_stateEngagementStateSíEngagement lifecycle state. Active requires every blocking onboarding item to pass.Restricciones: one of "Onboarding", "Blocked", "Active", "Closing", "Complete", "Canceled"
activated_atstring (date-time) | nullSíWhen it became Active.
completed_atstring (date-time) | nullSíWhen it became Complete.
application_idstring (uuid) | nullSíIdentifier of the accepted application the engagement came from.
worker_classificationstring | nullSíWorker classification, from xpms.worker_classification; null for Client and Sponsor engagements.Restricciones: pattern ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$
pay_basisstring | nullSíPay basis; with the arrangement a permitted canon pair.Restricciones: length 1 to 300
arrangementstring | nullSíArrangement; with the pay basis a permitted canon pair.Restricciones: length 1 to 300
start_datestring (date)SíFirst day of the engagement; defaults to the offer's or the opportunity's.
end_datestring (date) | nullSíLast day of the engagement; defaults to the offer's or the opportunity's.
counterparty_idstring (uuid) | nullSíIdentifier of the counterparty (vendor) the holder is engaged through; null when direct.
{
  "id": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
  "org_id": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
  "created_at": "2026-10-08T14:30:00Z",
  "created_by": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
  "updated_at": "2026-10-08T14:30:00Z",
  "updated_by": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
  "person_id": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
  "organization_id": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
  "project_id": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
  "offer_id": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
  "role_type": "Crew",
  "engagement_state": "Onboarding",
  "activated_at": "2026-10-08T14:30:00Z",
  "completed_at": "2026-10-08T14:30:00Z",
  "application_id": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
  "worker_classification": "INDEPENDENT_CONTRACTOR",
  "pay_basis": "Day Rate",
  "arrangement": "Per Engagement",
  "start_date": "2026-10-08",
  "end_date": "2026-10-08",
  "counterparty_id": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f"
}

Ejemplos de código

curl -X POST "$XOS_BASE_URL/engagements/0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f/transitions" \
  -H "Authorization: Bearer $XOS_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"expected_state":"Onboarding","to_state":"Active","reason":"Client approved the revised scope."}'
const { data } = await xos.engagements.transition("0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f", {
    "expected_state": "Onboarding",
    "to_state": "Active",
    "reason": "Client approved the revised scope."
  });
response = xos.engagements.transition("0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f", {"expected_state": "Onboarding", "to_state": "Active", "reason": "Client approved the revised scope."})
xos engagements transition 0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f --data '{"expected_state":"Onboarding","to_state":"Active","reason":"Client approved the revised scope."}'