cURL
curl --request POST \
--url https://grid.squads.xyz/api/grid/v1/accounts/{address}/proposals/{proposal_address}/vote-and-execute \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'x-grid-environment: <x-grid-environment>' \
--data '
{
"signers": [
"<string>"
],
"feeConfig": {
"payer_address": "<string>",
"self_managed_fees": true
}
}
'import requests
url = "https://grid.squads.xyz/api/grid/v1/accounts/{address}/proposals/{proposal_address}/vote-and-execute"
payload = {
"signers": ["<string>"],
"feeConfig": {
"payer_address": "<string>",
"self_managed_fees": True
}
}
headers = {
"x-grid-environment": "<x-grid-environment>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-grid-environment': '<x-grid-environment>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
signers: ['<string>'],
feeConfig: {payer_address: '<string>', self_managed_fees: true}
})
};
fetch('https://grid.squads.xyz/api/grid/v1/accounts/{address}/proposals/{proposal_address}/vote-and-execute', 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://grid.squads.xyz/api/grid/v1/accounts/{address}/proposals/{proposal_address}/vote-and-execute",
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([
'signers' => [
'<string>'
],
'feeConfig' => [
'payer_address' => '<string>',
'self_managed_fees' => true
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"x-grid-environment: <x-grid-environment>"
],
]);
$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://grid.squads.xyz/api/grid/v1/accounts/{address}/proposals/{proposal_address}/vote-and-execute"
payload := strings.NewReader("{\n \"signers\": [\n \"<string>\"\n ],\n \"feeConfig\": {\n \"payer_address\": \"<string>\",\n \"self_managed_fees\": true\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-grid-environment", "<x-grid-environment>")
req.Header.Add("Authorization", "Bearer <token>")
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://grid.squads.xyz/api/grid/v1/accounts/{address}/proposals/{proposal_address}/vote-and-execute")
.header("x-grid-environment", "<x-grid-environment>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"signers\": [\n \"<string>\"\n ],\n \"feeConfig\": {\n \"payer_address\": \"<string>\",\n \"self_managed_fees\": true\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://grid.squads.xyz/api/grid/v1/accounts/{address}/proposals/{proposal_address}/vote-and-execute")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-grid-environment"] = '<x-grid-environment>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"signers\": [\n \"<string>\"\n ],\n \"feeConfig\": {\n \"payer_address\": \"<string>\",\n \"self_managed_fees\": true\n }\n}"
response = http.request(request)
puts response.read_body{
"data": {
"signers": [
"<string>"
],
"transactions": [
"<string>"
]
},
"metadata": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z"
}
}Proposals
Vote and Execute
Vote to approve and immediately execute a proposal in one operation
POST
/
api
/
grid
/
v1
/
accounts
/
{address}
/
proposals
/
{proposal_address}
/
vote-and-execute
cURL
curl --request POST \
--url https://grid.squads.xyz/api/grid/v1/accounts/{address}/proposals/{proposal_address}/vote-and-execute \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'x-grid-environment: <x-grid-environment>' \
--data '
{
"signers": [
"<string>"
],
"feeConfig": {
"payer_address": "<string>",
"self_managed_fees": true
}
}
'import requests
url = "https://grid.squads.xyz/api/grid/v1/accounts/{address}/proposals/{proposal_address}/vote-and-execute"
payload = {
"signers": ["<string>"],
"feeConfig": {
"payer_address": "<string>",
"self_managed_fees": True
}
}
headers = {
"x-grid-environment": "<x-grid-environment>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-grid-environment': '<x-grid-environment>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
signers: ['<string>'],
feeConfig: {payer_address: '<string>', self_managed_fees: true}
})
};
fetch('https://grid.squads.xyz/api/grid/v1/accounts/{address}/proposals/{proposal_address}/vote-and-execute', 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://grid.squads.xyz/api/grid/v1/accounts/{address}/proposals/{proposal_address}/vote-and-execute",
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([
'signers' => [
'<string>'
],
'feeConfig' => [
'payer_address' => '<string>',
'self_managed_fees' => true
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"x-grid-environment: <x-grid-environment>"
],
]);
$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://grid.squads.xyz/api/grid/v1/accounts/{address}/proposals/{proposal_address}/vote-and-execute"
payload := strings.NewReader("{\n \"signers\": [\n \"<string>\"\n ],\n \"feeConfig\": {\n \"payer_address\": \"<string>\",\n \"self_managed_fees\": true\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-grid-environment", "<x-grid-environment>")
req.Header.Add("Authorization", "Bearer <token>")
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://grid.squads.xyz/api/grid/v1/accounts/{address}/proposals/{proposal_address}/vote-and-execute")
.header("x-grid-environment", "<x-grid-environment>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"signers\": [\n \"<string>\"\n ],\n \"feeConfig\": {\n \"payer_address\": \"<string>\",\n \"self_managed_fees\": true\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://grid.squads.xyz/api/grid/v1/accounts/{address}/proposals/{proposal_address}/vote-and-execute")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-grid-environment"] = '<x-grid-environment>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"signers\": [\n \"<string>\"\n ],\n \"feeConfig\": {\n \"payer_address\": \"<string>\",\n \"self_managed_fees\": true\n }\n}"
response = http.request(request)
puts response.read_body{
"data": {
"signers": [
"<string>"
],
"transactions": [
"<string>"
]
},
"metadata": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z"
}
}Combines voting and execution into a single operation. More efficient than separate vote and execute calls when you want to finalize a proposal immediately.
At least one signer must have
CAN_EXECUTE permission (mask includes value 4). Unlike the vote endpoint, this is required.How It Works
- Validates proposal is
ActiveorApproved - Filters signers who already approved
- Selects minimum signers needed to reach threshold
- First signer with
CAN_EXECUTEbecomes the executor - Returns transaction(s) for signing
When Threshold Is Already Met
If the proposal already has enough approvals, the voting step becomes a no-op—only execution occurs.
// Proposal has 2/2 approvals (Approved status)
const response = await grid.voteAndExecute(accountAddress, proposalAddress, {
signers: [executorKey] // Only needs CAN_EXECUTE
});
// Returns execute transaction only
Permission Requirements
- All signers need
CAN_VOTE(2) - At least one signer needs
CAN_EXECUTE(4)
Transaction Output
Returns 1-2 transactions depending on size:- Single transaction: Vote + execute fit within 1232 bytes
- Two transactions: Submit vote first, then execute
const response = await grid.voteAndExecute(accountAddress, proposalAddress, {
signers: [signerWithExecute],
fee_config: { currency: "SOL", payer_address: payerKey }
});
// Sign and submit in order
for (const tx of response.transactions) {
await signAndSubmit(tx);
}
When to Use Vote vs Vote-and-Execute
| Use Case | Endpoint |
|---|---|
| Approve and execute immediately | Vote-and-Execute |
| Approve without executing | Vote |
| Reject or cancel | Vote |
| No CAN_EXECUTE signer available | Vote |
Related Endpoints
- Vote on Proposal — Vote without executing
- Get Proposal — Check current state
Authorizations
Your Grid API key from the Grid Dashboard
Headers
Target Solana environment
Path Parameters
Smart account address (Solana public key)
Proposal address (Solana public key)
Was this page helpful?
⌘I