curl --request POST \
--url https://staging.crossmint.com/api/2025-06-09/wallets/{walletLocator}/signers \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <x-api-key>' \
--data '
{
"signer": "passkey:cWtP7gmZbd98HbKUuGXx5Q",
"approver": "passkey:cWtP7gmZbd98HbKUuGXx5Q",
"deployImmediately": true,
"expiresAt": "2023-11-07T05:31:56Z",
"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": "2023-11-07T05:31:56Z",
"scopes": {
"spendingLimit": {
"amount": "10",
"interval": 86400
},
"tokenLocator": "base-sepolia:usdc",
"type": "transfer"
}
}
headers = {
"X-API-KEY": "<x-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': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
signer: 'passkey:cWtP7gmZbd98HbKUuGXx5Q',
approver: 'passkey:cWtP7gmZbd98HbKUuGXx5Q',
deployImmediately: true,
expiresAt: '2023-11-07T05:31:56Z',
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' => '2023-11-07T05:31:56Z',
'scopes' => [
'spendingLimit' => [
'amount' => '10',
'interval' => 86400
],
'tokenLocator' => 'base-sepolia:usdc',
'type' => 'transfer'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-KEY: <x-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\": \"2023-11-07T05:31:56Z\",\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", "<x-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", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"signer\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"approver\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"deployImmediately\": true,\n \"expiresAt\": \"2023-11-07T05:31:56Z\",\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"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"signer\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"approver\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"deployImmediately\": true,\n \"expiresAt\": \"2023-11-07T05:31:56Z\",\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{
"address": "<string>",
"locator": "<string>",
"type": "api-key",
"chains": {},
"expiresAt": 123,
"scopes": {
"spendingLimit": {
"amount": "10",
"interval": 86400
},
"tokenLocator": "base-sepolia:usdc",
"type": "transfer"
}
}{
"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: <x-api-key>' \
--data '
{
"signer": "passkey:cWtP7gmZbd98HbKUuGXx5Q",
"approver": "passkey:cWtP7gmZbd98HbKUuGXx5Q",
"deployImmediately": true,
"expiresAt": "2023-11-07T05:31:56Z",
"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": "2023-11-07T05:31:56Z",
"scopes": {
"spendingLimit": {
"amount": "10",
"interval": 86400
},
"tokenLocator": "base-sepolia:usdc",
"type": "transfer"
}
}
headers = {
"X-API-KEY": "<x-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': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
signer: 'passkey:cWtP7gmZbd98HbKUuGXx5Q',
approver: 'passkey:cWtP7gmZbd98HbKUuGXx5Q',
deployImmediately: true,
expiresAt: '2023-11-07T05:31:56Z',
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' => '2023-11-07T05:31:56Z',
'scopes' => [
'spendingLimit' => [
'amount' => '10',
'interval' => 86400
],
'tokenLocator' => 'base-sepolia:usdc',
'type' => 'transfer'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-KEY: <x-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\": \"2023-11-07T05:31:56Z\",\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", "<x-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", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"signer\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"approver\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"deployImmediately\": true,\n \"expiresAt\": \"2023-11-07T05:31:56Z\",\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"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"signer\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"approver\": \"passkey:cWtP7gmZbd98HbKUuGXx5Q\",\n \"deployImmediately\": true,\n \"expiresAt\": \"2023-11-07T05:31:56Z\",\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{
"address": "<string>",
"locator": "<string>",
"type": "api-key",
"chains": {},
"expiresAt": 123,
"scopes": {
"spendingLimit": {
"amount": "10",
"interval": 86400
},
"tokenLocator": "base-sepolia:usdc",
"type": "transfer"
}
}{
"error": true,
"message": "<error message>",
"code": "DEVICE_SIGNER_NOT_SUPPORTED"
}{
"error": true,
"message": "<error message>",
"code": "DEVICE_SIGNER_NOT_SUPPORTED"
}Headers
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
abstract, abstract-testnet, apechain, arbitrum, arbitrum-sepolia, arbitrumnova, arc-testnet, avalanche, avalanche-fuji, base, base-sepolia, bsc, curtis, ethereum, ethereum-sepolia, flow, flow-testnet, mantle, mantle-sepolia, mode, mode-sepolia, optimism, optimism-sepolia, plume, plume-testnet, polygon, polygon-amoy, scroll, scroll-sepolia, sei-atlantic-2-testnet, sei-pacific-1, shape, story, story-testnet, tempo, tempo-testnet, world-chain, world-chain-sepolia, zora, zora-sepolia A signer locator that can be either a of format '' for external wallet type signers or ':'
"passkey:cWtP7gmZbd98HbKUuGXx5Q"
The recovery signer that authorizes this operation. Required when the wallet has multiple recovery signers.
"passkey:cWtP7gmZbd98HbKUuGXx5Q"
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
^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$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.
- 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
- 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
Complete delegated signer response including the signer and authorizations for each chain
The blockchain address of the custodial signer
The locator of the signer
Identifier for API key signer type
api-key Authorization for each chain, keyed by chain name. The value is either a signature request (signature flow) or an on-chain registration transaction (deployImmediately flow).
Show child attributes
Show child attributes
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": "10", "interval": 86400 },
"tokenLocator": "base-sepolia:usdc",
"type": "transfer"
}
Was this page helpful?

