curl --request POST \
--url https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--data '
{
"signer": "passkey:cWtP7gmZbd98HbKUuGXx5Q",
"approver": "passkey:cWtP7gmZbd98HbKUuGXx5Q",
"deployImmediately": true,
"expiresAt": "2024-01-15T10:30:00.000Z",
"scopes": {
"spendingLimit": {
"amount": "10",
"interval": 86400
},
"tokenLocator": "base-sepolia:usdc",
"type": "transfer"
}
}
'import requests
url = "https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers"
payload = {
"signer": "passkey:cWtP7gmZbd98HbKUuGXx5Q",
"approver": "passkey:cWtP7gmZbd98HbKUuGXx5Q",
"deployImmediately": True,
"expiresAt": "2024-01-15T10:30:00.000Z",
"scopes": {
"spendingLimit": {
"amount": "10",
"interval": 86400
},
"tokenLocator": "base-sepolia:usdc",
"type": "transfer"
}
}
headers = {
"X-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
signer: 'passkey:cWtP7gmZbd98HbKUuGXx5Q',
approver: 'passkey:cWtP7gmZbd98HbKUuGXx5Q',
deployImmediately: true,
expiresAt: '2024-01-15T10:30:00.000Z',
scopes: {
spendingLimit: {amount: '10', interval: 86400},
tokenLocator: 'base-sepolia:usdc',
type: 'transfer'
}
})
};
fetch('https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'signer' => 'passkey:cWtP7gmZbd98HbKUuGXx5Q',
'approver' => 'passkey:cWtP7gmZbd98HbKUuGXx5Q',
'deployImmediately' => true,
'expiresAt' => '2024-01-15T10:30:00.000Z',
'scopes' => [
'spendingLimit' => [
'amount' => '10',
'interval' => 86400
],
'tokenLocator' => 'base-sepolia:usdc',
'type' => 'transfer'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers"
payload := strings.NewReader("{\n \"signer\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"approver\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"deployImmediately\": true,\n \"expiresAt\": \"2024-01-15T10:30:00.000Z\",\n \"scopes\": {\n \"spendingLimit\": {\n \"amount\": \"10\",\n \"interval\": 86400\n },\n \"tokenLocator\": \"base-sepolia:usdc\",\n \"type\": \"transfer\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-KEY", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers")
.header("X-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"signer\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"approver\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"deployImmediately\": true,\n \"expiresAt\": \"2024-01-15T10:30:00.000Z\",\n \"scopes\": {\n \"spendingLimit\": {\n \"amount\": \"10\",\n \"interval\": 86400\n },\n \"tokenLocator\": \"base-sepolia:usdc\",\n \"type\": \"transfer\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"signer\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"approver\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"deployImmediately\": true,\n \"expiresAt\": \"2024-01-15T10:30:00.000Z\",\n \"scopes\": {\n \"spendingLimit\": {\n \"amount\": \"10\",\n \"interval\": 86400\n },\n \"tokenLocator\": \"base-sepolia:usdc\",\n \"type\": \"transfer\"\n }\n}"
response = http.request(request)
puts response.read_body{
"locator": "<string>",
"members": [
{
"address": "<string>",
"locator": "<string>",
"phone": "<string>",
"type": "phone"
}
],
"threshold": 4503599627370496,
"type": "quorum",
"expiresAt": 123,
"scopes": {
"spendingLimit": {
"amount": "100"
},
"tokenLocator": "stellar:usdc",
"type": "transfer"
},
"transaction": {
"chainType": "stellar",
"createdAt": 123,
"id": "<string>",
"onChain": {
"expiration": 123,
"transaction": {
"method": "<string>",
"tx": "<string>"
},
"explorerLink": "<string>",
"ledger": 123,
"proxiedTxId": "<string>",
"result": "<unknown>",
"txId": "<string>"
},
"status": "awaiting-approval",
"walletType": "smart",
"approvals": {
"pending": [
{
"quorumApprovals": {
"pending": [
{
"member": {
"address": "<string>",
"locator": "<string>",
"type": "api-key"
},
"message": "<string>"
}
],
"remaining": 123,
"submitted": [
{
"member": {
"address": "<string>",
"locator": "<string>",
"type": "api-key"
},
"message": "<string>",
"signature": "<string>",
"submittedAt": 123
}
],
"threshold": 123
},
"signer": {
"locator": "<string>",
"type": "quorum"
}
}
],
"submitted": [
{
"quorumApprovals": {
"pending": [
{
"member": {
"address": "<string>",
"locator": "<string>",
"type": "api-key"
},
"message": "<string>"
}
],
"remaining": 123,
"submitted": [
{
"member": {
"address": "<string>",
"locator": "<string>",
"type": "api-key"
},
"message": "<string>",
"signature": "<string>",
"submittedAt": 123
}
],
"threshold": 123
},
"signer": {
"locator": "<string>",
"type": "quorum"
}
}
],
"required": 123
},
"completedAt": 123,
"error": {
"message": "<string>",
"reason": "program_error",
"logs": "<unknown>",
"revertData": {}
},
"fees": {
"mode": "project",
"actual": "<unknown>",
"billed": {
"usd": 123
},
"billing": {
"status": "failed"
},
"estimate": "<unknown>"
},
"sendParams": {
"params": {
"recipient": "<string>",
"recipientAddress": "<string>",
"amount": "<string>"
},
"token": "<string>"
}
}
}{
"error": true,
"message": "<error message>",
"code": "DEVICE_SIGNER_NOT_SUPPORTED"
}{
"error": true,
"message": "<error message>",
"code": "DEVICE_SIGNER_NOT_SUPPORTED"
}Create Delegated Signer
Create a delegated signer for a smart wallet with optional restrictions around permissions and expiry date.
API scope required: wallets.create
curl --request POST \
--url https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--data '
{
"signer": "passkey:cWtP7gmZbd98HbKUuGXx5Q",
"approver": "passkey:cWtP7gmZbd98HbKUuGXx5Q",
"deployImmediately": true,
"expiresAt": "2024-01-15T10:30:00.000Z",
"scopes": {
"spendingLimit": {
"amount": "10",
"interval": 86400
},
"tokenLocator": "base-sepolia:usdc",
"type": "transfer"
}
}
'import requests
url = "https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers"
payload = {
"signer": "passkey:cWtP7gmZbd98HbKUuGXx5Q",
"approver": "passkey:cWtP7gmZbd98HbKUuGXx5Q",
"deployImmediately": True,
"expiresAt": "2024-01-15T10:30:00.000Z",
"scopes": {
"spendingLimit": {
"amount": "10",
"interval": 86400
},
"tokenLocator": "base-sepolia:usdc",
"type": "transfer"
}
}
headers = {
"X-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
signer: 'passkey:cWtP7gmZbd98HbKUuGXx5Q',
approver: 'passkey:cWtP7gmZbd98HbKUuGXx5Q',
deployImmediately: true,
expiresAt: '2024-01-15T10:30:00.000Z',
scopes: {
spendingLimit: {amount: '10', interval: 86400},
tokenLocator: 'base-sepolia:usdc',
type: 'transfer'
}
})
};
fetch('https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'signer' => 'passkey:cWtP7gmZbd98HbKUuGXx5Q',
'approver' => 'passkey:cWtP7gmZbd98HbKUuGXx5Q',
'deployImmediately' => true,
'expiresAt' => '2024-01-15T10:30:00.000Z',
'scopes' => [
'spendingLimit' => [
'amount' => '10',
'interval' => 86400
],
'tokenLocator' => 'base-sepolia:usdc',
'type' => 'transfer'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers"
payload := strings.NewReader("{\n \"signer\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"approver\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"deployImmediately\": true,\n \"expiresAt\": \"2024-01-15T10:30:00.000Z\",\n \"scopes\": {\n \"spendingLimit\": {\n \"amount\": \"10\",\n \"interval\": 86400\n },\n \"tokenLocator\": \"base-sepolia:usdc\",\n \"type\": \"transfer\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-KEY", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers")
.header("X-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"signer\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"approver\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"deployImmediately\": true,\n \"expiresAt\": \"2024-01-15T10:30:00.000Z\",\n \"scopes\": {\n \"spendingLimit\": {\n \"amount\": \"10\",\n \"interval\": 86400\n },\n \"tokenLocator\": \"base-sepolia:usdc\",\n \"type\": \"transfer\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"signer\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"approver\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"deployImmediately\": true,\n \"expiresAt\": \"2024-01-15T10:30:00.000Z\",\n \"scopes\": {\n \"spendingLimit\": {\n \"amount\": \"10\",\n \"interval\": 86400\n },\n \"tokenLocator\": \"base-sepolia:usdc\",\n \"type\": \"transfer\"\n }\n}"
response = http.request(request)
puts response.read_body{
"locator": "<string>",
"members": [
{
"address": "<string>",
"locator": "<string>",
"phone": "<string>",
"type": "phone"
}
],
"threshold": 4503599627370496,
"type": "quorum",
"expiresAt": 123,
"scopes": {
"spendingLimit": {
"amount": "100"
},
"tokenLocator": "stellar:usdc",
"type": "transfer"
},
"transaction": {
"chainType": "stellar",
"createdAt": 123,
"id": "<string>",
"onChain": {
"expiration": 123,
"transaction": {
"method": "<string>",
"tx": "<string>"
},
"explorerLink": "<string>",
"ledger": 123,
"proxiedTxId": "<string>",
"result": "<unknown>",
"txId": "<string>"
},
"status": "awaiting-approval",
"walletType": "smart",
"approvals": {
"pending": [
{
"quorumApprovals": {
"pending": [
{
"member": {
"address": "<string>",
"locator": "<string>",
"type": "api-key"
},
"message": "<string>"
}
],
"remaining": 123,
"submitted": [
{
"member": {
"address": "<string>",
"locator": "<string>",
"type": "api-key"
},
"message": "<string>",
"signature": "<string>",
"submittedAt": 123
}
],
"threshold": 123
},
"signer": {
"locator": "<string>",
"type": "quorum"
}
}
],
"submitted": [
{
"quorumApprovals": {
"pending": [
{
"member": {
"address": "<string>",
"locator": "<string>",
"type": "api-key"
},
"message": "<string>"
}
],
"remaining": 123,
"submitted": [
{
"member": {
"address": "<string>",
"locator": "<string>",
"type": "api-key"
},
"message": "<string>",
"signature": "<string>",
"submittedAt": 123
}
],
"threshold": 123
},
"signer": {
"locator": "<string>",
"type": "quorum"
}
}
],
"required": 123
},
"completedAt": 123,
"error": {
"message": "<string>",
"reason": "program_error",
"logs": "<unknown>",
"revertData": {}
},
"fees": {
"mode": "project",
"actual": "<unknown>",
"billed": {
"usd": 123
},
"billing": {
"status": "failed"
},
"estimate": "<unknown>"
},
"sendParams": {
"params": {
"recipient": "<string>",
"recipientAddress": "<string>",
"amount": "<string>"
},
"token": "<string>"
}
}
}{
"error": true,
"message": "<error message>",
"code": "DEVICE_SIGNER_NOT_SUPPORTED"
}{
"error": true,
"message": "<error message>",
"code": "DEVICE_SIGNER_NOT_SUPPORTED"
}Authorizations
API key required for authentication
Path Parameters
A wallet locator can be of the format:
<walletAddress>email:<email>:<chainType>[:<walletType>][:alias:<alias>](walletType defaults to 'smart')userId:<userId>:<chainType>[:<walletType>][:alias:<alias>](white label user example)phoneNumber:<phoneNumber>:<chainType>[:<walletType>][:alias:<alias>]twitter:<handle>:<chainType>[:<walletType>][:alias:<alias>]x:<handle>:<chainType>[:<walletType>][:alias:<alias>]me:<chainType>[:<walletType>][:alias:<alias>](Use when calling from the client side with a client API key)chainType[:<walletType>]:alias:<alias>
Body
- EVM
- Solana
- Stellar
Parameters for creating a EVM delegated signer
The chain where the signer will be registered
apechain, arbitrum, arbitrum-sepolia, arbitrumnova, arc, arc-testnet, avalanche, avalanche-fuji, base, base-sepolia, bsc, celo, celo-sepolia, curtis, ethereum, ethereum-sepolia, flow, flow-testnet, mantle, mantle-sepolia, optimism, optimism-sepolia, polygon, polygon-amoy, robinhood-chain, robinhood-chain-testnet, scroll, scroll-sepolia, sei-atlantic-2-testnet, sei-pacific-1, shape, story, story-testnet, tempo, tempo-testnet, zora, zora-sepolia A signer locator that can be either a of format '' for external wallet type signers or ':'
"passkey:cWtP7gmZbd98HbKUuGXx5Q"
The recovery method that authorizes this operation. Required when the wallet has multiple recovery methods.
"passkey:cWtP7gmZbd98HbKUuGXx5Q"
"api-key:123456789"
"external-wallet:0x1234567890123456789012345678901234567890"
"server:0x1234567890123456789012345678901234567890"
"email:test@example.com"
"phone:+1234567890"
"device:BIVmCqMz8QJB+se2kJEpGQ..."
"quorum:123e4567-e89b-12d3-a456-426614174000"
If true, returns a transaction to register the signer in the wallet. If false (default), it generates a signature and the signer will be registered on the following transaction.
The expiry date of the signer in ISO 8601 format
"2024-01-15T10:30:00.000Z"
Optional array of scopes to restrict the signer's capabilities
Show child attributes
Show child attributes
{
"spendingLimit": { "amount": "10", "interval": 86400 },
"tokenLocator": "base-sepolia:usdc",
"type": "transfer"
}
Response
The delegated signer has been successfully created.
- Stellar Delegated Signer Response
- Stellar Delegated Signer Response
- Stellar Delegated Signer Response
- Stellar Delegated Signer Response
- Stellar Delegated Signer Response
- Stellar Delegated Signer Response
- Stellar Delegated Signer Response
- Stellar Delegated Signer Response
- EVM Delegated Signer Response
- EVM Delegated Signer Response
- EVM Delegated Signer Response
- EVM Delegated Signer Response
- EVM Delegated Signer Response
- EVM Delegated Signer Response
- EVM Delegated Signer Response
- Solana Delegated Signer Response
- Solana Delegated Signer Response
- Solana Delegated Signer Response
- Solana Delegated Signer Response
- Solana Delegated Signer Response
- Solana Delegated Signer Response
- Solana Delegated Signer Response
Complete delegated signer response including the signer and authorization transaction
The quorum's locator, generated when it was added. Name it as signer to act as the quorum.
^quorum:[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$The member signers, each under its own locator
Configuration for a phone signer
- Phone Signer
- Server Signer
- Email Signer
- External Wallet Signer
- Passkey Signer
Show child attributes
Show child attributes
The number of member signatures required to approve
1 <= x <= 9007199254740991Identifier for quorum (multisig) signer type
"quorum"The expiry date of the signer in ISO 8601 format
Optional array of scopes restricting the signer's capabilities
Show child attributes
Show child attributes
{
"spendingLimit": { "amount": "100" },
"tokenLocator": "stellar:usdc",
"type": "transfer"
}
The transaction for the signer
Show child attributes
Show child attributes
Was this page helpful?

