curl --request POST \
--url https://api.sumvin.com/v0/budgets/ \
--header 'Content-Type: application/json' \
--header 'x-juno-jwt: <api-key>' \
--data '
{
"budget_type": "custom",
"category_name": "Travel",
"currency": "GBP",
"limit_amount": "2000.00",
"name": "Sabbatical Travel",
"original_request": "Budget £2000 for travel over the next 3 months",
"period": {
"kind": "relative",
"length": 3,
"unit": "months"
}
}
'import requests
url = "https://api.sumvin.com/v0/budgets/"
payload = {
"budget_type": "custom",
"category_name": "Travel",
"currency": "GBP",
"limit_amount": "2000.00",
"name": "Sabbatical Travel",
"original_request": "Budget £2000 for travel over the next 3 months",
"period": {
"kind": "relative",
"length": 3,
"unit": "months"
}
}
headers = {
"x-juno-jwt": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-juno-jwt': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
budget_type: 'custom',
category_name: 'Travel',
currency: 'GBP',
limit_amount: '2000.00',
name: 'Sabbatical Travel',
original_request: 'Budget £2000 for travel over the next 3 months',
period: {kind: 'relative', length: 3, unit: 'months'}
})
};
fetch('https://api.sumvin.com/v0/budgets/', 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.sumvin.com/v0/budgets/",
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([
'budget_type' => 'custom',
'category_name' => 'Travel',
'currency' => 'GBP',
'limit_amount' => '2000.00',
'name' => 'Sabbatical Travel',
'original_request' => 'Budget £2000 for travel over the next 3 months',
'period' => [
'kind' => 'relative',
'length' => 3,
'unit' => 'months'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-juno-jwt: <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.sumvin.com/v0/budgets/"
payload := strings.NewReader("{\n \"budget_type\": \"custom\",\n \"category_name\": \"Travel\",\n \"currency\": \"GBP\",\n \"limit_amount\": \"2000.00\",\n \"name\": \"Sabbatical Travel\",\n \"original_request\": \"Budget £2000 for travel over the next 3 months\",\n \"period\": {\n \"kind\": \"relative\",\n \"length\": 3,\n \"unit\": \"months\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-juno-jwt", "<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.sumvin.com/v0/budgets/")
.header("x-juno-jwt", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"budget_type\": \"custom\",\n \"category_name\": \"Travel\",\n \"currency\": \"GBP\",\n \"limit_amount\": \"2000.00\",\n \"name\": \"Sabbatical Travel\",\n \"original_request\": \"Budget £2000 for travel over the next 3 months\",\n \"period\": {\n \"kind\": \"relative\",\n \"length\": 3,\n \"unit\": \"months\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sumvin.com/v0/budgets/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-juno-jwt"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"budget_type\": \"custom\",\n \"category_name\": \"Travel\",\n \"currency\": \"GBP\",\n \"limit_amount\": \"2000.00\",\n \"name\": \"Sabbatical Travel\",\n \"original_request\": \"Budget £2000 for travel over the next 3 months\",\n \"period\": {\n \"kind\": \"relative\",\n \"length\": 3,\n \"unit\": \"months\"\n }\n}"
response = http.request(request)
puts response.read_body{
"_links": {},
"budget": {
"id": "<string>",
"name": "<string>",
"original_request": "<string>",
"category_name": "<string>",
"limit_amount": "<string>",
"currency": "<string>",
"spent": "<string>",
"remaining": "<string>",
"daily_avg": "<string>",
"period_start": 123,
"period_end": 123,
"created_at": 123,
"updated_at": 123,
"transactions": [
{
"transaction_id": "<string>",
"amount": "<string>",
"amount_in_budget_currency": "<string>",
"timestamp": 123,
"running_total": "<string>"
}
]
}
}{
"detail": "No wallet found with ID 12345 for this user.",
"error_code": "WAL-404-001",
"instance": "/v0/wallets/12345",
"status": 404,
"title": "Wallet Not Found",
"trace_id": "abc123-def456-ghi789",
"type": "https://api.sumvin.com/errors/wal-404-001"
}{
"detail": "No wallet found with ID 12345 for this user.",
"error_code": "WAL-404-001",
"instance": "/v0/wallets/12345",
"status": 404,
"title": "Wallet Not Found",
"trace_id": "abc123-def456-ghi789",
"type": "https://api.sumvin.com/errors/wal-404-001"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Create Budget
curl --request POST \
--url https://api.sumvin.com/v0/budgets/ \
--header 'Content-Type: application/json' \
--header 'x-juno-jwt: <api-key>' \
--data '
{
"budget_type": "custom",
"category_name": "Travel",
"currency": "GBP",
"limit_amount": "2000.00",
"name": "Sabbatical Travel",
"original_request": "Budget £2000 for travel over the next 3 months",
"period": {
"kind": "relative",
"length": 3,
"unit": "months"
}
}
'import requests
url = "https://api.sumvin.com/v0/budgets/"
payload = {
"budget_type": "custom",
"category_name": "Travel",
"currency": "GBP",
"limit_amount": "2000.00",
"name": "Sabbatical Travel",
"original_request": "Budget £2000 for travel over the next 3 months",
"period": {
"kind": "relative",
"length": 3,
"unit": "months"
}
}
headers = {
"x-juno-jwt": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-juno-jwt': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
budget_type: 'custom',
category_name: 'Travel',
currency: 'GBP',
limit_amount: '2000.00',
name: 'Sabbatical Travel',
original_request: 'Budget £2000 for travel over the next 3 months',
period: {kind: 'relative', length: 3, unit: 'months'}
})
};
fetch('https://api.sumvin.com/v0/budgets/', 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.sumvin.com/v0/budgets/",
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([
'budget_type' => 'custom',
'category_name' => 'Travel',
'currency' => 'GBP',
'limit_amount' => '2000.00',
'name' => 'Sabbatical Travel',
'original_request' => 'Budget £2000 for travel over the next 3 months',
'period' => [
'kind' => 'relative',
'length' => 3,
'unit' => 'months'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-juno-jwt: <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.sumvin.com/v0/budgets/"
payload := strings.NewReader("{\n \"budget_type\": \"custom\",\n \"category_name\": \"Travel\",\n \"currency\": \"GBP\",\n \"limit_amount\": \"2000.00\",\n \"name\": \"Sabbatical Travel\",\n \"original_request\": \"Budget £2000 for travel over the next 3 months\",\n \"period\": {\n \"kind\": \"relative\",\n \"length\": 3,\n \"unit\": \"months\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-juno-jwt", "<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.sumvin.com/v0/budgets/")
.header("x-juno-jwt", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"budget_type\": \"custom\",\n \"category_name\": \"Travel\",\n \"currency\": \"GBP\",\n \"limit_amount\": \"2000.00\",\n \"name\": \"Sabbatical Travel\",\n \"original_request\": \"Budget £2000 for travel over the next 3 months\",\n \"period\": {\n \"kind\": \"relative\",\n \"length\": 3,\n \"unit\": \"months\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sumvin.com/v0/budgets/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-juno-jwt"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"budget_type\": \"custom\",\n \"category_name\": \"Travel\",\n \"currency\": \"GBP\",\n \"limit_amount\": \"2000.00\",\n \"name\": \"Sabbatical Travel\",\n \"original_request\": \"Budget £2000 for travel over the next 3 months\",\n \"period\": {\n \"kind\": \"relative\",\n \"length\": 3,\n \"unit\": \"months\"\n }\n}"
response = http.request(request)
puts response.read_body{
"_links": {},
"budget": {
"id": "<string>",
"name": "<string>",
"original_request": "<string>",
"category_name": "<string>",
"limit_amount": "<string>",
"currency": "<string>",
"spent": "<string>",
"remaining": "<string>",
"daily_avg": "<string>",
"period_start": 123,
"period_end": 123,
"created_at": 123,
"updated_at": 123,
"transactions": [
{
"transaction_id": "<string>",
"amount": "<string>",
"amount_in_budget_currency": "<string>",
"timestamp": 123,
"running_total": "<string>"
}
]
}
}{
"detail": "No wallet found with ID 12345 for this user.",
"error_code": "WAL-404-001",
"instance": "/v0/wallets/12345",
"status": 404,
"title": "Wallet Not Found",
"trace_id": "abc123-def456-ghi789",
"type": "https://api.sumvin.com/errors/wal-404-001"
}{
"detail": "No wallet found with ID 12345 for this user.",
"error_code": "WAL-404-001",
"instance": "/v0/wallets/12345",
"status": 404,
"title": "Wallet Not Found",
"trace_id": "abc123-def456-ghi789",
"type": "https://api.sumvin.com/errors/wal-404-001"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Authorizations
JWT issued by Dynamic Labs or Privy. Sent in the x-juno-jwt header on every authenticated request.
Headers
Tenant org ID for multi-tenant auth
Controls how timestamp fields are serialized in JSON response bodies.
Default (header omitted or any other value): epoch milliseconds as integers.
iso8601: UTC ISO 8601 strings of the form YYYY-MM-DDTHH:MM:SSZ.
Example: with X-Timestamp-Format: iso8601, the field value 1704067200000 becomes "2024-01-01T00:00:00Z".
Affected fields (recursively, in dicts and arrays): any field whose name ends in _at, plus the literal field names timestamp, period_start, and period_end. All other fields are passed through unchanged.
Only iso8601 is recognized. Any other value (or omitting the header) yields the default epoch-ms representation; the server does not reject unknown values, so this is documented as an example rather than an enum to keep generated clients permissive.
"iso8601"
Body
1 - 100How often a budget starts over.
weekly, monthly and yearly repeat on their own and work out each period
for themselves. custom covers one stretch of time that has to be given
explicitly alongside it.
weekly, monthly, yearly, custom An explicit budget window with fixed start and end timestamps.
- AbsolutePeriod
- RelativePeriod
Show child attributes
Show child attributes