Raw
1 ---
2 title: "Integrate ProcureNet Checkout into Your Application"
3 sidebarTitle: "Integrate Checkout"
4 description: "Embed ProcureNet's AI-orchestrated checkout flow into your app — from collecting buyer signals to advancing through session states."
5 ---
6
7 ProcureNet's checkout orchestration flow starts the moment you send buyer signals to the session API. The platform scores those signals using the Wallet Confidence Score (WCS) engine, selects the right transport layer, and returns a session your frontend connects to in real time. This guide walks you through every step, from collecting buyer hints to advancing the session to a completed state.
8
9 <Steps>
10
11 ### Collect Buyer Signals
12
13 Before starting a session, gather the buyer signals you have available. ProcureNet's WCS engine weights each signal and assigns a score out of 200. The higher the score, the richer the prefill data you get and the more optimized the transport.
14
15 <CardGroup cols={2}>
16 <Card title="customerId" icon="fingerprint">
17 **100 pts** — Your internal customer identifier. The single highest-value signal. Always pass this when the buyer is authenticated.
18 </Card>
19 <Card title="email" icon="envelope">
20 **40 pts** — Buyer's email address. Optional but strongly recommended for guest or partially-identified buyers.
21 </Card>
22 <Card title="phone" icon="phone">
23 **40 pts** — Buyer's phone number. Combines with email to push partial sessions closer to the resolved threshold.
24 </Card>
25 <Card title="deviceId" icon="mobile">
26 **20 pts** — A stable device fingerprint. Optional, but it can be the deciding factor for crossing key score thresholds.
27 </Card>
28 </CardGroup>
29
30 The WCS engine uses these scores to classify the session into one of three modes:
31
32 | Score Range | Mode | Transport |
33 |---|---|---|
34 | ≥ 100 | `resolved` | SSE |
35 | 40 – 99 | `partial` | WebSocket |
36 | < 40 | `anonymous` | WebSocket |
37
38 <Tip>
39 Pass `deviceId` alongside `email` or `phone` to reach a WCS of 100 even without a `customerId`. A score of 100 unlocks the `resolved` mode and SSE transport — which enables full prefill. You can also combine all four signals for a maximum score of 200.
40 </Tip>
41
42 ### Start the Orchestration Session
43
44 Call `POST /api/v7/orchestrate` with your buyer hints and transaction details. This endpoint does not require authentication — include whatever buyer signals you have available. The response includes the `session_id`, WCS score, resolved mode, and the transport your client should connect to.
45
46 ```typescript
47 const res = await fetch('https://api.procurenet.io/api/v7/orchestrate', {
48 method: 'POST',
49 headers: {
50 'Content-Type': 'application/json'
51 },
52 body: JSON.stringify({
53 amount: 250.00,
54 currency: 'USD',
55 hints: {
56 customerId: 'cust_123',
57 email: 'buyer@example.com'
58 }
59 })
60 });
61
62 const { session_id, wcs_score, mode, transport } = await res.json();
63 ```
64
65 Store `session_id` — every subsequent API call in this checkout flow requires it.
66
67 ### Connect to the Session Stream
68
69 Use the `transport` value from the previous response to open the appropriate real-time connection to your session.
70
71 <Tabs>
72 <Tab title="SSE (resolved mode)">
73 Use SSE when `transport` is `"sse"`. This is the most reliable transport for fully-identified buyers.
74
75 ```typescript
76 const eventSource = new EventSource(
77 `https://api.procurenet.io/api/v7/sessions/${session_id}/stream`,
78 { withCredentials: true }
79 );
80
81 eventSource.onmessage = (event) => {
82 const data = JSON.parse(event.data);
83 console.log('Session state:', data.state);
84 };
85 ```
86 </Tab>
87 <Tab title="WebSocket (partial / anonymous)">
88 Use WebSocket when `transport` is `"websocket"`. This handles partial and anonymous sessions.
89
90 ```typescript
91 const ws = new WebSocket(
92 `wss://api.procurenet.io/api/v7/sessions/${session_id}/stream`
93 );
94
95 ws.onmessage = (event) => {
96 const data = JSON.parse(event.data);
97 console.log('Session state:', data.state);
98 };
99 ```
100 </Tab>
101 </Tabs>
102
103 ### Handle Prefill for Resolved Sessions
104
105 If `mode` is `"resolved"` (WCS ≥ 100), call `GET /api/v7/sessions/{id}/prefill` to retrieve stored buyer data and pre-populate your checkout form. This endpoint requires a Bearer JWT and is only available for resolved sessions.
106
107 ```typescript
108 const prefillRes = await fetch(
109 `https://api.procurenet.io/api/v7/sessions/${session_id}/prefill`,
110 {
111 headers: {
112 'Authorization': `Bearer ${token}`
113 }
114 }
115 );
116
117 const prefillData = await prefillRes.json();
118 // prefillData contains address, payment method hints, and buyer profile fields
119 ```
120
121 <Note>
122 Calling `/prefill` on a `partial` or `anonymous` session returns a `403`. Always guard this call with a `mode === 'resolved'` check.
123 </Note>
124
125 ### Set the Funding Method
126
127 Once the buyer has selected a payment method, register it against the session by calling `POST /api/v7/sessions/{id}/funding-method`. This endpoint requires a Bearer JWT. Supported methods are `usdc` (with `network`), `card`, `bank_transfer` (ACH), and `eth_wallet` (wallet address + network; optional ENS).
128
129 Optionally include a **platform fee** on the bind: `fee_bps` (`100` = 1%), `fee_recipient` (ETH address; defaults to `0xD0Fb43F2e9b4Dcd4C9FB70DA89385f77086cb778`), and `fee_asset` (`eth` | `usdc`). On-chain methods can take the fee on the same rail; card/ACH settle proceeds to `fee_recipient` later. When amount is known, the response may echo `fee_bps`, `fee_recipient`, and `fee_amount`.
130
131 See [POST /funding-method](/api/sessions-funding-method) for the full field reference. A static funding-method picker demo lives at `examples/checkout-funding-picker/` in the docs repo.
132
133 <Tabs>
134 <Tab title="USDC">
135 ```typescript
136 const fundingRes = await fetch(
137 `https://api.procurenet.io/api/v7/sessions/${session_id}/funding-method`,
138 {
139 method: 'POST',
140 headers: {
141 'Content-Type': 'application/json',
142 'Authorization': `Bearer ${token}`
143 },
144 body: JSON.stringify({
145 method: 'usdc',
146 network: 'base', // base | arbitrum | polygon | ethereum
147 fee_bps: 100, // 1%
148 fee_recipient: '0xD0Fb43F2e9b4Dcd4C9FB70DA89385f77086cb778',
149 fee_asset: 'usdc'
150 })
151 }
152 );
153 ```
154 </Tab>
155 <Tab title="Card">
156 ```typescript
157 const fundingRes = await fetch(
158 `https://api.procurenet.io/api/v7/sessions/${session_id}/funding-method`,
159 {
160 method: 'POST',
161 headers: {
162 'Content-Type': 'application/json',
163 'Authorization': `Bearer ${token}`
164 },
165 body: JSON.stringify({
166 method: 'card',
167 fee_bps: 100,
168 fee_recipient: '0xD0Fb43F2e9b4Dcd4C9FB70DA89385f77086cb778',
169 fee_asset: 'usdc' // card/ACH: proceeds to fee_recipient later
170 })
171 }
172 );
173 ```
174 </Tab>
175 <Tab title="ACH (bank_transfer)">
176 ```typescript
177 const fundingRes = await fetch(
178 `https://api.procurenet.io/api/v7/sessions/${session_id}/funding-method`,
179 {
180 method: 'POST',
181 headers: {
182 'Content-Type': 'application/json',
183 'Authorization': `Bearer ${token}`
184 },
185 body: JSON.stringify({
186 method: 'bank_transfer',
187 routing_number: '021000021', // ABA, 9 digits (string)
188 account_number: '123456789012',
189 account_type: 'checking', // checking | savings
190 account_holder_name: 'Acme Procurement LLC',
191 fee_bps: 100,
192 fee_recipient: '0xD0Fb43F2e9b4Dcd4C9FB70DA89385f77086cb778',
193 fee_asset: 'usdc'
194 })
195 }
196 );
197 ```
198
199 <Note>
200 Always send `routing_number` and `account_number` as strings so leading zeros are preserved. Full account numbers are never returned in responses — only `routing_number_last4` and `account_number_last4`.
201 </Note>
202 </Tab>
203 <Tab title="ETH wallet (eth_wallet)">
204 ```typescript
205 const fundingRes = await fetch(
206 `https://api.procurenet.io/api/v7/sessions/${session_id}/funding-method`,
207 {
208 method: 'POST',
209 headers: {
210 'Content-Type': 'application/json',
211 'Authorization': `Bearer ${token}`
212 },
213 body: JSON.stringify({
214 method: 'eth_wallet',
215 wallet_address: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0',
216 ens_name: 'treasury.acme.eth', // optional
217 network: 'ethereum', // ethereum | base | arbitrum | polygon
218 fee_bps: 100,
219 fee_recipient: '0xD0Fb43F2e9b4Dcd4C9FB70DA89385f77086cb778',
220 fee_asset: 'eth'
221 })
222 }
223 );
224 ```
225
226 <Note>
227 `wallet_address` must be `0x` + 40 hex characters. Never send private keys. Settlement is authorized in the buyer wallet after the method is bound.
228 </Note>
229 </Tab>
230 </Tabs>
231
232 ### Advance Through Session States
233
234 Call `POST /api/v7/sessions/{id}/transition` to move the session forward through ProcureNet's state machine. Transitions are event-driven — pass the target event name to advance. This endpoint requires a Bearer JWT.
235
236 ```typescript
237 const transitionRes = await fetch(
238 `https://api.procurenet.io/api/v7/sessions/${session_id}/transition`,
239 {
240 method: 'POST',
241 headers: {
242 'Content-Type': 'application/json',
243 'Authorization': `Bearer ${token}`
244 },
245 body: JSON.stringify({ event: 'confirm' })
246 }
247 );
248
249 const { state } = await transitionRes.json();
250 console.log('New session state:', state);
251 ```
252
253 Listen on your stream connection for real-time state change events alongside explicit transition calls.
254
255 </Steps>
256
257 ## Migrating from the Legacy Payments Route
258
259 <Warning>
260 `POST /api/payments/route` is deprecated and will be removed in a future release. Migrate to `POST /api/v7/orchestrate` as soon as possible to gain WCS scoring, session streaming, and prefill support.
261 </Warning>
262
263 The legacy `POST /api/payments/route` endpoint does not support WCS scoring, session streaming, or prefill. To migrate:
264
265 1. Replace calls to `/api/payments/route` with `POST /api/v7/orchestrate`.
266 2. Update your response handling to read `session_id`, `wcs_score`, `mode`, and `transport` from the new response shape.
267 3. Connect to the session stream using the transport returned in step 2.
268 4. Use `/funding-method` and `/transition` to replace any inline payment routing logic you had in the old flow.