|
1
|
--- |
|
2
|
title: "Manually Confirm a USDC Payment — Admin Override" |
|
3
|
sidebarTitle: "POST /manual-confirm" |
|
4
|
description: "Force-confirm a pending USDC payment request using elevated admin credentials. Use when autoWatch is disabled or automated confirmation has stalled." |
|
5
|
--- |
|
6
|
|
|
7
|
The manual confirmation endpoint lets an administrator force a USDC payment into confirmed status without waiting for the automated on-chain watch cycle. This is an elevated operation intended for operational recovery — use it when `autoWatch` is disabled on your `ProcureNetWalletClient`, when a payment has stalled due to network delays, or when you need to confirm a payment outside the normal polling window. Both `x-perplexity-mod-key` and `x-admin-key` headers are required; this endpoint is not accessible with a mod key alone. |
|
8
|
|
|
9
|
## Endpoint |
|
10
|
|
|
11
|
```http |
|
12
|
POST /mods/procurement_wallet/usdc/manual-confirm |
|
13
|
``` |
|
14
|
|
|
15
|
## Authentication |
|
16
|
|
|
17
|
This endpoint requires **both** your mod API key and an admin key. Both headers must be present and valid; a missing or invalid header on either returns `401`. |
|
18
|
|
|
19
|
```text |
|
20
|
x-perplexity-mod-key: <your-api-key> |
|
21
|
x-admin-key: <your-admin-key> |
|
22
|
``` |
|
23
|
|
|
24
|
<Warning> |
|
25
|
Your admin key is an elevated credential that bypasses normal on-chain confirmation requirements. Never expose `x-admin-key` in client-side code, browser environments, or mobile apps. Restrict all calls to this endpoint to server-side admin workflows with access controls and audit logging in place. |
|
26
|
</Warning> |
|
27
|
|
|
28
|
## Request Body |
|
29
|
|
|
30
|
<ParamField body="payment_id" type="string" required> |
|
31
|
The `payment_id` of the payment you want to manually confirm. You can retrieve this from the original create-request response. |
|
32
|
</ParamField> |
|
33
|
|
|
34
|
## Code Example |
|
35
|
|
|
36
|
<CodeGroup> |
|
37
|
```typescript TypeScript (Bridge) |
|
38
|
import { VCIProcureNetBridge, ProcureNetWalletClient } from '@procurenet/wallet-sdk'; |
|
39
|
|
|
40
|
// Instantiate the wallet client and bridge |
|
41
|
const wallet = new ProcureNetWalletClient( |
|
42
|
'https://api.procurenet.io', |
|
43
|
process.env.PROCURENET_MOD_KEY! |
|
44
|
); |
|
45
|
|
|
46
|
const bridge = new VCIProcureNetBridge(queue, wallet); |
|
47
|
|
|
48
|
// manualConfirmPayment accepts a local record ID and admin key |
|
49
|
const result = await bridge.manualConfirmPayment( |
|
50
|
localId, // local record ID (number) |
|
51
|
process.env.ADMIN_KEY! |
|
52
|
); |
|
53
|
|
|
54
|
if (result.confirmed) { |
|
55
|
console.log('Payment manually confirmed. TX:', result.transaction_hash); |
|
56
|
} else { |
|
57
|
console.warn('Manual confirmation did not result in a confirmed status.'); |
|
58
|
} |
|
59
|
``` |
|
60
|
|
|
61
|
```typescript TypeScript (Direct Client) |
|
62
|
import { ProcureNetWalletClient } from '@procurenet/wallet-sdk'; |
|
63
|
|
|
64
|
const wallet = new ProcureNetWalletClient( |
|
65
|
'https://api.procurenet.io', |
|
66
|
process.env.PROCURENET_MOD_KEY! |
|
67
|
); |
|
68
|
|
|
69
|
const result = await wallet.manualConfirm( |
|
70
|
'pay_xyz789', |
|
71
|
process.env.ADMIN_KEY! |
|
72
|
); |
|
73
|
|
|
74
|
if (result.confirmed) { |
|
75
|
console.log('Transaction hash:', result.transaction_hash); |
|
76
|
} |
|
77
|
``` |
|
78
|
|
|
79
|
```bash cURL |
|
80
|
curl -X POST https://api.procurenet.io/mods/procurement_wallet/usdc/manual-confirm \ |
|
81
|
-H "Content-Type: application/json" \ |
|
82
|
-H "x-perplexity-mod-key: $PROCURENET_MOD_KEY" \ |
|
83
|
-H "x-admin-key: $ADMIN_KEY" \ |
|
84
|
-d '{ "payment_id": "pay_xyz789" }' |
|
85
|
``` |
|
86
|
</CodeGroup> |
|
87
|
|
|
88
|
## When to Use Manual Confirmation |
|
89
|
|
|
90
|
<CardGroup cols={2}> |
|
91
|
<Card title="autoWatch Disabled" icon="eye-slash"> |
|
92
|
If you initialized `ProcureNetWalletClient` with `autoWatch: false`, the client will not poll for on-chain confirmations. Use this endpoint to confirm payments after you have verified the transfer through an external source. |
|
93
|
</Card> |
|
94
|
<Card title="Stalled Confirmation" icon="clock"> |
|
95
|
If a payment remains unconfirmed longer than expected — for example, due to network congestion on Ethereum mainnet — you can use this endpoint to unblock the settlement flow. |
|
96
|
</Card> |
|
97
|
<Card title="Operational Recovery" icon="wrench"> |
|
98
|
During incidents where the watch service is temporarily unavailable, you can replay confirmations for affected payments using this endpoint from a secure admin context. |
|
99
|
</Card> |
|
100
|
<Card title="Testing & Staging" icon="flask"> |
|
101
|
In non-production environments where you are not routing real on-chain transfers, use manual confirmation to exercise the rest of your payment settlement workflow without waiting for blockchain activity. |
|
102
|
</Card> |
|
103
|
</CardGroup> |
|
104
|
|
|
105
|
## Response |
|
106
|
|
|
107
|
<ResponseField name="confirmed" type="boolean" required> |
|
108
|
`true` when the payment has been successfully force-confirmed. In most cases this will be `true` on a valid request, but may return `false` if the payment is already in a terminal failure state. |
|
109
|
</ResponseField> |
|
110
|
|
|
111
|
<ResponseField name="transaction_hash" type="string"> |
|
112
|
The blockchain transaction hash if one is available. For manually confirmed payments, this may be absent if the payment was confirmed without a corresponding on-chain transfer. |
|
113
|
</ResponseField> |
|
114
|
|
|
115
|
### Example Response |
|
116
|
|
|
117
|
```json |
|
118
|
{ |
|
119
|
"confirmed": true, |
|
120
|
"transaction_hash": "0x4f3c8b2a1e9d7f6c0b5a4e3d2c1b0a9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b" |
|
121
|
} |
|
122
|
``` |
|
123
|
|
|
124
|
## Error Codes |
|
125
|
|
|
126
|
| Status | Meaning | |
|
127
|
|---|---| |
|
128
|
| `401` | Missing or invalid `x-perplexity-mod-key` or `x-admin-key` header | |
|
129
|
| `404` | No payment found for the given `payment_id` | |
|
130
|
|
|
131
|
<Info> |
|
132
|
If you need to confirm multiple stalled payments in bulk, iterate over the affected payment IDs and call `wallet.manualConfirm(paymentId, adminKey)` for each one. Ensure your admin workflow logs each confirmation with a timestamp for your audit trail. |
|
133
|
</Info> |