Sign and broadcast with a customer Solana wallet
curl --request POST \
--url https://api-production.fossapay.com/api/v1/wallets/crypto/customer/{customerId}/transactions/sign-and-broadcast \
--header 'Content-Type: application/json' \
--header 'X-Idempotency-Key: <x-idempotency-key>' \
--header 'x-api-key: <api-key>' \
--data '
{
"serializedTransaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB..."
}
'import requests
url = "https://api-production.fossapay.com/api/v1/wallets/crypto/customer/{customerId}/transactions/sign-and-broadcast"
payload = { "serializedTransaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB..." }
headers = {
"X-Idempotency-Key": "<x-idempotency-key>",
"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-Idempotency-Key': '<x-idempotency-key>',
'x-api-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
serializedTransaction: 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB...'
})
};
fetch('https://api-production.fossapay.com/api/v1/wallets/crypto/customer/{customerId}/transactions/sign-and-broadcast', 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://api-production.fossapay.com/api/v1/wallets/crypto/customer/{customerId}/transactions/sign-and-broadcast",
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([
'serializedTransaction' => 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB...'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Idempotency-Key: <x-idempotency-key>",
"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://api-production.fossapay.com/api/v1/wallets/crypto/customer/{customerId}/transactions/sign-and-broadcast"
payload := strings.NewReader("{\n \"serializedTransaction\": \"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB...\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Idempotency-Key", "<x-idempotency-key>")
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://api-production.fossapay.com/api/v1/wallets/crypto/customer/{customerId}/transactions/sign-and-broadcast")
.header("X-Idempotency-Key", "<x-idempotency-key>")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"serializedTransaction\": \"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB...\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-production.fossapay.com/api/v1/wallets/crypto/customer/{customerId}/transactions/sign-and-broadcast")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Idempotency-Key"] = '<x-idempotency-key>'
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"serializedTransaction\": \"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB...\"\n}"
response = http.request(request)
puts response.read_body{
"status": "success",
"statusCode": 202,
"message": "Solana transaction signed and submitted successfully",
"data": {
"requestId": "07836944-c8fd-444b-b080-776077fc70c9",
"walletType": "customer",
"customerId": "11111111-1111-4111-8111-111111111111",
"walletId": "61237ceb-bde6-4052-9294-38470806f672",
"walletAddress": "8aQ3Y97fxiX26Pe2ckc3keoQEz5MtWBCVk4pEx96Sqeb",
"network": "solana",
"cluster": "mainnet-beta",
"feePayer": "8aQ3Y97fxiX26Pe2ckc3keoQEz5MtWBCVk4pEx96Sqeb",
"status": "submitted",
"providerTransactionId": "8f9e6478-6ba7-462d-b53a-ec09d9f3a8c9",
"transactionHash": "3cQYpNzFfDm6BkLwgGz4JPQCYGmS7SxTpKRtvBPWVPSLDjpGJBrUojwt7FA97Cn4vdHXgyxL4G2LQ1HsBYVkKb9U",
"explorerLink": "https://explorer.solana.com/tx/3cQYpNzFfDm6BkLwgGz4JPQCYGmS7SxTpKRtvBPWVPSLDjpGJBrUojwt7FA97Cn4vdHXgyxL4G2LQ1HsBYVkKb9U",
"simulation": {
"unitsConsumed": 21192,
"logs": ["Program MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr success"]
}
}
}
Crypto Wallets
Sign a Customer Wallet Transaction
Validate, simulate, sign, and broadcast a Solana transaction with a customer wallet
POST
/
api
/
v1
/
wallets
/
crypto
/
customer
/
{customerId}
/
transactions
/
sign-and-broadcast
Sign and broadcast with a customer Solana wallet
curl --request POST \
--url https://api-production.fossapay.com/api/v1/wallets/crypto/customer/{customerId}/transactions/sign-and-broadcast \
--header 'Content-Type: application/json' \
--header 'X-Idempotency-Key: <x-idempotency-key>' \
--header 'x-api-key: <api-key>' \
--data '
{
"serializedTransaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB..."
}
'import requests
url = "https://api-production.fossapay.com/api/v1/wallets/crypto/customer/{customerId}/transactions/sign-and-broadcast"
payload = { "serializedTransaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB..." }
headers = {
"X-Idempotency-Key": "<x-idempotency-key>",
"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-Idempotency-Key': '<x-idempotency-key>',
'x-api-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
serializedTransaction: 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB...'
})
};
fetch('https://api-production.fossapay.com/api/v1/wallets/crypto/customer/{customerId}/transactions/sign-and-broadcast', 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://api-production.fossapay.com/api/v1/wallets/crypto/customer/{customerId}/transactions/sign-and-broadcast",
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([
'serializedTransaction' => 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB...'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Idempotency-Key: <x-idempotency-key>",
"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://api-production.fossapay.com/api/v1/wallets/crypto/customer/{customerId}/transactions/sign-and-broadcast"
payload := strings.NewReader("{\n \"serializedTransaction\": \"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB...\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Idempotency-Key", "<x-idempotency-key>")
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://api-production.fossapay.com/api/v1/wallets/crypto/customer/{customerId}/transactions/sign-and-broadcast")
.header("X-Idempotency-Key", "<x-idempotency-key>")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"serializedTransaction\": \"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB...\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-production.fossapay.com/api/v1/wallets/crypto/customer/{customerId}/transactions/sign-and-broadcast")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Idempotency-Key"] = '<x-idempotency-key>'
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"serializedTransaction\": \"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB...\"\n}"
response = http.request(request)
puts response.read_body{
"status": "success",
"statusCode": 202,
"message": "Solana transaction signed and submitted successfully",
"data": {
"requestId": "07836944-c8fd-444b-b080-776077fc70c9",
"walletType": "customer",
"customerId": "11111111-1111-4111-8111-111111111111",
"walletId": "61237ceb-bde6-4052-9294-38470806f672",
"walletAddress": "8aQ3Y97fxiX26Pe2ckc3keoQEz5MtWBCVk4pEx96Sqeb",
"network": "solana",
"cluster": "mainnet-beta",
"feePayer": "8aQ3Y97fxiX26Pe2ckc3keoQEz5MtWBCVk4pEx96Sqeb",
"status": "submitted",
"providerTransactionId": "8f9e6478-6ba7-462d-b53a-ec09d9f3a8c9",
"transactionHash": "3cQYpNzFfDm6BkLwgGz4JPQCYGmS7SxTpKRtvBPWVPSLDjpGJBrUojwt7FA97Cn4vdHXgyxL4G2LQ1HsBYVkKb9U",
"explorerLink": "https://explorer.solana.com/tx/3cQYpNzFfDm6BkLwgGz4JPQCYGmS7SxTpKRtvBPWVPSLDjpGJBrUojwt7FA97Cn4vdHXgyxL4G2LQ1HsBYVkKb9U",
"simulation": {
"unitsConsumed": 21192,
"logs": ["Program MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr success"]
}
}
}
The customer and active Solana wallet must belong to the merchant resolved from the API key. The customer wallet must be both a required signer and the fee payer. A successful
202 response means the transaction was submitted, not finalized.
Path parameter
string
required
FossaPay UUID of the individual customer whose wallet will sign and fund the transaction.
Headers
string
required
Active production API key belonging to the customer’s merchant.
string
required
Unique key for this logical signing request, up to 255 characters. Retain it with the exact serialized transaction.
Request body
string
required
Base64-encoded serialized Solana
VersionedTransaction, up to 4,096 characters. The selected customer wallet must be the fee payer and a required signer. Other required signers must sign before serialization.curl --request POST \
--url https://api-production.fossapay.com/api/v1/wallets/crypto/customer/11111111-1111-4111-8111-111111111111/transactions/sign-and-broadcast \
--header "x-api-key: $FOSSAPAY_API_KEY" \
--header "X-Idempotency-Key: $IDEMPOTENCY_KEY" \
--header 'Content-Type: application/json' \
--data "{\"serializedTransaction\":\"$SERIALIZED_TRANSACTION\"}"
Response
{
"status": "success",
"statusCode": 202,
"message": "Solana transaction signed and submitted successfully",
"data": {
"requestId": "07836944-c8fd-444b-b080-776077fc70c9",
"walletType": "customer",
"customerId": "11111111-1111-4111-8111-111111111111",
"walletId": "61237ceb-bde6-4052-9294-38470806f672",
"walletAddress": "8aQ3Y97fxiX26Pe2ckc3keoQEz5MtWBCVk4pEx96Sqeb",
"network": "solana",
"cluster": "mainnet-beta",
"feePayer": "8aQ3Y97fxiX26Pe2ckc3keoQEz5MtWBCVk4pEx96Sqeb",
"status": "submitted",
"providerTransactionId": "8f9e6478-6ba7-462d-b53a-ec09d9f3a8c9",
"transactionHash": "3cQYpNzFfDm6BkLwgGz4JPQCYGmS7SxTpKRtvBPWVPSLDjpGJBrUojwt7FA97Cn4vdHXgyxL4G2LQ1HsBYVkKb9U",
"explorerLink": "https://explorer.solana.com/tx/3cQYpNzFfDm6BkLwgGz4JPQCYGmS7SxTpKRtvBPWVPSLDjpGJBrUojwt7FA97Cn4vdHXgyxL4G2LQ1HsBYVkKb9U",
"simulation": {
"unitsConsumed": 21192,
"logs": ["Program MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr success"]
}
}
}
Important behavior
- FossaPay verifies customer ownership before accessing the wallet.
- FossaPay simulates before signing and broadcasting.
- The selected customer wallet pays the Solana network fee.
- Requests are limited to 10 per minute.
- Repeating the identical submitted request with the same idempotency key returns the stored result.
- A failed or expired transaction must be rebuilt with a fresh blockhash and submitted with a new key.
- Finality is reconciled through Solana RPC; this flow does not emit a merchant webhook.
Authorizations
Headers
Unique merchant-scoped key for this exact signing request. Maximum 255 characters.
Required string length:
1 - 255Path Parameters
FossaPay customer UUID owned by the authenticated merchant.
Body
application/json
Base64-encoded serialized Solana VersionedTransaction. The selected FossaPay wallet must be a required signer and the fee payer; all other required signers must already have signed.
Required string length:
1 - 4096Example:
"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAB..."

