curl --request POST \
--url https://app.gc.ai/api/external/v1/vaults/{id}/columns \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"label": "Renewal notice",
"field_key": "renewalNotice",
"instructions": "Extract the number of days notice required to avoid automatic renewal. Return the number of days only.",
"field_type": "text",
"field_meta": {
"type": "enum",
"options": [
"Renewal",
"New business",
"Amendment"
]
},
"extraction_mode": "ai",
"sort_order": 123
}
'import requests
url = "https://app.gc.ai/api/external/v1/vaults/{id}/columns"
payload = {
"label": "Renewal notice",
"field_key": "renewalNotice",
"instructions": "Extract the number of days notice required to avoid automatic renewal. Return the number of days only.",
"field_type": "text",
"field_meta": {
"type": "enum",
"options": ["Renewal", "New business", "Amendment"]
},
"extraction_mode": "ai",
"sort_order": 123
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
label: 'Renewal notice',
field_key: 'renewalNotice',
instructions: 'Extract the number of days notice required to avoid automatic renewal. Return the number of days only.',
field_type: 'text',
field_meta: {type: 'enum', options: ['Renewal', 'New business', 'Amendment']},
extraction_mode: 'ai',
sort_order: 123
})
};
fetch('https://app.gc.ai/api/external/v1/vaults/{id}/columns', 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.gc.ai/api/external/v1/vaults/{id}/columns",
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([
'label' => 'Renewal notice',
'field_key' => 'renewalNotice',
'instructions' => 'Extract the number of days notice required to avoid automatic renewal. Return the number of days only.',
'field_type' => 'text',
'field_meta' => [
'type' => 'enum',
'options' => [
'Renewal',
'New business',
'Amendment'
]
],
'extraction_mode' => 'ai',
'sort_order' => 123
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"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.gc.ai/api/external/v1/vaults/{id}/columns"
payload := strings.NewReader("{\n \"label\": \"Renewal notice\",\n \"field_key\": \"renewalNotice\",\n \"instructions\": \"Extract the number of days notice required to avoid automatic renewal. Return the number of days only.\",\n \"field_type\": \"text\",\n \"field_meta\": {\n \"type\": \"enum\",\n \"options\": [\n \"Renewal\",\n \"New business\",\n \"Amendment\"\n ]\n },\n \"extraction_mode\": \"ai\",\n \"sort_order\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<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://app.gc.ai/api/external/v1/vaults/{id}/columns")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"label\": \"Renewal notice\",\n \"field_key\": \"renewalNotice\",\n \"instructions\": \"Extract the number of days notice required to avoid automatic renewal. Return the number of days only.\",\n \"field_type\": \"text\",\n \"field_meta\": {\n \"type\": \"enum\",\n \"options\": [\n \"Renewal\",\n \"New business\",\n \"Amendment\"\n ]\n },\n \"extraction_mode\": \"ai\",\n \"sort_order\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.gc.ai/api/external/v1/vaults/{id}/columns")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"label\": \"Renewal notice\",\n \"field_key\": \"renewalNotice\",\n \"instructions\": \"Extract the number of days notice required to avoid automatic renewal. Return the number of days only.\",\n \"field_type\": \"text\",\n \"field_meta\": {\n \"type\": \"enum\",\n \"options\": [\n \"Renewal\",\n \"New business\",\n \"Amendment\"\n ]\n },\n \"extraction_mode\": \"ai\",\n \"sort_order\": 123\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"field_key": "renewalNotice",
"label": "Renewal notice",
"instructions": "<string>",
"field_type": "text",
"field_meta": {
"type": "enum",
"options": [
"<string>"
],
"legacy_options": [
"<string>"
]
},
"extraction_mode": "ai",
"kind": "built_in",
"editable": true,
"sort_order": 123,
"created_at": "<string>",
"updated_at": "<string>"
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}Add a Column to a Vault
Add a column to a vault’s table.
Adding a column scans nothing. Documents already in the vault keep an empty cell for the new column until a re-scan fills it, which you start from the vault in the app. Add the columns you want before you upload, and every document that arrives afterwards is read against all of them.
The new column starts hidden in every saved view of this vault. A saved view is a sharing boundary, so a column created after the view was saved never joins it on its own; a member of the view reveals it there when they want it.
field_key is frozen at creation. Omit it and GC AI builds one from the label. Renaming the column later leaves the key alone, so the values already extracted stay attached to it.
A vault holds at most 500 columns. Column 501 returns 403 with the message the app shows, and you have to delete a column before adding another.
Requires the editor or owner role in the vault and the organization-level permission to manage vaults.
Requires a user-scoped API key (u:gcai_...). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.
curl --request POST \
--url https://app.gc.ai/api/external/v1/vaults/{id}/columns \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"label": "Renewal notice",
"field_key": "renewalNotice",
"instructions": "Extract the number of days notice required to avoid automatic renewal. Return the number of days only.",
"field_type": "text",
"field_meta": {
"type": "enum",
"options": [
"Renewal",
"New business",
"Amendment"
]
},
"extraction_mode": "ai",
"sort_order": 123
}
'import requests
url = "https://app.gc.ai/api/external/v1/vaults/{id}/columns"
payload = {
"label": "Renewal notice",
"field_key": "renewalNotice",
"instructions": "Extract the number of days notice required to avoid automatic renewal. Return the number of days only.",
"field_type": "text",
"field_meta": {
"type": "enum",
"options": ["Renewal", "New business", "Amendment"]
},
"extraction_mode": "ai",
"sort_order": 123
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
label: 'Renewal notice',
field_key: 'renewalNotice',
instructions: 'Extract the number of days notice required to avoid automatic renewal. Return the number of days only.',
field_type: 'text',
field_meta: {type: 'enum', options: ['Renewal', 'New business', 'Amendment']},
extraction_mode: 'ai',
sort_order: 123
})
};
fetch('https://app.gc.ai/api/external/v1/vaults/{id}/columns', 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.gc.ai/api/external/v1/vaults/{id}/columns",
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([
'label' => 'Renewal notice',
'field_key' => 'renewalNotice',
'instructions' => 'Extract the number of days notice required to avoid automatic renewal. Return the number of days only.',
'field_type' => 'text',
'field_meta' => [
'type' => 'enum',
'options' => [
'Renewal',
'New business',
'Amendment'
]
],
'extraction_mode' => 'ai',
'sort_order' => 123
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"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.gc.ai/api/external/v1/vaults/{id}/columns"
payload := strings.NewReader("{\n \"label\": \"Renewal notice\",\n \"field_key\": \"renewalNotice\",\n \"instructions\": \"Extract the number of days notice required to avoid automatic renewal. Return the number of days only.\",\n \"field_type\": \"text\",\n \"field_meta\": {\n \"type\": \"enum\",\n \"options\": [\n \"Renewal\",\n \"New business\",\n \"Amendment\"\n ]\n },\n \"extraction_mode\": \"ai\",\n \"sort_order\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<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://app.gc.ai/api/external/v1/vaults/{id}/columns")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"label\": \"Renewal notice\",\n \"field_key\": \"renewalNotice\",\n \"instructions\": \"Extract the number of days notice required to avoid automatic renewal. Return the number of days only.\",\n \"field_type\": \"text\",\n \"field_meta\": {\n \"type\": \"enum\",\n \"options\": [\n \"Renewal\",\n \"New business\",\n \"Amendment\"\n ]\n },\n \"extraction_mode\": \"ai\",\n \"sort_order\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.gc.ai/api/external/v1/vaults/{id}/columns")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"label\": \"Renewal notice\",\n \"field_key\": \"renewalNotice\",\n \"instructions\": \"Extract the number of days notice required to avoid automatic renewal. Return the number of days only.\",\n \"field_type\": \"text\",\n \"field_meta\": {\n \"type\": \"enum\",\n \"options\": [\n \"Renewal\",\n \"New business\",\n \"Amendment\"\n ]\n },\n \"extraction_mode\": \"ai\",\n \"sort_order\": 123\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"field_key": "renewalNotice",
"label": "Renewal notice",
"instructions": "<string>",
"field_type": "text",
"field_meta": {
"type": "enum",
"options": [
"<string>"
],
"legacy_options": [
"<string>"
]
},
"extraction_mode": "ai",
"kind": "built_in",
"editable": true,
"sort_order": 123,
"created_at": "<string>",
"updated_at": "<string>"
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"details": {}
}Authorizations
API key for authentication. Format: gcai_xxxxxxxxx
Create API keys in the GC AI app under Settings → API.
Path Parameters
The vault ID
Body
The column heading shown in the vault table.
1 - 200"Renewal notice"
The key extracted values are stored under. Omit it and GC AI builds one from the label (Renewal notice becomes renewalNotice). Set it when you need the key to match something you already store, because the key is frozen once the column exists: renaming the column later never changes it. Any printable key up to 100 characters works, including one with an underscore or a hyphen; percent-encode it when you address a cell on this column.
1 - 100"renewalNotice"
Required for an ai column: this text is the prompt extraction reads each document with, so say what to look for and what to return. Optional for a manual column, where it is only a note to whoever fills the column in.
4000"Extract the number of days notice required to avoid automatic renewal. Return the number of days only."
The shape of the values in this column. enum and multi_enum need field_meta; every other type needs field_meta: null.
text, date, date_range, enum, multi_enum, boolean, number, currency, percentage, duration, email, url, list, rich_text The option list for an enum or multi_enum column. Send null, or omit it, for every other type.
Show child attributes
Show child attributes
How the column gets filled. ai (the default) has extraction read it out of each document. manual keeps it out of every scan so the values stay exactly what a person types.
ai, manual Placement weight, 0 by default. The table orders columns by sort_order first and creation time second, so columns added without one keep the order you added them in.
Response
The created column
Unique column identifier, or null for a built-in column. A built-in column has no row of its own in this vault, so it has no ID and cannot be changed or deleted.
The stable key extracted values are stored under. It is set once, when the column is created, and never changes, so renaming the column keeps every value already extracted for it.
"renewalNotice"
The column heading shown in the vault table
"Renewal notice"
For an ai column, the prompt extraction reads each document with. For a manual or import column, a note to whoever reads the column.
The shape of the values in this column. Built-in columns can report party_list and related_agreement_list, which you cannot set yourself.
text, date, date_range, enum, multi_enum, boolean, number, currency, percentage, duration, email, url, list, rich_text, party_list, related_agreement_list The option list for an enum or multi_enum column. Null for every other type.
Show child attributes
Show child attributes
How the column gets filled. ai: extraction reads it out of each document. manual: a person types it and no scan ever touches it. import: values come from a connected spreadsheet, which owns the column. You can create ai and manual columns; an import column is created by connecting a spreadsheet in the app.
ai, manual, import What this column is. built_in: merged into every vault by GC AI, with no ID and no way to change it. system: owned by this vault but managed by GC AI (Document Name, Document Status, Document Title), so it has an ID but rejects every change and every delete. custom: yours, and the only kind PATCH and DELETE accept.
built_in, system, custom True when this column can be changed with PATCH /vaults/{id}/columns/{columnId}. Built-in and system columns report false: GC AI owns their name, type, options, and prompt. One exception, on both surfaces: sort_order is list position rather than identity, so it can be set on any column that has an ID.
Placement weight for this column, or null for a built-in one. The table orders columns by sort_order first and creation time second.
ISO 8601 creation timestamp, or null for a built-in column
ISO 8601 last-update timestamp, or null for a built-in column
Was this page helpful?