Skip to main content
POST
/
databases
/
{databaseId}
/
tables
/
{tableId}
/
fields
Add Table Field
curl --request POST \
  --url https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/fields \
  --header 'Content-Type: application/json' \
  --header 'Softr-Api-Key: <api-key>' \
  --data '
{
  "name": "<string>",
  "type": "<string>",
  "options": {}
}
'
import requests

url = "https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/fields"

payload = {
"name": "<string>",
"type": "<string>",
"options": {}
}
headers = {
"Softr-Api-Key": "<api-key>",
"Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const options = {
method: 'POST',
headers: {'Softr-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({name: '<string>', type: '<string>', options: {}})
};

fetch('https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/fields', 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://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/fields",
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' => '<string>',
'type' => '<string>',
'options' => [

]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Softr-Api-Key: <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://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/fields"

payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"type\": \"<string>\",\n \"options\": {}\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Softr-Api-Key", "<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://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/fields")
.header("Softr-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"type\": \"<string>\",\n \"options\": {}\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/fields")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Softr-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"type\": \"<string>\",\n \"options\": {}\n}"

response = http.request(request)
puts response.read_body
{
  "data": {
    "id": "<string>",
    "name": "<string>",
    "description": "<string>",
    "options": {},
    "allowMultipleEntries": true,
    "readonly": true,
    "required": true,
    "locked": true,
    "defaultValue": "<string>",
    "aiOptions": {
      "aiFillable": true,
      "aiOnly": true,
      "allowWebSearch": true,
      "aiModel": "<string>",
      "prompt": "<string>",
      "canBeTriggeredManually": true,
      "runWhenRecordIsCreated": true,
      "runWhenRecordIsUpdated": true
    },
    "createdAt": "2023-11-07T05:31:56Z",
    "updatedAt": "2023-11-07T05:31:56Z"
  }
}

Field Types Reference

Editable Fields

TypeValue FormatDescription
SINGLE_LINE_TEXTstringShort text
LONG_TEXTstringMulti-line text
EMAILstringEmail address
PHONEstringPhone number
URLstringWeb URL
NUMBERnumberNumeric value
CURRENCYnumberMonetary amount
PERCENTnumberPercentage (0–100)
RATINGnumberStar rating
DURATIONnumberDuration
CHECKBOXbooleanTrue/false
SELECTstring or arraySingle or multi-select from predefined choices
USERobject or arrayUser reference
LINKED_RECORDstring or arrayLink to record(s) in another table
ATTACHMENTobject or arrayFile attachment
DATEstringDate (ISO 8601)
DATETIMEstringDate and time (ISO 8601)

Read-Only Fields

These are computed or system-managed and cannot be set when creating or updating records.
TypeDescription
LOOKUPValue from a linked record’s field
ROLLUPAggregation over linked records
FORMULACalculated from a formula expression
CREATED_ATRecord creation timestamp
UPDATED_ATRecord last modified timestamp
CREATED_BYUser who created the record
UPDATED_BYUser who last modified the record
AUTONUMBERAuto-incrementing number
RECORD_IDSystem record identifier

Field Options

Type-specific configuration passed in the options object when creating or updating fields.

SELECT

{
  "choices": [
    { "id": "choice-1", "label": "Option A", "color": "#FF0000" },
    { "id": "choice-2", "label": "Option B", "color": "#00FF00" }
  ],
  "allowToAddNewChoice": true,
  "sorting": "CUSTOM",
  "enforceOrder": false
}
sorting can be CUSTOM, ALPHA_ASC, or ALPHA_DESC.

NUMBER

{
  "precision": 2,
  "min": 0,
  "max": 1000000,
  "showThousandSeparator": true,
  "thousandSeparatorLocale": "en-US",
  "largeNumberAbbreviation": "NONE",
  "prefix": null,
  "suffix": null
}
largeNumberAbbreviation can be NONE, K, M, B, or T.

CURRENCY

{
  "precision": 2,
  "min": null,
  "max": null,
  "isoCode": "USD",
  "customSymbol": null,
  "showAs": "SYMBOL",
  "showThousandSeparator": true,
  "thousandSeparatorLocale": "en-US",
  "largeNumberAbbreviation": "NONE",
  "symbolOrCodePosition": "BEFORE"
}
  • showAs: SYMBOL or CODE
  • symbolOrCodePosition: BEFORE or AFTER

LINKED_RECORD

{
  "linkedTableId": "table-uuid",
  "inverseLinkFieldId": "field-uuid",
  "viewId": null,
  "sorting": [],
  "filter": null,
  "enforceOrder": false
}

LOOKUP

{
  "linkedRecordFieldId": "field-uuid",
  "lookupFieldId": "field-uuid",
  "isValid": true
}

ROLLUP

{
  "linkedRecordFieldId": "field-uuid",
  "rollupFieldId": "field-uuid",
  "function": "SUM",
  "filter": null
}
Available functions: SUM, MIN, MAX, COUNT, AVERAGE, ARRAYCOMPACT, ARRAYJOIN, ARRAYUNIQUE, ARRAYFLATTEN, CONCATENATE, COUNTALL, COUNTA, OR, AND.

ATTACHMENT

{
  "showAs": "PREVIEW",
  "inferredFileType": "OTHER",
  "enableFileLinkExpiration": true,
  "fileLinkExpirationValue": 2,
  "fileLinkExpirationUnit": "HOURS"
}
  • showAs: PREVIEW, LIST, or BADGE
  • inferredFileType: IMAGE, VIDEO, PDF, AUDIO, or OTHER
  • fileLinkExpirationUnit: HOURS or MINUTES

FORMULA

{
  "formula": "IF({Status} = 'Active', {Amount} * 1.1, {Amount})",
  "isValid": true,
  "referencedFieldIds": ["field-uuid-1", "field-uuid-2"]
}

AI Options

Fields can include an aiOptions object that configures AI-powered auto-fill behavior. This is returned in field definitions and can be set when creating or updating fields.
{
  "aiFillable": true,
  "aiOnly": false,
  "allowWebSearch": true,
  "aiModel": "GPT_4_1",
  "prompt": "Summarize the customer's request based on {Description}",
  "canBeTriggeredManually": true,
  "runWhenRecordIsCreated": true,
  "runWhenRecordIsUpdated": false
}
PropertyTypeDefaultDescription
aiFillablebooleanfalseWhether AI can fill this field
aiOnlybooleantrueIf true, only AI can write to this field
allowWebSearchbooleanfalseAllow AI to use web search when filling
aiModelstring"GPT_4_1"AI model to use
promptstring""Prompt template (reference other fields with {FieldName})
canBeTriggeredManuallybooleantrueWhether users can trigger AI fill manually
runWhenRecordIsCreatedbooleantrueAuto-run when record is created
runWhenRecordIsUpdatedbooleantrueAuto-run when record is updated
Fields without AI configuration return "aiOptions": null.

Authorizations

Softr-Api-Key
string
header
required

Path Parameters

databaseId
string
required
tableId
string
required

Body

application/json
name
string
required
type
string
required
options
object

Response

The newly created field.

data
object