|
1
|
--- |
|
2
|
title: "Poll USDC Payment Confirmation — Watch Endpoint" |
|
3
|
sidebarTitle: "GET /usdc/watch" |
|
4
|
description: "Poll an active USDC payment request for on-chain confirmation. Returns confirmed status and a transaction hash once the transfer is detected." |
|
5
|
--- |
|
6
|
|
|
7
|
After creating a USDC payment request, use the watch endpoint to check whether the corresponding on-chain transfer has been confirmed. Call this endpoint periodically with the `payment_id` returned by the create endpoint until `confirmed` is `true`. When you initialize `ProcureNetWalletClient` with `autoWatch: true`, the client handles this polling loop automatically — you only need to call this endpoint directly when you want to manage the polling lifecycle yourself. |
|
8
|
|
|
9
|
## Endpoint |
|
10
|
|
|
11
|
```http |
|
12
|
GET /mods/procurement_wallet/usdc/watch/{paymentId} |
|
13
|
``` |
|
14
|
|
|
15
|
## Authentication |
|
16
|
|
|
17
|
Requests require your mod API key in the `x-perplexity-mod-key` header. |
|
18
|
|
|
19
|
```text |
|
20
|
x-perplexity-mod-key: <your-api-key> |
|
21
|
``` |
|
22
|
|
|
23
|
## Path Parameters |
|
24
|
|
|
25
|
<ParamField path="paymentId" type="string" required> |
|
26
|
The `payment_id` returned when you created the payment request via [`POST /usdc/request`](/api/usdc-request). |
|
27
|
</ParamField> |
|
28
|
|
|
29
|
## Polling Behavior |
|
30
|
|
|
31
|
Call this endpoint on a fixed interval until the response includes `"confirmed": true`. A reasonable starting interval is every 10–15 seconds for `base` and `arbitrum` networks, and every 30–60 seconds for `ethereum` mainnet. |
|
32
|
|
|
33
|
<Note> |
|
34
|
If `autoWatch: true` is set on your `ProcureNetWalletClient` instance, the client automatically calls `watchPayment()` after initiating a payment request. You do not need to poll manually in that case. |
|
35
|
</Note> |
|
36
|
|
|
37
|
## Code Example |
|
38
|
|
|
39
|
<CodeGroup> |
|
40
|
```typescript TypeScript |
|
41
|
import { ProcureNetWalletClient } from '@procurenet/wallet-sdk'; |
|
42
|
|
|
43
|
const wallet = new ProcureNetWalletClient( |
|
44
|
'https://api.procurenet.io', |
|
45
|
process.env.PROCURENET_MOD_KEY! |
|
46
|
); |
|
47
|
|
|
48
|
// Manual polling loop |
|
49
|
async function pollUntilConfirmed(paymentId: string): Promise<string | undefined> { |
|
50
|
const INTERVAL_MS = 15_000; |
|
51
|
const MAX_ATTEMPTS = 40; // ~10 minutes |
|
52
|
|
|
53
|
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) { |
|
54
|
const result = await wallet.watchPayment(paymentId); |
|
55
|
|
|
56
|
if (result.confirmed) { |
|
57
|
console.log('Transaction confirmed:', result.transaction_hash); |
|
58
|
return result.transaction_hash; |
|
59
|
} |
|
60
|
|
|
61
|
console.log(`Attempt ${attempt + 1}: not yet confirmed. Retrying...`); |
|
62
|
await new Promise(resolve => setTimeout(resolve, INTERVAL_MS)); |
|
63
|
} |
|
64
|
|
|
65
|
console.warn('Payment not confirmed within polling window.'); |
|
66
|
return undefined; |
|
67
|
} |
|
68
|
|
|
69
|
const txHash = await pollUntilConfirmed('pay_xyz789'); |
|
70
|
``` |
|
71
|
|
|
72
|
```bash cURL |
|
73
|
curl -X GET \ |
|
74
|
https://api.procurenet.io/mods/procurement_wallet/usdc/watch/pay_xyz789 \ |
|
75
|
-H "x-perplexity-mod-key: $PROCURENET_MOD_KEY" |
|
76
|
``` |
|
77
|
</CodeGroup> |
|
78
|
|
|
79
|
## Response |
|
80
|
|
|
81
|
<ResponseField name="confirmed" type="boolean" required> |
|
82
|
`true` when the on-chain transaction has been detected and confirmed. `false` if the payment is still pending or has expired without a matching transfer. |
|
83
|
</ResponseField> |
|
84
|
|
|
85
|
<ResponseField name="transaction_hash" type="string"> |
|
86
|
The blockchain transaction hash for the confirmed transfer. This field is only present when `confirmed` is `true`. Store this value for auditing and reconciliation. |
|
87
|
</ResponseField> |
|
88
|
|
|
89
|
### Example Response — Pending |
|
90
|
|
|
91
|
```json |
|
92
|
{ |
|
93
|
"confirmed": false |
|
94
|
} |
|
95
|
``` |
|
96
|
|
|
97
|
### Example Response — Confirmed |
|
98
|
|
|
99
|
```json |
|
100
|
{ |
|
101
|
"confirmed": true, |
|
102
|
"transaction_hash": "0x4f3c8b2a1e9d7f6c0b5a4e3d2c1b0a9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b" |
|
103
|
} |
|
104
|
``` |
|
105
|
|
|
106
|
## Expired Payments |
|
107
|
|
|
108
|
<Warning> |
|
109
|
If a payment request expires before the transfer is confirmed, this endpoint returns `"confirmed": false` with no `transaction_hash`. The payment request cannot be reactivated. Create a new payment request via [`POST /usdc/request`](/api/usdc-request) and restart the confirmation flow. |
|
110
|
</Warning> |
|
111
|
|
|
112
|
## Error Codes |
|
113
|
|
|
114
|
| Status | Meaning | |
|
115
|
|---|---| |
|
116
|
| `401` | Missing or invalid `x-perplexity-mod-key` header | |
|
117
|
| `404` | No payment found for the given `paymentId` | |
|
118
|
|
|
119
|
<Tip> |
|
120
|
Once you receive `"confirmed": true`, record the `transaction_hash` in your own systems immediately for auditing and reconciliation purposes. |
|
121
|
</Tip> |