curl --request POST \
--url https://api.vollna.com/v1/proposal-templates \
--header 'Content-Type: application/json' \
--header 'X-API-TOKEN: <api-key>' \
--data '
{
"name": "Web development",
"sender": {
"organization_id": 15,
"contractor_uid": "contractor_abc123"
},
"hourly_rate": {
"rate": 501,
"smart_rate_min": 501,
"smart_rate_max": 501,
"smart_rate_percent": 50,
"increase_percent": 1
},
"ai": {
"model": "gemini-3.6-flash",
"instructions": "Write like a human",
"client_questions": "<string>",
"additional_context": "<string>",
"template_structure": true
},
"fixed_price": {
"price": 500002.5,
"min_price": 500002.5,
"client_budget_percent": 500
},
"ab_testing": true,
"answers": [
{
"question": "Availability?",
"answer": "Full time"
}
],
"cover_letters": {
"variant_a": "<string>",
"variant_b": "<string>"
}
}
'import requests
url = "https://api.vollna.com/v1/proposal-templates"
payload = {
"name": "Web development",
"sender": {
"organization_id": 15,
"contractor_uid": "contractor_abc123"
},
"hourly_rate": {
"rate": 501,
"smart_rate_min": 501,
"smart_rate_max": 501,
"smart_rate_percent": 50,
"increase_percent": 1
},
"ai": {
"model": "gemini-3.6-flash",
"instructions": "Write like a human",
"client_questions": "<string>",
"additional_context": "<string>",
"template_structure": True
},
"fixed_price": {
"price": 500002.5,
"min_price": 500002.5,
"client_budget_percent": 500
},
"ab_testing": True,
"answers": [
{
"question": "Availability?",
"answer": "Full time"
}
],
"cover_letters": {
"variant_a": "<string>",
"variant_b": "<string>"
}
}
headers = {
"X-API-TOKEN": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-TOKEN': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Web development',
sender: {organization_id: 15, contractor_uid: 'contractor_abc123'},
hourly_rate: {
rate: 501,
smart_rate_min: 501,
smart_rate_max: 501,
smart_rate_percent: 50,
increase_percent: 1
},
ai: {
model: 'gemini-3.6-flash',
instructions: 'Write like a human',
client_questions: '<string>',
additional_context: '<string>',
template_structure: true
},
fixed_price: {price: 500002.5, min_price: 500002.5, client_budget_percent: 500},
ab_testing: true,
answers: [{question: 'Availability?', answer: 'Full time'}],
cover_letters: {variant_a: '<string>', variant_b: '<string>'}
})
};
fetch('https://api.vollna.com/v1/proposal-templates', 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.vollna.com/v1/proposal-templates",
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([
'name' => 'Web development',
'sender' => [
'organization_id' => 15,
'contractor_uid' => 'contractor_abc123'
],
'hourly_rate' => [
'rate' => 501,
'smart_rate_min' => 501,
'smart_rate_max' => 501,
'smart_rate_percent' => 50,
'increase_percent' => 1
],
'ai' => [
'model' => 'gemini-3.6-flash',
'instructions' => 'Write like a human',
'client_questions' => '<string>',
'additional_context' => '<string>',
'template_structure' => true
],
'fixed_price' => [
'price' => 500002.5,
'min_price' => 500002.5,
'client_budget_percent' => 500
],
'ab_testing' => true,
'answers' => [
[
'question' => 'Availability?',
'answer' => 'Full time'
]
],
'cover_letters' => [
'variant_a' => '<string>',
'variant_b' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-TOKEN: <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.vollna.com/v1/proposal-templates"
payload := strings.NewReader("{\n \"name\": \"Web development\",\n \"sender\": {\n \"organization_id\": 15,\n \"contractor_uid\": \"contractor_abc123\"\n },\n \"hourly_rate\": {\n \"rate\": 501,\n \"smart_rate_min\": 501,\n \"smart_rate_max\": 501,\n \"smart_rate_percent\": 50,\n \"increase_percent\": 1\n },\n \"ai\": {\n \"model\": \"gemini-3.6-flash\",\n \"instructions\": \"Write like a human\",\n \"client_questions\": \"<string>\",\n \"additional_context\": \"<string>\",\n \"template_structure\": true\n },\n \"fixed_price\": {\n \"price\": 500002.5,\n \"min_price\": 500002.5,\n \"client_budget_percent\": 500\n },\n \"ab_testing\": true,\n \"answers\": [\n {\n \"question\": \"Availability?\",\n \"answer\": \"Full time\"\n }\n ],\n \"cover_letters\": {\n \"variant_a\": \"<string>\",\n \"variant_b\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-TOKEN", "<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.vollna.com/v1/proposal-templates")
.header("X-API-TOKEN", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Web development\",\n \"sender\": {\n \"organization_id\": 15,\n \"contractor_uid\": \"contractor_abc123\"\n },\n \"hourly_rate\": {\n \"rate\": 501,\n \"smart_rate_min\": 501,\n \"smart_rate_max\": 501,\n \"smart_rate_percent\": 50,\n \"increase_percent\": 1\n },\n \"ai\": {\n \"model\": \"gemini-3.6-flash\",\n \"instructions\": \"Write like a human\",\n \"client_questions\": \"<string>\",\n \"additional_context\": \"<string>\",\n \"template_structure\": true\n },\n \"fixed_price\": {\n \"price\": 500002.5,\n \"min_price\": 500002.5,\n \"client_budget_percent\": 500\n },\n \"ab_testing\": true,\n \"answers\": [\n {\n \"question\": \"Availability?\",\n \"answer\": \"Full time\"\n }\n ],\n \"cover_letters\": {\n \"variant_a\": \"<string>\",\n \"variant_b\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vollna.com/v1/proposal-templates")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-TOKEN"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Web development\",\n \"sender\": {\n \"organization_id\": 15,\n \"contractor_uid\": \"contractor_abc123\"\n },\n \"hourly_rate\": {\n \"rate\": 501,\n \"smart_rate_min\": 501,\n \"smart_rate_max\": 501,\n \"smart_rate_percent\": 50,\n \"increase_percent\": 1\n },\n \"ai\": {\n \"model\": \"gemini-3.6-flash\",\n \"instructions\": \"Write like a human\",\n \"client_questions\": \"<string>\",\n \"additional_context\": \"<string>\",\n \"template_structure\": true\n },\n \"fixed_price\": {\n \"price\": 500002.5,\n \"min_price\": 500002.5,\n \"client_budget_percent\": 500\n },\n \"ab_testing\": true,\n \"answers\": [\n {\n \"question\": \"Availability?\",\n \"answer\": \"Full time\"\n }\n ],\n \"cover_letters\": {\n \"variant_a\": \"<string>\",\n \"variant_b\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": 123,
"name": "Web development",
"visibility": "shared_admins",
"sender": {
"name": "John Smith",
"type": "agency",
"organization": "Acme Agency LLC"
},
"hourly_rate": {
"mode": "smart",
"rate": 50,
"smart_rate_min": 25,
"smart_rate_max": 120,
"smart_rate_percent": 98,
"rules_count": 0,
"increase_percent": null,
"increase_frequency": "never"
},
"fixed_price": {
"type": "by-job-terms",
"price": 123,
"min_price": 123,
"client_budget_percent": 123
},
"ai": {
"model": "gemini-3.6-flash",
"instructions": "Write like a human",
"client_questions": "Answer briefly",
"additional_context": "<string>",
"template_structure": true
},
"filters": [
{
"id": 123,
"name": "<string>"
}
],
"auto_bidding_setups": [
{
"id": 123,
"name": "<string>"
}
],
"ab_testing": true,
"answers": [
{
"question": "Availability?",
"answer": "Full time",
"match_type": "exact"
}
],
"attachments": [
{
"uid": "9f1c2ab34de56f7890ab12cd34ef56ab",
"name": "portfolio.pdf",
"mime_type": "application/pdf",
"size_bytes": 245760
}
],
"cover_letters": {
"variant_a": "Hi, I build web apps with Symfony and React...",
"variant_b": "<string>"
},
"created_at": "2026-08-26T10:00:00+00:00",
"updated_at": "2026-08-26T10:00:00+00:00"
}
}{
"error": "Validation failed",
"fields": {
"hourly_rate.rate": "must be a number between 3 and 999",
"ai.model": "unknown model"
}
}{
"error": "<string>"
}Create proposal template
Creates a template with the dashboard defaults. Required: name, sender (from GET /proposal-senders), hourly_rate.rate and ai.instructions. All other update fields are accepted
curl --request POST \
--url https://api.vollna.com/v1/proposal-templates \
--header 'Content-Type: application/json' \
--header 'X-API-TOKEN: <api-key>' \
--data '
{
"name": "Web development",
"sender": {
"organization_id": 15,
"contractor_uid": "contractor_abc123"
},
"hourly_rate": {
"rate": 501,
"smart_rate_min": 501,
"smart_rate_max": 501,
"smart_rate_percent": 50,
"increase_percent": 1
},
"ai": {
"model": "gemini-3.6-flash",
"instructions": "Write like a human",
"client_questions": "<string>",
"additional_context": "<string>",
"template_structure": true
},
"fixed_price": {
"price": 500002.5,
"min_price": 500002.5,
"client_budget_percent": 500
},
"ab_testing": true,
"answers": [
{
"question": "Availability?",
"answer": "Full time"
}
],
"cover_letters": {
"variant_a": "<string>",
"variant_b": "<string>"
}
}
'import requests
url = "https://api.vollna.com/v1/proposal-templates"
payload = {
"name": "Web development",
"sender": {
"organization_id": 15,
"contractor_uid": "contractor_abc123"
},
"hourly_rate": {
"rate": 501,
"smart_rate_min": 501,
"smart_rate_max": 501,
"smart_rate_percent": 50,
"increase_percent": 1
},
"ai": {
"model": "gemini-3.6-flash",
"instructions": "Write like a human",
"client_questions": "<string>",
"additional_context": "<string>",
"template_structure": True
},
"fixed_price": {
"price": 500002.5,
"min_price": 500002.5,
"client_budget_percent": 500
},
"ab_testing": True,
"answers": [
{
"question": "Availability?",
"answer": "Full time"
}
],
"cover_letters": {
"variant_a": "<string>",
"variant_b": "<string>"
}
}
headers = {
"X-API-TOKEN": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-TOKEN': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Web development',
sender: {organization_id: 15, contractor_uid: 'contractor_abc123'},
hourly_rate: {
rate: 501,
smart_rate_min: 501,
smart_rate_max: 501,
smart_rate_percent: 50,
increase_percent: 1
},
ai: {
model: 'gemini-3.6-flash',
instructions: 'Write like a human',
client_questions: '<string>',
additional_context: '<string>',
template_structure: true
},
fixed_price: {price: 500002.5, min_price: 500002.5, client_budget_percent: 500},
ab_testing: true,
answers: [{question: 'Availability?', answer: 'Full time'}],
cover_letters: {variant_a: '<string>', variant_b: '<string>'}
})
};
fetch('https://api.vollna.com/v1/proposal-templates', 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.vollna.com/v1/proposal-templates",
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([
'name' => 'Web development',
'sender' => [
'organization_id' => 15,
'contractor_uid' => 'contractor_abc123'
],
'hourly_rate' => [
'rate' => 501,
'smart_rate_min' => 501,
'smart_rate_max' => 501,
'smart_rate_percent' => 50,
'increase_percent' => 1
],
'ai' => [
'model' => 'gemini-3.6-flash',
'instructions' => 'Write like a human',
'client_questions' => '<string>',
'additional_context' => '<string>',
'template_structure' => true
],
'fixed_price' => [
'price' => 500002.5,
'min_price' => 500002.5,
'client_budget_percent' => 500
],
'ab_testing' => true,
'answers' => [
[
'question' => 'Availability?',
'answer' => 'Full time'
]
],
'cover_letters' => [
'variant_a' => '<string>',
'variant_b' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-TOKEN: <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.vollna.com/v1/proposal-templates"
payload := strings.NewReader("{\n \"name\": \"Web development\",\n \"sender\": {\n \"organization_id\": 15,\n \"contractor_uid\": \"contractor_abc123\"\n },\n \"hourly_rate\": {\n \"rate\": 501,\n \"smart_rate_min\": 501,\n \"smart_rate_max\": 501,\n \"smart_rate_percent\": 50,\n \"increase_percent\": 1\n },\n \"ai\": {\n \"model\": \"gemini-3.6-flash\",\n \"instructions\": \"Write like a human\",\n \"client_questions\": \"<string>\",\n \"additional_context\": \"<string>\",\n \"template_structure\": true\n },\n \"fixed_price\": {\n \"price\": 500002.5,\n \"min_price\": 500002.5,\n \"client_budget_percent\": 500\n },\n \"ab_testing\": true,\n \"answers\": [\n {\n \"question\": \"Availability?\",\n \"answer\": \"Full time\"\n }\n ],\n \"cover_letters\": {\n \"variant_a\": \"<string>\",\n \"variant_b\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-TOKEN", "<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.vollna.com/v1/proposal-templates")
.header("X-API-TOKEN", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Web development\",\n \"sender\": {\n \"organization_id\": 15,\n \"contractor_uid\": \"contractor_abc123\"\n },\n \"hourly_rate\": {\n \"rate\": 501,\n \"smart_rate_min\": 501,\n \"smart_rate_max\": 501,\n \"smart_rate_percent\": 50,\n \"increase_percent\": 1\n },\n \"ai\": {\n \"model\": \"gemini-3.6-flash\",\n \"instructions\": \"Write like a human\",\n \"client_questions\": \"<string>\",\n \"additional_context\": \"<string>\",\n \"template_structure\": true\n },\n \"fixed_price\": {\n \"price\": 500002.5,\n \"min_price\": 500002.5,\n \"client_budget_percent\": 500\n },\n \"ab_testing\": true,\n \"answers\": [\n {\n \"question\": \"Availability?\",\n \"answer\": \"Full time\"\n }\n ],\n \"cover_letters\": {\n \"variant_a\": \"<string>\",\n \"variant_b\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vollna.com/v1/proposal-templates")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-TOKEN"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Web development\",\n \"sender\": {\n \"organization_id\": 15,\n \"contractor_uid\": \"contractor_abc123\"\n },\n \"hourly_rate\": {\n \"rate\": 501,\n \"smart_rate_min\": 501,\n \"smart_rate_max\": 501,\n \"smart_rate_percent\": 50,\n \"increase_percent\": 1\n },\n \"ai\": {\n \"model\": \"gemini-3.6-flash\",\n \"instructions\": \"Write like a human\",\n \"client_questions\": \"<string>\",\n \"additional_context\": \"<string>\",\n \"template_structure\": true\n },\n \"fixed_price\": {\n \"price\": 500002.5,\n \"min_price\": 500002.5,\n \"client_budget_percent\": 500\n },\n \"ab_testing\": true,\n \"answers\": [\n {\n \"question\": \"Availability?\",\n \"answer\": \"Full time\"\n }\n ],\n \"cover_letters\": {\n \"variant_a\": \"<string>\",\n \"variant_b\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": 123,
"name": "Web development",
"visibility": "shared_admins",
"sender": {
"name": "John Smith",
"type": "agency",
"organization": "Acme Agency LLC"
},
"hourly_rate": {
"mode": "smart",
"rate": 50,
"smart_rate_min": 25,
"smart_rate_max": 120,
"smart_rate_percent": 98,
"rules_count": 0,
"increase_percent": null,
"increase_frequency": "never"
},
"fixed_price": {
"type": "by-job-terms",
"price": 123,
"min_price": 123,
"client_budget_percent": 123
},
"ai": {
"model": "gemini-3.6-flash",
"instructions": "Write like a human",
"client_questions": "Answer briefly",
"additional_context": "<string>",
"template_structure": true
},
"filters": [
{
"id": 123,
"name": "<string>"
}
],
"auto_bidding_setups": [
{
"id": 123,
"name": "<string>"
}
],
"ab_testing": true,
"answers": [
{
"question": "Availability?",
"answer": "Full time",
"match_type": "exact"
}
],
"attachments": [
{
"uid": "9f1c2ab34de56f7890ab12cd34ef56ab",
"name": "portfolio.pdf",
"mime_type": "application/pdf",
"size_bytes": 245760
}
],
"cover_letters": {
"variant_a": "Hi, I build web apps with Symfony and React...",
"variant_b": "<string>"
},
"created_at": "2026-08-26T10:00:00+00:00",
"updated_at": "2026-08-26T10:00:00+00:00"
}
}{
"error": "Validation failed",
"fields": {
"hourly_rate.rate": "must be a number between 3 and 999",
"ai.model": "unknown model"
}
}{
"error": "<string>"
}Authorizations
API token for authentication
Body
Required on create: name, sender, hourly_rate.rate and ai.instructions. Everything else falls back to the dashboard defaults (visibility shared_admins, fixed price by job terms, A/B testing off)
Non-empty; null not allowed
255"Web development"
Assign who bids with this template, from GET /proposal-senders. contractor_uid is required for agencies and not allowed for freelancer profiles. Switching an agency template to a freelancer sender makes it ineligible for auto-bidding
Show child attributes
Show child attributes
Partial update of the hourly rate block
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Replaces the whole list
50Show child attributes
Show child attributes
Partial update of the A/B slots
Show child attributes
Show child attributes
The API token acts with team admin rights; private is not available through the API
shared_view, shared_edit, shared_admins Response
Template created; returns the same shape as GET /proposal-templates/{id}
Show child attributes
Show child attributes
Was this page helpful?