Skip to main content
POST
/
public
/
v1
/
teardowns
/
transition
/
{teardown_id}
# active_starting -> active_in_process
curl -X POST "$base_url/public/v1/teardowns/transition/$teardown_id" \
  -H "Authorization: Bearer $api_key" \
  -H "X-Organization-Id: $org_id" \
  -H "Content-Type: application/json" \
  -d '{"action": "start_processing"}'
# active_in_process -> active_completed
curl -X POST "$base_url/public/v1/teardowns/transition/$teardown_id" \
  -H "Authorization: Bearer $api_key" \
  -H "X-Organization-Id: $org_id" \
  -H "Content-Type: application/json" \
  -d '{"action": "complete"}'
# any active_* -> draft
curl -X POST "$base_url/public/v1/teardowns/transition/$teardown_id" \
  -H "Authorization: Bearer $api_key" \
  -H "X-Organization-Id: $org_id" \
  -H "Content-Type: application/json" \
  -d '{"action": "unpublish"}'
# any -> archived (soft delete)
curl -X POST "$base_url/public/v1/teardowns/transition/$teardown_id" \
  -H "Authorization: Bearer $api_key" \
  -H "X-Organization-Id: $org_id" \
  -H "Content-Type: application/json" \
  -d '{"action": "archive"}'
# archived -> draft
curl -X POST "$base_url/public/v1/teardowns/transition/$teardown_id" \
  -H "Authorization: Bearer $api_key" \
  -H "X-Organization-Id: $org_id" \
  -H "Content-Type: application/json" \
  -d '{"action": "restore"}'
# draft -> active_starting
curl -X POST "$base_url/public/v1/teardowns/transition/$teardown_id" \
  -H "Authorization: Bearer $api_key" \
  -H "X-Organization-Id: $org_id" \
  -H "Content-Type: application/json" \
  -d '{"action": "submit"}'
import requests

def transition(teardown_id: str, action: str) -> dict:
    resp = requests.post(
        f"{base_url}/public/v1/teardowns/transition/{teardown_id}",
        headers={
            "Authorization": f"Bearer {api_key}",
            "X-Organization-Id": org_id,
        },
        json={"action": action},
    )
    resp.raise_for_status()
    return resp.json()

# Drive a teardown through the full lifecycle
transition(teardown_id, "start_processing")  # -> active_in_process
transition(teardown_id, "complete")          # -> active_completed
transition(teardown_id, "archive")           # -> archived
transition(teardown_id, "restore")           # -> draft
transition(teardown_id, "submit")            # -> active_starting
transition(teardown_id, "unpublish")         # -> draft
{
  "id": "3c707051-021d-4d04-a8e7-4eb254e80858",
  "status": "active_in_process",
  "previous_status": null
}
{
  "detail": "Cannot perform 'complete' from status 'active_starting'"
}
{
  "detail": "Action 'approve' requires admin role"
}
{
  "detail": "Reason required for rejection"
}
Drives a teardown between lifecycle states. Use this not PATCH to change a teardown’s status. Each action is validated against the state machine; trying an invalid transition returns 400 with a clear message. See status lifecycle for the full state diagram.

Headers

Authorization
string
required
Bearer tdao_live_…
X-Organization-Id
string
required
Your organization’s UUID.
Content-Type
string
required
application/json

Path parameters

teardown_id
string (UUID)
required

Body

action
string
required
The transition action to perform. See the table below.
reason
string
Required when action="reject". Optional otherwise. Stored in the audit row’s metadata.

Actions

ActionValid fromResultRequires
start_processingactive_startingactive_in_processseller
completeactive_in_processactive_completedseller
unpublishany active_*draft (UI-only state)seller
archiveanyarchivedseller
restorearchiveddraftseller
submitdraftactive_startingseller

Response

200 OK. A small transition response:
id
string (UUID)
The teardown’s id.
status
string
The new status after the transition.
previous_status
string | null
The prior status. Populated for admin-only transitions; usually null for the seller-facing actions listed above.
The transition endpoint currently returns the internal field names (id, status). The other teardown endpoints have moved to the partner-facing names (teardown_id, etc.). We’ll align this in a future release.
# active_starting -> active_in_process
curl -X POST "$base_url/public/v1/teardowns/transition/$teardown_id" \
  -H "Authorization: Bearer $api_key" \
  -H "X-Organization-Id: $org_id" \
  -H "Content-Type: application/json" \
  -d '{"action": "start_processing"}'
# active_in_process -> active_completed
curl -X POST "$base_url/public/v1/teardowns/transition/$teardown_id" \
  -H "Authorization: Bearer $api_key" \
  -H "X-Organization-Id: $org_id" \
  -H "Content-Type: application/json" \
  -d '{"action": "complete"}'
# any active_* -> draft
curl -X POST "$base_url/public/v1/teardowns/transition/$teardown_id" \
  -H "Authorization: Bearer $api_key" \
  -H "X-Organization-Id: $org_id" \
  -H "Content-Type: application/json" \
  -d '{"action": "unpublish"}'
# any -> archived (soft delete)
curl -X POST "$base_url/public/v1/teardowns/transition/$teardown_id" \
  -H "Authorization: Bearer $api_key" \
  -H "X-Organization-Id: $org_id" \
  -H "Content-Type: application/json" \
  -d '{"action": "archive"}'
# archived -> draft
curl -X POST "$base_url/public/v1/teardowns/transition/$teardown_id" \
  -H "Authorization: Bearer $api_key" \
  -H "X-Organization-Id: $org_id" \
  -H "Content-Type: application/json" \
  -d '{"action": "restore"}'
# draft -> active_starting
curl -X POST "$base_url/public/v1/teardowns/transition/$teardown_id" \
  -H "Authorization: Bearer $api_key" \
  -H "X-Organization-Id: $org_id" \
  -H "Content-Type: application/json" \
  -d '{"action": "submit"}'
import requests

def transition(teardown_id: str, action: str) -> dict:
    resp = requests.post(
        f"{base_url}/public/v1/teardowns/transition/{teardown_id}",
        headers={
            "Authorization": f"Bearer {api_key}",
            "X-Organization-Id": org_id,
        },
        json={"action": action},
    )
    resp.raise_for_status()
    return resp.json()

# Drive a teardown through the full lifecycle
transition(teardown_id, "start_processing")  # -> active_in_process
transition(teardown_id, "complete")          # -> active_completed
transition(teardown_id, "archive")           # -> archived
transition(teardown_id, "restore")           # -> draft
transition(teardown_id, "submit")            # -> active_starting
transition(teardown_id, "unpublish")         # -> draft
{
  "id": "3c707051-021d-4d04-a8e7-4eb254e80858",
  "status": "active_in_process",
  "previous_status": null
}
{
  "detail": "Cannot perform 'complete' from status 'active_starting'"
}
{
  "detail": "Action 'approve' requires admin role"
}
{
  "detail": "Reason required for rejection"
}

Audit trail

Every transition writes one audit row:
  • action = teardown.<your-action> (e.g., teardown.complete, teardown.archive).
  • previous_state = { "status": "<old-status>" }
  • new_state = { "status": "<new-status>" }
  • metadata.via_api = true plus the standard API-key tags.
  • For reject: metadata.reason carries your reason string.

See also