1 ---
2 title: "POST /api/v7/sessions/{id}/transition — Advance State"
3 sidebarTitle: "POST /transition"
4 description: "Advance a session through the procurement state machine. Illegal moves return deterministic error codes. Every transition emits a timestamped audit event."
5 ---
6
7 ProcureNet manages each procurement session as a strict state machine. Calling this endpoint moves the session forward to a target state you specify. The engine validates that the transition is permitted from the session's current state — if it isn't, you receive a deterministic `400` error with a machine-readable rejection code so your integration can handle it without guesswork. Every successful transition also emits a timestamped audit event, giving you a complete, structured record of how a session progressed.
8
9 ## Authentication
10
11 <Warning>
12 This endpoint requires a valid Bearer JWT in the `Authorization` header. Requests without a token, or with an expired or malformed token, receive `401 Unauthorized`.
13 </Warning>
14
15 ```
16 Authorization: Bearer <your_jwt>
17 ```
18
19 ## Path Parameters
20
21 <ParamField path="id" type="string" required>
22 The session ID returned by `POST /api/v7/orchestrate`. Identifies the session whose state machine you are advancing.
23 </ParamField>
24
25 ## Request Body
26
27 <ParamField body="to" type="string" required>
28 The target state to transition the session into. The engine enforces which transitions are valid from the session's current state and rejects any that are out of sequence.
29
30 Common target states include:
31
32 | State | Meaning |
33 |---|---|
34 | `pending_payment` | Buyer has confirmed their cart; awaiting funding method |
35 | `escrow_pending` | High-value transaction detected; escrow acceptance required |
36 | `payment_processing` | Funding method submitted; payment is in flight |
37 | `completed` | Transaction finalized |
38 | `cancelled` | Session terminated by buyer or system |
39 </ParamField>
40
41 ## Request Example
42
43 ```typescript
44 const sessionId = 'sess_abc123';
45
46 const res = await fetch(
47 `https://api.procurenet.io/api/v7/sessions/${sessionId}/transition`,
48 {
49 method: 'POST',
50 headers: {
51 'Authorization': 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...',
52 'Content-Type': 'application/json'
53 },
54 body: JSON.stringify({ to: 'pending_payment' })
55 }
56 );
57
58 const result = await res.json();
59 // {
60 // "session_id": "sess_abc123",
61 // "previous_state": "orchestrated",
62 // "current_state": "pending_payment",
63 // "transitioned_at": "2026-04-01T14:23:11Z"
64 // }
65 ```
66
67 ## Response Fields
68
69 <ResponseField name="session_id" type="string" required>
70 Echoes back the session ID for correlation in your logs.
71 </ResponseField>
72
73 <ResponseField name="previous_state" type="string" required>
74 The state the session was in immediately before this transition.
75 </ResponseField>
76
77 <ResponseField name="current_state" type="string" required>
78 The state the session has moved into as a result of this call. This will match the `to` value you submitted.
79 </ResponseField>
80
81 <ResponseField name="transitioned_at" type="string" required>
82 ISO 8601 timestamp of when the transition was recorded. This is the same timestamp written to the transition audit event.
83 </ResponseField>
84
85 ## Response Example
86
87 ```json
88 {
89 "session_id": "sess_abc123",
90 "previous_state": "orchestrated",
91 "current_state": "pending_payment",
92 "transitioned_at": "2026-04-01T14:23:11Z"
93 }
94 ```
95
96 ## Handling Illegal Transitions
97
98 If you attempt a transition that is not valid from the session's current state, the engine returns `400` with a structured error body. Parse the `code` field to drive retry or fallback logic in your integration.
99
100 ```typescript
101 if (!res.ok) {
102 const err = await res.json();
103 // err.code === 'ILLEGAL_TRANSITION'
104 // err.current_state === 'payment_processing'
105 // err.attempted === 'pending_payment'
106 console.error(`Cannot transition: ${err.message}`);
107 }
108 ```
109
110 ```json
111 {
112 "code": "ILLEGAL_TRANSITION",
113 "message": "Cannot move to 'pending_payment' from 'payment_processing'.",
114 "current_state": "payment_processing",
115 "attempted": "pending_payment"
116 }
117 ```
118
119 <Info>
120 Every successful transition — and every rejected attempt — is emitted as a structured audit event. You can use these events to reconstruct the full lifecycle of any session for debugging or compliance purposes.
121 </Info>
122
123 ## Error Codes
124
125 | HTTP Status | Code | Description |
126 |---|---|---|
127 | `400 Bad Request` | `ILLEGAL_TRANSITION` | The `to` state is not reachable from the session's current state. |
128 | `400 Bad Request` | `UNKNOWN_STATE` | The `to` value is not a recognized session state. |
129 | `401 Unauthorized` | — | Missing, expired, or invalid Bearer JWT. |
130 | `404 Not Found` | — | No session exists for the provided `id`. |
131 | `410 Gone` | `SESSION_EXPIRED` | The session has passed its TTL and can no longer be transitioned. Start a new session with `POST /api/v7/orchestrate`. |