Field Types & Data Validation
How GKit infers column types from your sheet and how to control validation.
GKit reads your sheet and automatically infers a JSON type for every column. This page explains how inference works, how to override it with column header suffixes, and what happens when a write request violates the expected type.
How type inference works
When GKit fetches a sheet, it scans the first non-header row of each column and applies a set of heuristic rules to decide which JSON type to use. The result determines how values are serialised in API responses.
GKit recognises five types: string, number, boolean, date, and null
(for empty cells). The inference is best-effort - if GKit cannot match a value to a
more specific type it falls back to string.
Inference rules
The table below shows representative cell values, the type GKit infers, and how the value appears in a JSON response.
| Cell value | Inferred type | JSON representation |
|---|---|---|
Hello world | string | "Hello world" |
42 | number | 42 |
3.14 | number | 3.14 |
-0.5 | number | -0.5 |
TRUE / FALSE | boolean | true / false |
true / false | boolean | true / false |
2024-01-15 | date | "2024-01-15T00:00:00.000Z" |
01/15/2024 | date | "2024-01-15T00:00:00.000Z" |
15-Jan-2024 | date | "2024-01-15T00:00:00.000Z" |
| (empty cell) | null | null |
Inference is applied per-column, not per-cell. If the first sampled value in a column
is 42, every cell in that column is cast to number - including cells that contain
text, which will surface as null in the response rather than an incorrect number.
Explicit type hints via column header suffixes
Auto-inference can be wrong - especially for columns like ZIP codes (90210 looks like
a number but should stay a string) or timestamps stored in a human-readable format.
Append a :type suffix to the column header to force a specific type.
| Header | Forced type | Example value → JSON |
|---|---|---|
price:number | number | "49.99" → 49.99 |
active:boolean | boolean | "yes" → true |
created_at:date | date | "June 1 2025" → "2025-06-01T00:00:00.000Z" |
zip_code:string | string | 90210 → "90210" |
The suffix is stripped from the key name in the JSON response, so a header named
price:number appears as price in every API response object.
Boolean coercion with :boolean - GKit treats the following values as true:
"true", "yes", "1", "on" (case-insensitive). Everything else becomes false.
Null handling
Empty cells always become null in the JSON response, regardless of the column type.
This applies to cells that were never filled in, cells cleared by a user, and cells
where a formula returns an empty string.
{
"name": "Widget Pro",
"description": null,
"price": 49.99,
"tags": null
}Downstream code should guard against null before parsing or displaying a field:
const label = row.description ?? "No description provided.";Date handling
All date values are serialised as ISO 8601 UTC strings (YYYY-MM-DDTHH:mm:ss.sssZ),
regardless of the format displayed in the sheet.
{
"created_at": "2024-01-15T00:00:00.000Z",
"updated_at": "2025-06-01T14:30:00.000Z"
}Timezone note - Google Sheets stores dates without timezone information. GKit interprets bare dates (no time component) as midnight UTC. If your sheet's dates represent a specific local timezone, convert them on the client after reading:
// Shift a UTC midnight date to a local date string
const local = new Date(row.created_at).toLocaleDateString("en-US", {
timeZone: "America/New_York",
});Time-of-day values (e.g. 14:30) are attached to the Unix epoch date
(1970-01-01) and serialised as "1970-01-01T14:30:00.000Z".
Validation errors on write
When you POST or PATCH a row, GKit validates each field value against the inferred
or declared type for that column. If a value cannot be coerced to the expected type,
the request fails with HTTP 400 and no rows are written.
The error body follows this shape:
{
"error": "VALIDATION_ERROR",
"message": "One or more fields failed type validation.",
"fields": [
{
"column": "price",
"expected": "number",
"received": "not-a-number",
"hint": "Use a numeric value such as 49.99."
}
]
}Each entry in fields names the offending column, the type GKit expected, the raw
value it received, and a short hint. Fix all reported fields and resubmit - partial
writes are not applied.
See Writing Data for the full POST request reference.