Summary
Building an App-to-User (A2U) payout flow on Testnet using the official pi-backend Node SDK (v0.1.3). The server flow (createPayment, submitPayment, completePayment) is wired and proven correct up to the createPayment call. createPayment returns HTTP 404 for a recipient uid that is valid, current, and freshly identity-verified. There is no A2U enablement control visible in the Developer Portal, and the 404 is opaque, so I want to confirm the recipient eligibility rules.
Environment
- SDK:
pi-backend (Node), v0.1.3
- Runtime: Next.js API route on Node.js runtime
- Network: Testnet (Testnet API key, Testnet app wallet funded)
- Platform host: default
https://api.minepi.com (no base URL override)
Steps to reproduce
- Initialize the SDK with the app's Testnet API key and the app wallet private seed.
- Call
createPayment with { amount, memo, metadata, uid }, where uid is the recipient's canonical app-specific user id.
- Observe the response.
Expected
createPayment returns a payment identifier so the flow can proceed.
Actual
createPayment throws with Request failed with status code 404. No payment id is returned.
What I have ruled out
- API key: regenerated and confirmed accepted. The same call moved from 401 to 404 after the key swap, so authentication to /v2/payments works.
- uid validity and rotation: the recipient uid is the canonical id for the username, identical across every recent identity sign-in. No rotation.
- Fresh authentication: the recipient completed a fresh sign-in minutes before the failed payout. Server logs show pi_token_verified (validated against /v2/me), then user_provisioned, then sign_in_complete, all for the same uid.
- Scope requested in code: the client calls Pi.authenticate with
['username', 'payments'].
- Platform host: confirmed from SDK source that createPayment posts to api.minepi.com for both networks; the Testnet/Mainnet split happens only at the Horizon submit step using the network value in the createPayment response. An experimental base URL override to the Testnet Horizon host failed with the same 404 (expected, since that host does not serve the platform payments endpoint). Reverted to default.
The likely cause I cannot confirm from my side
No payments consent dialog appears on the recipient's sign-in, even on a fully fresh sign-in. I suspect this user previously consented to username only (before payments was added to the scopes array), so Pi does not re-prompt and the verified token carries no active payments grant. The platform_API docs show the verification response includes credentials.scopes, but I want to confirm the mechanics before assuming.
Questions
- What are the exact preconditions for a uid to be a valid A2U createPayment recipient? Must the recipient have an active, approved
payments-scope grant (or a prior U2A payment) before they can receive A2U?
- If a user previously consented to
username only, how do I force a fresh payments-scope consent? Pi does not appear to re-prompt when the requested scope set changes for an already-consented user.
- Is A2U enabled by default for Testnet apps, or is there an activation step not surfaced in the Developer Portal?
- Does a 404 on POST /v2/payments specifically mean "recipient not payable," or can it also indicate an app or endpoint context issue?
Happy to share the exact request shape with secrets removed.
Summary
Building an App-to-User (A2U) payout flow on Testnet using the official
pi-backendNode SDK (v0.1.3). The server flow (createPayment, submitPayment, completePayment) is wired and proven correct up to the createPayment call.createPaymentreturns HTTP 404 for a recipient uid that is valid, current, and freshly identity-verified. There is no A2U enablement control visible in the Developer Portal, and the 404 is opaque, so I want to confirm the recipient eligibility rules.Environment
pi-backend(Node), v0.1.3https://api.minepi.com(no base URL override)Steps to reproduce
createPaymentwith{ amount, memo, metadata, uid }, whereuidis the recipient's canonical app-specific user id.Expected
createPaymentreturns a payment identifier so the flow can proceed.Actual
createPaymentthrows withRequest failed with status code 404. No payment id is returned.What I have ruled out
['username', 'payments'].The likely cause I cannot confirm from my side
No payments consent dialog appears on the recipient's sign-in, even on a fully fresh sign-in. I suspect this user previously consented to
usernameonly (beforepaymentswas added to the scopes array), so Pi does not re-prompt and the verified token carries no activepaymentsgrant. The platform_API docs show the verification response includescredentials.scopes, but I want to confirm the mechanics before assuming.Questions
payments-scope grant (or a prior U2A payment) before they can receive A2U?usernameonly, how do I force a freshpayments-scope consent? Pi does not appear to re-prompt when the requested scope set changes for an already-consented user.Happy to share the exact request shape with secrets removed.