Approve Change
curl --request POST \
--url https://app.textql.com/v2/changes/{id}/approve \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"expected_git_ref": "<string>"
}
'import requests
url = "https://app.textql.com/v2/changes/{id}/approve"
payload = { "expected_git_ref": "<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({expected_git_ref: '<string>'})
};
fetch('https://app.textql.com/v2/changes/{id}/approve', 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://app.textql.com/v2/changes/{id}/approve",
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([
'expected_git_ref' => '<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://app.textql.com/v2/changes/{id}/approve"
payload := strings.NewReader("{\n \"expected_git_ref\": \"<string>\"\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://app.textql.com/v2/changes/{id}/approve")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"expected_git_ref\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.textql.com/v2/changes/{id}/approve")
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 \"expected_git_ref\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"merged": true,
"approval_count": 123,
"required_approvals": 123,
"already_approved": true
}{
"error": {
"code": "invalid_request",
"message": "Invalid request body"
}
}{
"error": {
"code": "unauthenticated",
"message": "Authentication required"
}
}{
"error": {
"code": "permission_denied",
"message": "Insufficient permissions"
}
}{
"error": {
"code": "not_found",
"message": "Resource not found"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded"
}
}{
"error": {
"code": "internal",
"message": "Internal server error"
}
}Changes
Approve Change
Record your approval and merge the change once the folder’s approval rule is satisfied.
POST
/
v2
/
changes
/
{id}
/
approve
Approve Change
curl --request POST \
--url https://app.textql.com/v2/changes/{id}/approve \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"expected_git_ref": "<string>"
}
'import requests
url = "https://app.textql.com/v2/changes/{id}/approve"
payload = { "expected_git_ref": "<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({expected_git_ref: '<string>'})
};
fetch('https://app.textql.com/v2/changes/{id}/approve', 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://app.textql.com/v2/changes/{id}/approve",
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([
'expected_git_ref' => '<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://app.textql.com/v2/changes/{id}/approve"
payload := strings.NewReader("{\n \"expected_git_ref\": \"<string>\"\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://app.textql.com/v2/changes/{id}/approve")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"expected_git_ref\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.textql.com/v2/changes/{id}/approve")
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 \"expected_git_ref\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"merged": true,
"approval_count": 123,
"required_approvals": 123,
"already_approved": true
}{
"error": {
"code": "invalid_request",
"message": "Invalid request body"
}
}{
"error": {
"code": "unauthenticated",
"message": "Authentication required"
}
}{
"error": {
"code": "permission_denied",
"message": "Insufficient permissions"
}
}{
"error": {
"code": "not_found",
"message": "Resource not found"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded"
}
}{
"error": {
"code": "internal",
"message": "Internal server error"
}
}You must have
OWNERS write authority on every path the change touches.
Self-approval is rejected when a folder rule requires distinct approvers. The
change merges to the Ontology only once the required approvals are met;
until then the response reports merged: false with the running
approval_count / required_approvals.Two behaviors matter when you describe this control to an auditor:Organization admins hold full Library access, so they count as an Owner of
every path for approval purposes even when they are not listed in the folder’s
OWNERS file. Your approver population for a governed folder is its declared
Owners plus every org admin.An approval rule scoped to a set of author roles applies only to authors
holding one of those roles. Any other author is outside the rule, and their
changes to that folder apply on their own authority. Leave the author roles
empty for a rule that must govern every author.Authorizations
API key or JWT token
Path Parameters
Change ID
Body
application/json
The change git_ref the caller reviewed; a stale value returns 409.