API Documentation
Relayer API Documentation
Environment Setup
Ensure you have a .env
file or other definition with your chosen relayer endpoint. We have provided a sample one here.
RELAYER_API_URL=https://relayerapi.emailwallet.org
When you want more flexibility, you can deploy your own relayer via the Relayer Infrastructure.
Core API Endpoints
These endpoints concern basic universal features like sending ERC20s and ERC721s. You can see how to hit this or staging APIs for account recovery or oauth login in those specific docs. For safe signers, simply adding an email wallet address to a Safe Wallet on Base Sepolia will automatically trigger the email-based signer flow -- to make that multichain, please reach out to the team.
Create Account
Endpoint:
POST /api/createAccount
Request Body:
{
"email_addr": "user@example.com"
}
Example:
const createAccount = async (email) => {
const response = await fetch(`${RELAYER_API_URL}/api/createAccount`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email_addr: email }),
});
const textResponse = await response.text();
console.log("Parsed response:", textResponse);
return textResponse != "0x" ? textResponse : "";
};
createAccount('user@example.com')
.then(address => console.log('Account Address:', address))
.catch(error => console.error('Error:', error));
Check if Account is Created
Endpoint:
POST /api/isAccountCreated
Request Body:
{
"email_addr": "user@example.com"
}
Example:
const isAccountCreated = async (email) => {
const response = await fetch(`${RELAYER_API_URL}/api/isAccountCreated`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email_addr: email }),
});
const text = await response.text();
return text == "true" ? "Account exists" : "Account does not exist";
};
isAccountCreated('user@example.com')
.then(status => console.log('Account Status:', status))
.catch(error => console.error('Error:', error));
Send Asset
Endpoint:
POST /api/send
Request Body:
{
"email_addr": "user@example.com",
"amount": 100,
"token_id": "token123",
"recipient_addr": "recipient@example.com",
"is_recipient_email": true
}
Example:
const sendAsset = async (amountString, tokenId, recipientAddr) => {
const email = localStorage.getItem("loggedInUser") || "";
const isRecipientEmail = recipientAddr.includes("@");
const amount = parseFloat(amountString);
const response = await fetch(`${RELAYER_API_URL}/api/send`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email_addr: email,
amount,
token_id: tokenId,
recipient_addr: recipientAddr,
is_recipient_email: isRecipientEmail,
}),
});
const data = await response.text();
return data ? "Asset sent successfully" : "Failed to send asset";
};
sendAsset('100', 'token123', 'recipient@example.com')
.then(status => console.log('Send Status:', status))
.catch(error => console.error('Error:', error));
Recover Account Code
Endpoint:
POST /api/recoverAccountCode
Request Body:
{
"email_addr": "user@example.com"
}
Example:
const recoverAccountCode = async (email) => {
const response = await fetch(`${RELAYER_API_URL}/api/recoverAccountCode`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email_addr: email }),
});
const data = await response.text();
return data
? "Account key recovery email sent"
: "Failed to send account key recovery email";
};
recoverAccountCode('user@example.com')
.then(status => console.log('Recovery Status:', status))
.catch(error => console.error('Error:', error));
Get Wallet Address
Endpoint:
POST /api/getWalletAddress
Request Body:
{
"email_addr": "user@example.com",
"account_code": "<characters with 256 bits of entropy>"
}
Example:
const getWalletAddress = async (email, accountKey) => {
let code = accountKey.startsWith("0x") ? accountKey : `0x${accountKey}`;
const response = await fetch(`${RELAYER_API_URL}/api/getWalletAddress`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email_addr: email, account_code: code }),
});
const data = await response.text();
return data || "Failed to fetch address, no address found";
};
getWalletAddress('user@example.com', 'accountKey123')
.then(address => console.log('Wallet Address:', address))
.catch(error => console.error('Error:', error));
Transfer NFT
Endpoint:
POST /api/nftTransfer
Request Body:
{
"email_addr": "user@example.com",
"nft_id": 123,
"nft_addr": "0xNFTContractAddress",
"recipient_addr": "recipient@example.com",
"is_recipient_email": true
}
Example:
const transferNFT = async (nftId, nftAddr, recipientAddr) => {
const email = localStorage.getItem("loggedInUser") || "";
const isRecipientEmail = recipientAddr.includes("@");
const response = await fetch(`${RELAYER_API_URL}/api/nftTransfer`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email_addr: email,
nft_id: Number(nftId),
nft_addr: nftAddr,
recipient_addr: recipientAddr,
is_recipient_email: isRecipientEmail,
}),
});
const data = await response.text();
return data ? "NFT transferred successfully" : "Failed to transfer NFT";
};
transferNFT('nft123', '0xNFTContractAddress', 'recipient@example.com')
.then(status => console.log('Transfer Status:', status))
.catch(error => console.error('Error:', error));