docs: publish payment destination + secure payment link integration guide#82
Conversation
Greptile SummaryThis PR replaces the previous "Quick start"-style secure payments guide with a comprehensive end-to-end onboarding walkthrough covering wallet sign-in, payment destination creation, Client ID generation, webhook setup, and secure payment link creation. The rewrite is well-structured and meaningfully improves self-serve discoverability for integration partners. Key findings:
Confidence Score: 3/5
Important Files Changed
Sequence DiagramsequenceDiagram
actor Dev as Developer
participant Dash as Dashboard<br/>(dashboard.request.network)
participant Auth as Auth API<br/>(auth.request.network)
participant Portal as Portal<br/>(portal.request.network)
participant API as Request API<br/>(api.request.network)
Dev->>Dash: Sign in with wallet (Step 1)
Dash-->>Dev: wallet session cookie (session_token)
Dev->>Dash: Create payment destination (Step 2)
Dash-->>Dev: humanReadableInteropAddress (destinationId)
Dev->>Auth: POST /v1/client-ids (Step 3)
Auth-->>Dev: clientId
Dev->>Portal: Configure webhook endpoint (Step 4)
Portal-->>Dev: webhook signing secret
Dev->>API: POST /v2/secure-payments<br/>x-client-id: clientId<br/>destinationId: humanReadableInteropAddress:tokenAddress (Step 5)
API-->>Dev: requestIds, securePaymentUrl, token
Dev->>Dev: Share securePaymentUrl with payer
Portal-->>Dev: Webhook event (payment.confirmed / payment.partial)
opt Step 6 – optional polling
Dev->>API: GET /v2/request/{requestId}
API-->>Dev: hasBeenPaid, txHash
end
Reviews (1): Last reviewed commit: "docs: publish end-to-end payment destina..." | Re-trigger Greptile |
| Dashboard returns a `destinationId` (also shown as `humanReadableInteropAddress`). Save it for Step 5. | ||
|
|
||
| The `destinationId` follows ERC-7828 format: | ||
|
|
||
| ```text | ||
| {walletAddress}@eip155:{chainId}#{checksum} | ||
| ``` |
There was a problem hiding this comment.
destinationId definition inconsistency between Step 2 and Step 5
Step 2 tells readers that Dashboard returns a destinationId which is the same as humanReadableInteropAddress (ERC-7828 format, e.g. {walletAddress}@eip155:{chainId}#{checksum}), and instructs them to "Save it for Step 5."
However, Step 5's "Constructing destinationId" section defines the destinationId field used in the API call as a composite value: {humanReadableInteropAddress}:{tokenAddress}. A user who blindly reuses the destinationId saved in Step 2 will submit an incomplete identifier (missing :{tokenAddress}) and the API call will fail.
The fix is to clarify in Step 2 that what Dashboard returns is the humanReadableInteropAddress portion only, and that the full destinationId for the API is humanReadableInteropAddress:tokenAddress (constructed in Step 5):
| Dashboard returns a `destinationId` (also shown as `humanReadableInteropAddress`). Save it for Step 5. | |
| The `destinationId` follows ERC-7828 format: | |
| ```text | |
| {walletAddress}@eip155:{chainId}#{checksum} | |
| ``` | |
| Dashboard returns a `humanReadableInteropAddress`. Save it; you will combine it with a token address in Step 5 to form the full `destinationId`. | |
| The `humanReadableInteropAddress` follows ERC-7828 format: |
| ```text | ||
| ┌──────────────────────┐ | ||
| │ 1. Sign in with │ dashboard.request.network | ||
| │ wallet │ | ||
| └──────────┬───────────┘ | ||
| │ | ||
| ▼ | ||
| ┌──────────────────────┐ | ||
| │ 2. Create Payee │ dashboard.request.network | ||
| │ Destination │ | ||
| └──────────┬───────────┘ | ||
| │ | ||
| ▼ | ||
| ┌──────────────────────┐ | ||
| │ 3. Create Client ID │ auth.request.network/open-api | ||
| │ (Auth API) │ | ||
| └──────────┬───────────┘ | ||
| │ | ||
| ▼ | ||
| ┌──────────────────────┐ | ||
| │ 4. Set up Webhook │ portal.request.network | ||
| └──────────┬───────────┘ | ||
| │ | ||
| ▼ | ||
| ┌──────────────────────┐ | ||
| │ 5. Create Secure │ api.request.network/open-api | ||
| │ Payment (link) │ | ||
| └──────────────────────┘ | ||
| ``` |
There was a problem hiding this comment.
The ASCII art diagram lists 5 steps, but the guide documents 6 steps (Step 6: "Check payment status" is optional but still part of the flow). Consider adding it with an "(optional)" label to match the rest of the guide, or noting in the diagram that Step 6 is optional:
| ```text | |
| ┌──────────────────────┐ | |
| │ 1. Sign in with │ dashboard.request.network | |
| │ wallet │ | |
| └──────────┬───────────┘ | |
| │ | |
| ▼ | |
| ┌──────────────────────┐ | |
| │ 2. Create Payee │ dashboard.request.network | |
| │ Destination │ | |
| └──────────┬───────────┘ | |
| │ | |
| ▼ | |
| ┌──────────────────────┐ | |
| │ 3. Create Client ID │ auth.request.network/open-api | |
| │ (Auth API) │ | |
| └──────────┬───────────┘ | |
| │ | |
| ▼ | |
| ┌──────────────────────┐ | |
| │ 4. Set up Webhook │ portal.request.network | |
| └──────────┬───────────┘ | |
| │ | |
| ▼ | |
| ┌──────────────────────┐ | |
| │ 5. Create Secure │ api.request.network/open-api | |
| │ Payment (link) │ | |
| └──────────────────────┘ | |
| ``` | |
| ```text | |
| ┌──────────────────────┐ | |
| │ 1. Sign in with │ dashboard.request.network | |
| │ wallet │ | |
| └──────────┬───────────┘ | |
| │ | |
| ▼ | |
| ┌──────────────────────┐ | |
| │ 2. Create Payee │ dashboard.request.network | |
| │ Destination │ | |
| └──────────┬───────────┘ | |
| │ | |
| ▼ | |
| ┌──────────────────────┐ | |
| │ 3. Create Client ID │ auth.request.network/open-api | |
| │ (Auth API) │ | |
| └──────────┬───────────┘ | |
| │ | |
| ▼ | |
| ┌──────────────────────┐ | |
| │ 4. Set up Webhook │ portal.request.network | |
| └──────────┬───────────┘ | |
| │ | |
| ▼ | |
| ┌──────────────────────┐ | |
| │ 5. Create Secure │ api.request.network/open-api | |
| │ Payment (link) │ | |
| └──────────┬───────────┘ | |
| │ | |
| ▼ | |
| ┌──────────────────────┐ | |
| │ 6. Check Payment │ api.request.network/open-api | |
| │ Status (opt.) │ | |
| └──────────────────────┘ |
| ## Step 1: Sign in with wallet | ||
|
|
||
| 1. Go to [dashboard.request.network](https://dashboard.request.network/). | ||
| 2. Connect your EVM wallet and sign the authentication message. | ||
| 3. Keep this session active for the next steps. | ||
|
|
||
| <Warning> | ||
| Wallet sessions expire after around 15 minutes. If your session expires, sign in again from Dashboard. | ||
| </Warning> | ||
|
|
||
| ## Step 2: Create a payment destination | ||
|
|
||
| A payment destination registers where you receive payments, by linking your wallet address to a token on a chain. | ||
|
|
||
| 1. In Dashboard, navigate to payment destination setup. | ||
| 2. Select chain and token. | ||
| 3. Confirm creation. |
There was a problem hiding this comment.
Use
<Steps> component for numbered procedures
The AGENTS.md style guide says: "Use Steps for procedures and sequential instructions." The sub-instruction lists within each step section (e.g. "1. Go to …", "2. Connect …", "3. Keep …" in Step 1 and similar patterns in Steps 2–5) should use Mintlify's <Steps> / <Step> components instead of plain numbered Markdown lists. This applies consistently across Steps 1 through 5 in the file.
Example for Step 1:
<Steps>
<Step title="Navigate to Dashboard">
Go to [dashboard.request.network](https://dashboard.request.network/).
</Step>
<Step title="Connect your wallet">
Connect your EVM wallet and sign the authentication message.
</Step>
<Step title="Keep session active">
Keep this session active for the next steps.
</Step>
</Steps>
The same pattern applies at lines 71–73 (Step 2), 104–106 (Step 3), 155–157 (Step 4), and 179–181 (Step 5).
Context Used: AGENTS.md (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| ```json | ||
| { | ||
| "requests": [ | ||
| { | ||
| "requestIds": [ | ||
| "01e273ecc29d4b526df3a0f1f05ffc59372af8752c2b678096e49ac270416a7cdb" | ||
| ], | ||
| "securePaymentUrl": "https://secure.request.network/?token=01ABC123DEF456GHI789JKL", | ||
| "token": "01ABC123DEF456GHI789JKL" | ||
| "destinationId": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7@eip155:11155111#1f969856:0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", | ||
| "amount": "1" | ||
| } | ||
| ``` | ||
| </ResponseExample> | ||
| </Step> | ||
|
|
||
| <Step title="Persist payment mapping in your database"> | ||
| Store at least: | ||
| - your internal metadata | ||
| - returned `requestIds` | ||
| - `token` | ||
| - `securePaymentUrl` | ||
|
|
||
| This mapping lets you reconcile webhook events back to your internal records. | ||
| </Step> | ||
|
|
||
| <Step title="Redirect payer to secure page"> | ||
| Redirect in the same tab or open the secure URL in a new tab. | ||
| </Step> | ||
|
|
||
| <Step title="Process webhook events and update order status"> | ||
| Handle payment events from webhooks and update your order/payment state from those events. | ||
| </Step> | ||
| </Steps> | ||
|
|
||
| ## Integration pattern: generated URL + redirect | ||
|
|
||
| ### Backend example (Node.js/Express) | ||
|
|
||
| ```javascript server.js | ||
| import express from "express"; | ||
|
|
||
| const app = express(); | ||
| app.use(express.json()); | ||
|
|
||
| app.post("/api/checkout/secure-payment", async (req, res) => { | ||
| const { orderId, payee, amount, currencyId } = req.body; | ||
|
|
||
| const apiResponse = await fetch("https://api.request.network/v2/secure-payments", { | ||
| method: "POST", | ||
| headers: { | ||
| "x-api-key": process.env.REQUEST_API_KEY, | ||
| "content-type": "application/json", | ||
| }, | ||
| body: JSON.stringify({ | ||
| requests: [ | ||
| { | ||
| payee, | ||
| amount, | ||
| invoiceCurrency: currencyId, | ||
| paymentCurrency: currencyId, | ||
| }, | ||
| ], | ||
| }), | ||
| }); | ||
|
|
||
| if (!apiResponse.ok) { | ||
| const errorBody = await apiResponse.text(); | ||
| return res.status(apiResponse.status).json({ error: errorBody }); | ||
| } | ||
|
|
||
| const securePayment = await apiResponse.json(); | ||
|
|
||
| // Persist in your DB | ||
| // Example payload: | ||
| // { | ||
| // orderId, | ||
| // requestIds: securePayment.requestIds, | ||
| // token: securePayment.token, | ||
| // securePaymentUrl: securePayment.securePaymentUrl, | ||
| // status: "pending" | ||
| // } | ||
|
|
||
| return res.status(200).json({ | ||
| orderId, | ||
| securePaymentUrl: securePayment.securePaymentUrl, | ||
| }); | ||
| }); | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| ### Constructing `destinationId` | ||
|
|
||
| `destinationId` is: | ||
|
|
||
| ```text | ||
| {humanReadableInteropAddress}:{tokenAddress} | ||
| ``` | ||
|
|
||
| ### Frontend redirect examples | ||
| Example: | ||
|
|
||
| <CodeGroup> | ||
| ```javascript Same tab | ||
| window.location.href = securePaymentUrl; | ||
| ```text | ||
| 0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7@eip155:11155111#1f969856:0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C | ||
| └──────────── humanReadableInteropAddress ─────────────────┘ └──────────── tokenAddress ──────────────────────┘ | ||
| ``` | ||
|
|
||
| ```javascript New tab | ||
| window.open(securePaymentUrl, "_blank", "noopener,noreferrer"); | ||
| | Field | Type | Required | Description | | ||
| | --- | --- | --- | --- | | ||
| | `requests` | `array` | Yes | Array of payment request items | | ||
| | `requests[].destinationId` | `string` | Yes | Composite ID `humanReadableInteropAddress:tokenAddress` | | ||
| | `requests[].amount` | `string` | Yes | Human-readable amount (for example `"10"`) | | ||
| | `feePercentage` | `string` | No | Fee percentage 0-100; if set, `feeAddress` is required | | ||
| | `feeAddress` | `string` | No | Fee recipient address | | ||
|
|
||
| **Example response** | ||
|
|
||
| ```json 201 Created | ||
| { | ||
| "requestIds": [ | ||
| "01de2a889ee629c15b71b5d7964e3a7e87638c886be75bf1b9d2c1fbe64cf855fb" | ||
| ], | ||
| "securePaymentUrl": "https://pay.request.network/?token=01KJRA0M9QG8MA4X887908T8A4", | ||
| "token": "01KJRA0M9QG8MA4X887908T8A4" | ||
| } |
There was a problem hiding this comment.
Use
<RequestExample> / <ResponseExample> for API endpoint documentation
AGENTS.md states: "Use RequestExample/ResponseExample specifically for API endpoint documentation" and "Use ParamField for API parameters, ResponseField for API responses."
The request body (lines 183–192) and its response (lines 219–227) are presented as plain code blocks with a Markdown table for parameters. The same pattern occurs for the Client ID response (lines 131–147) and the status-check response (lines 251–270). Replacing these with <RequestExample>, <ResponseExample>, and <ParamField> / <ResponseField> components will keep the guide consistent with the rest of the docs and provide a richer interactive rendering. This pattern also appears at the Step 3 response (lines 131–147) and Step 6 response examples (lines 251–270).
Context Used: AGENTS.md (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Summary
Why
Integration partners currently need manual access to internal docs. This makes onboarding self-serve in public docs.
Test plan
Closes #81