Documentation Index
Fetch the complete documentation index at: https://base-a060aa97-meyer9-discv5-p2p-protocol-id.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Base Pay supports requesting user profile information during payments through the dataCallback capability. This allows you to collect personal information like email addresses, physical addresses, phone numbers, and names during transactions.
Supported Data Types
The following data types are supported for profile requests:
type DataCallbackType =
| 'email' // Email address
| 'phoneNumber' // Phone number with country code
| 'physicalAddress' // Physical address for shipping
| 'name' // User's full name
// Full type definitions for requests and capability
type DataCallbackRequestType = {
optional?: boolean;
type: DataCallbackType;
}
type DataCallbackCapability = {
requests: DataCallbackRequestType[];
callbackURL?: string;
}
Data Object Types
Name Object
{
firstName: string;
lastName: string;
}
Physical Address Object
{
address1: string;
address2?: string;
city: string;
state: string;
postalCode: string;
country: string;
name: {
firstName: string;
familyName: string;
};
}
Phone Number Object
{
number: string;
countryCode: string;
}
To request profile data, include the dataCallback capability in your wallet_sendCalls request:
const response = await provider.request({
method: "wallet_sendCalls",
params: [{
version: "1.0",
chainId: numberToHex(84532), // Base Sepolia
calls: [
// Your transaction calls here
],
capabilities: {
dataCallback: {
requests: [
{
type: "email",
optional: false, // Whether this field is optional
},
{
type: "physicalAddress",
optional: true,
},
// Add more requests as needed
],
callbackURL: "https://your-api.com/validate", // Your validation endpoint
},
},
}],
});
Callback API
Your callback API will receive a POST request with the following structure:
// Request body structure
{
calls: {
to: string;
data: string;
}[];
chainId: string;
capabilities: {
dataCallback: {
requestedInfo: {
email?: string;
phoneNumber?: {
number: string;
country: string;
isPrimary: boolean;
};
physicalAddress?: {
address1: string;
address2?: string;
city: string;
state: string;
postalCode: string;
countryCode: string;
name: {
firstName: string;
familyName: string;
};
};
isPrimary: boolean;
name?: {
firstName: string;
familyName: string;
};
onchainAddress?: string;
};
};
};
}
Your callback API must respond with one of two formats:
1. Success Response
Return the calls the user will end up submitting wrapped in a request object. They can be the same calls or new ones, but they must be present. You can change all capabilities (e.g. switching Paymaster if calls happen on a different chain) except the data callback capability, which must remain present.
{
request: {
calls: {
to: string;
data: string;
}[];
chainId: string;
capabilities: {
dataCallback: {
// Original or updated dataCallback capability
};
// Other capabilities can be changed as needed
};
}
}
2. Error Response
Return validation errors to prompt the user to correct their information:
{
errors: {
email?: string;
phoneNumber?: {
number?: string;
country?: string;
};
physicalAddress?: {
address1?: string;
address2?: string;
city?: string;
state?: string;
postalCode?: string;
countryCode?: string;
name?: {
firstName?: string;
familyName?: string;
};
};
name?: {
firstName?: string;
familyName?: string;
};
onchainAddress?: string;
};
}
Example Implementation
Here’s a complete example of a validation API endpoint:
export async function POST(request: Request) {
const requestData = await request.json();
try {
const { requestedInfo } = requestData.capabilities.dataCallback;
const errors = {};
// Validate email
if (requestedInfo.email && requestedInfo.email.endsWith("@example.com")) {
errors.email = "Example.com emails are not allowed";
}
// Validate physical address
if (requestedInfo.physicalAddress) {
const addr = requestedInfo.physicalAddress.physicalAddress;
if (addr.postalCode && addr.postalCode.length < 5) {
if (!errors.physicalAddress) errors.physicalAddress = {};
errors.physicalAddress.postalCode = "Invalid postal code";
}
}
// Return errors if any found
if (Object.keys(errors).length > 0) {
return Response.json({ errors });
}
// Success - return the request data wrapped in a request object
// The wallet expects the response to contain the original or modified calls
return Response.json({
request: requestData
});
// Alternative: Explicitly enumerate fields if needed
// return Response.json({
// request: {
// calls: requestData.calls,
// chainId: requestData.chainId,
// capabilities: requestData.capabilities
// }
// });
} catch (error) {
return Response.json({
errors: { server: "Server error validating data" }
});
}
}
Important Notes
-
HTTPS Required: Your callback URL must use HTTPS, even for local development. Use a service like ngrok for testing.
-
Return Original or New Calls: You MUST return the original calls or new calls in your success response. If you don’t, the wallet will return an error.
-
Optional Fields: You can make any requested field optional by setting
optional: true in the request. Optional fields will be marked as such in the Base Account interface.
-
Privacy: Users always have full control over their data. They can choose to share or withhold any information, and they’re clearly shown what data you’re requesting.
-
Validation: Base Account performs basic validation before sending data to your callback URL. This includes checking that emails are valid and addresses are properly formatted.