curl --request POST \
--url https://api.symmetry.com/stl/v1/experimental/compare \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"taxIds": "<string>",
"context_a": {
"payCalc": {},
"session": "<string>"
},
"context_b": {
"payCalc": {},
"session": "<string>"
}
}
'import requests
url = "https://api.symmetry.com/stl/v1/experimental/compare"
payload = {
"taxIds": "<string>",
"context_a": {
"payCalc": {},
"session": "<string>"
},
"context_b": {
"payCalc": {},
"session": "<string>"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
taxIds: '<string>',
context_a: {payCalc: {}, session: '<string>'},
context_b: {payCalc: {}, session: '<string>'}
})
};
fetch('https://api.symmetry.com/stl/v1/experimental/compare', 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.symmetry.com/stl/v1/experimental/compare",
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([
'taxIds' => '<string>',
'context_a' => [
'payCalc' => [
],
'session' => '<string>'
],
'context_b' => [
'payCalc' => [
],
'session' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.symmetry.com/stl/v1/experimental/compare"
payload := strings.NewReader("{\n \"taxIds\": \"<string>\",\n \"context_a\": {\n \"payCalc\": {},\n \"session\": \"<string>\"\n },\n \"context_b\": {\n \"payCalc\": {},\n \"session\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
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://api.symmetry.com/stl/v1/experimental/compare")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"taxIds\": \"<string>\",\n \"context_a\": {\n \"payCalc\": {},\n \"session\": \"<string>\"\n },\n \"context_b\": {\n \"payCalc\": {},\n \"session\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.symmetry.com/stl/v1/experimental/compare")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"taxIds\": \"<string>\",\n \"context_a\": {\n \"payCalc\": {},\n \"session\": \"<string>\"\n },\n \"context_b\": {\n \"payCalc\": {},\n \"session\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"summary": "<string>",
"paycheck": {
"gross_a": 123,
"gross_b": 123,
"gross_delta": 123,
"net_a": 123,
"net_b": 123,
"net_delta": 123,
"pay_frequency_changed": false,
"jurisdiction_changed": false,
"wage_differences": [
{
"label": "<string>",
"id": "<string>",
"amount_a": 123,
"amount_b": 123,
"delta": 123,
"note": "<string>"
}
],
"benefit_differences": [
{
"label": "<string>",
"id": "<string>",
"amount_a": 123,
"amount_b": 123,
"delta": 123,
"note": "<string>"
}
]
},
"results": [
{
"taxId": "<string>",
"amount_a": 123,
"amount_b": 123,
"delta": 123,
"note": "<string>",
"error": "<string>"
}
],
"usage": {
"input_tokens": 123,
"output_tokens": 123
},
"ai_disclosure": "This explanation is generated using AI and is provided for informational purposes only. It does not constitute tax, legal, or financial advice. AI can make mistakes."
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Compare two paychecks and explain the differences
Accepts two PayCalc contexts. Runs both through STE, computes a structured diff, and returns a single AI-generated narrative explaining only the meaningful differences.
curl --request POST \
--url https://api.symmetry.com/stl/v1/experimental/compare \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"taxIds": "<string>",
"context_a": {
"payCalc": {},
"session": "<string>"
},
"context_b": {
"payCalc": {},
"session": "<string>"
}
}
'import requests
url = "https://api.symmetry.com/stl/v1/experimental/compare"
payload = {
"taxIds": "<string>",
"context_a": {
"payCalc": {},
"session": "<string>"
},
"context_b": {
"payCalc": {},
"session": "<string>"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
taxIds: '<string>',
context_a: {payCalc: {}, session: '<string>'},
context_b: {payCalc: {}, session: '<string>'}
})
};
fetch('https://api.symmetry.com/stl/v1/experimental/compare', 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.symmetry.com/stl/v1/experimental/compare",
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([
'taxIds' => '<string>',
'context_a' => [
'payCalc' => [
],
'session' => '<string>'
],
'context_b' => [
'payCalc' => [
],
'session' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.symmetry.com/stl/v1/experimental/compare"
payload := strings.NewReader("{\n \"taxIds\": \"<string>\",\n \"context_a\": {\n \"payCalc\": {},\n \"session\": \"<string>\"\n },\n \"context_b\": {\n \"payCalc\": {},\n \"session\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
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://api.symmetry.com/stl/v1/experimental/compare")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"taxIds\": \"<string>\",\n \"context_a\": {\n \"payCalc\": {},\n \"session\": \"<string>\"\n },\n \"context_b\": {\n \"payCalc\": {},\n \"session\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.symmetry.com/stl/v1/experimental/compare")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"taxIds\": \"<string>\",\n \"context_a\": {\n \"payCalc\": {},\n \"session\": \"<string>\"\n },\n \"context_b\": {\n \"payCalc\": {},\n \"session\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"summary": "<string>",
"paycheck": {
"gross_a": 123,
"gross_b": 123,
"gross_delta": 123,
"net_a": 123,
"net_b": 123,
"net_delta": 123,
"pay_frequency_changed": false,
"jurisdiction_changed": false,
"wage_differences": [
{
"label": "<string>",
"id": "<string>",
"amount_a": 123,
"amount_b": 123,
"delta": 123,
"note": "<string>"
}
],
"benefit_differences": [
{
"label": "<string>",
"id": "<string>",
"amount_a": 123,
"amount_b": 123,
"delta": 123,
"note": "<string>"
}
]
},
"results": [
{
"taxId": "<string>",
"amount_a": 123,
"amount_b": 123,
"delta": 123,
"note": "<string>",
"error": "<string>"
}
],
"usage": {
"input_tokens": 123,
"output_tokens": 123
},
"ai_disclosure": "This explanation is generated using AI and is provided for informational purposes only. It does not constitute tax, legal, or financial advice. AI can make mistakes."
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Authorizations
Obtain a token by calling GET /authentication/login with your Symmetry API key in the api-key header. Paste the accessToken value here.
Body
Input for POST /v1/experimental/compare — two PayCalc contexts with 1-10 tax IDs.
Tax ID(s) to compare. String for single tax, array for multiple (max 10)
First paycheck (earlier payDate becomes 'before')
Show child attributes
Show child attributes
Second paycheck (later payDate becomes 'after')
Show child attributes
Show child attributes
Response
Successful Response
Response for POST /v1/experimental/compare.
Request ID (ULID)
Single flowing narrative explaining differences (≤200 words)
Paycheck-level diff section (gross, net, wages, benefits)
Show child attributes
Show child attributes
Per-tax comparison results — one entry per requested tax that resolved in at least one context
Show child attributes
Show child attributes
Token usage statistics from the Bedrock call (None if the call did not complete)
Show child attributes
Show child attributes
Static AI-generated content disclaimer for client display

