Saltar a contenido

Lectura

Un registro

GET /public/publicacion/12
GET /public/publicacion/12?includes=autor

Si no existe —o el RLS no deja verlo—, 404. Nunca 403: para ese usuario la fila no existe, y un 403 le confirmaría que está ahí.

Una lista

GET /public/publicacion?autor_id=3&in_estado=publicada&in_estado=borrador&limit=20&offset=0&order_by=publicado_en&order=DESC

Filtros

Un parámetro por columna, con el nombre de la columna. Qué filtros tiene cada una depende de su tipo:

Parámetro Qué es Columnas
campo Igual a Enteros, texto, fechas (date), booleanos, enumerados, claves
in_campo Uno de varios valores Enteros, texto, fechas (date), claves
min_campo · max_campo Entre dos valores, incluidos Enteros, decimales, fechas y horas
  • Las listas se repiten: ?in_estado=publicada&in_estado=borrador. Separadas por comas no funcionan.
  • Un % en un filtro de texto es un patrón (ILIKE): ?titulo=%hola%. No hay forma de buscar un % literal.
  • La clave autoincremental se filtra solo por lista: ?in_id=3&in_id=7 trae esas filas (en una petición, no una por id). No tiene igualdad —para un registro está GET /{schema}/{tabla}/{clave}— ni rango, que sobre un contador del motor no dice nada del dato. Necesita tai-sql 0.8.0; antes no tenía ningún filtro.
  • Las demás claves primarias y las foráneas tienen igualdad y lista, sin rango.
  • Sin filtro: las columnas cifradas y las hasheadas —guardan un texto distinto para el mismo valor, así que no se pueden comparar—.
  • Los campos operativos (created_at, created_by…) tienen lista y rango, pero no igualdad.

Un filtro sobre una columna que no existe no es un error: se ignora —salvo en el modo estricto—.

Paginación y orden

Parámetro Qué es
limit Cuántos registros. Sin él, devuelve todos
offset Cuántos saltarse
order_by Columnas por las que ordenar, repetido: ?order_by=estado&order_by=titulo. Las que no existen se ignoran —salvo en el modo estricto—
order ASC (por defecto) o DESC, para todas las columnas de order_by

meta.pagination —total, has_next, has_prev— solo se calcula si se pide limit u offset. El total cuenta con los mismos filtros y el mismo RLS que la página, en la misma transacción: no puede contar filas que el usuario no ve.

Relaciones

GET /public/autor?includes=publicaciones&includes=publicaciones.etiquetas

includes se repite una vez por relación, y admite rutas con puntos hasta la profundidad máxima (client.max_depth del .taiapiproject, 5 por defecto). En la respuesta cada registro lleva todas sus relaciones, en todos los niveles: las que se pidieron con sus datos —una lista, [] si no hay filas; un registro, o null si su clave foránea es nula— y las demás a null. Un nombre que no existe se ignora, y lo que pasa de la profundidad máxima llega vacío —salvo en el modo estricto—.

El modo estricto

Con la cabecera X-Tai-Strict: 1, lo que la API ignoraría en silencio es un 422 VALIDATION_ERROR, con el nombre del parámetro en field:

  • un parámetro de consulta que el endpoint no tiene (?in_idd=3, o limit en /count);
  • un order_by sobre una columna que no existe (o que no está en la respuesta, como una hasheada);
  • un includes que no es una relación, o con más niveles que la profundidad máxima.
GET /public/publicacion?in_idd=3
X-Tai-Strict: 1
→ 422  { "errors": [ { "code": "VALIDATION_ERROR", "field": "in_idd", … } ] }

Sin la cabecera, todo sigue como siempre: un frontend que no la manda no nota nada. Vale en todos los endpoints de datos, y se comprueba después de la sesión y los permisos: sin token sigue siendo un 401. El cliente TypeScript la manda siempre (createTaiClient({ strict: false }) para no hacerlo): un filtro con una errata que devolvía la tabla entera pasa a ser un error.

Contar y comprobar

GET /public/publicacion/count?autor_id=3      → data: 7
GET /public/publicacion/exists?autor_id=3     → data: true

Con los mismos filtros que la lista.

Los tipos, tal como viajan

En el schema En el JSON Ojo
int, bigint, smallint número un bigint por encima de 2^53 pierde precisión en JavaScript
float, numeric número un numeric con muchos decimales, también
datetime, date, time texto ISO 8601 datetime va sin zona horaria: la columna es TIMESTAMP sin zona
enumerado su valor, como texto sus valores, en GET /{schema}/enums/{nombre}
dict objeto
columna hash=True no aparece el valor original no existe: solo se puede verificar
columna encrypt=True el valor, descifrado el cifrado protege el dato en reposo, no del usuario con permiso
bytes texto base64 sale en base64 estándar con relleno; se acepta estándar o url-safe, sin el prefijo data:…;base64, (con él, 422). En el cliente TypeScript, fileToBytes y compañía