Cómo usar la API de Supabase: Una guía completa

Daniel Costa

Daniel Costa

22 April 2025

Cómo usar la API de Supabase: Una guía completa

Supabase ha surgido rápidamente como una poderosa alternativa de código abierto a Firebase, proporcionando a los desarrolladores un conjunto de herramientas construidas en torno a una base de datos PostgreSQL. En su núcleo, Supabase ofrece una capa de API instantánea y en tiempo real sobre tu base de datos, acelerando significativamente el desarrollo del backend. Esta guía proporciona una visión general completa de cómo aprovechar la API de Supabase y cubre todo, desde la configuración inicial y operaciones básicas hasta seguridad, personalización y seguridad de tipos.

💡
¿Quieres una excelente herramienta de prueba de API que genere documentación de API hermosa?

¿Quieres una plataforma integrada, todo-en-uno para que tu equipo de desarrolladores trabaje juntos con máxima productividad?

Apidog satisface todas tus demandas y reemplaza a Postman a un precio mucho más asequible!
button

1. Introducción: ¿Qué es la API de Supabase?

A diferencia del desarrollo tradicional de backend, donde podrías pasar un tiempo considerable construyendo puntos finales REST o GraphQL para interactuar con tu base de datos, Supabase genera automáticamente una API segura y de alto rendimiento para ti. Cuando creas una tabla en tu base de datos PostgreSQL de Supabase, Supabase utiliza PostgREST, una herramienta de código abierto, para introspectar el esquema de tu base de datos y proporcionar puntos finales RESTful correspondientes.

Beneficios Clave:

Esta guía se centra principalmente en la API REST y su interacción a través de bibliotecas de cliente, así como en las Funciones Edge de Supabase.

2. Comenzando con la API de Supabase

La forma más fácil de entender la API de Supabase es sumergirse de inmediato. Supongamos que tienes un proyecto de Supabase configurado (si no, visita supabase.com y crea uno gratis) y has creado una tabla simple, por ejemplo, perfiles:

-- Crear una tabla para perfiles públicos
create table perfiles (
  id uuid references auth.users not null primary key,
  updated_at timestamp with time zone,
  username text unique,
  avatar_url text,
  website text,

  constraint username_length check (char_length(username) >= 3)
);

-- Configurar Seguridad a Nivel de Fila (RLS)
-- Ver https://supabase.com/docs/guides/auth/row-level-security para más detalles.
alter table perfiles
  enable row level security;

create policy "Los perfiles públicos son visibles para todos." on perfiles
  for select using (true);

create policy "Los usuarios pueden insertar su propio perfil." on perfiles
  for insert with check (auth.uid() = id);

create policy "Los usuarios pueden actualizar su propio perfil." on perfiles
  for update using (auth.uid() = id);

-- Este trigger crea automáticamente una entrada de perfil cuando un nuevo usuario se registra a través de Supabase Auth.
-- Ver https://supabase.com/docs/guides/auth/managing-user-data#using-triggers para más detalles.
create function public.handle_new_user()
returns trigger as $$
begin
  insert into public.perfiles (id, username)
  values (new.id, new.raw_user_meta_data->>'username');
  return new;
end;
$$ language plpgsql security definer;
create trigger on_auth_user_created
  after insert on auth.users
  for each row execute procedure public.handle_new_user();

(Nota: El ejemplo anterior usa perfiles, alineándose con los ejemplos estándar de Supabase. El concepto se aplica igualmente a una tabla todos o cualquier otra tabla que crees.)

Encontrando Tus Credenciales de API:

Cada proyecto de Supabase viene con credenciales de API únicas:

  1. URL del Proyecto: Tu endpoint único de Supabase (por ejemplo, https://<tu-referencia-de-proyecto>.supabase.co).
  2. Claves de API: Encontradas en el Tablero de Proyecto de Supabase bajo Configuración del Proyecto > API.

Interactuando con la API (usando la Biblioteca de Cliente Supabase JS):

Supabase proporciona bibliotecas de cliente para simplificar las interacciones con la API. Aquí te mostramos cómo usar la biblioteca de JavaScript (supabase-js):

// 1. Importar e inicializar el cliente
import { createClient } from '@supabase/supabase-js'

const supabaseUrl = 'https://<tu-referencia-de-proyecto>.supabase.co'
const supabaseAnonKey = '<tu-clave-anon>'

const supabase = createClient(supabaseUrl, supabaseAnonKey)

// 2. Obtener datos (SELECT *)
async function getProfiles() {
  const { data, error } = await supabase
    .from('perfiles')
    .select('*')

  if (error) console.error('Error al obtener perfiles:', error)
  else console.log('Perfiles:', data)
}

// 3. Insertar datos (INSERT)
async function createProfile(userId, username) {
  const { data, error } = await supabase
    .from('perfiles')
    .insert([
      { id: userId, username: username, updated_at: new Date() },
    ])
    .select() // Retorna los datos insertados

  if (error) console.error('Error al crear perfil:', error)
  else console.log('Perfil Creado:', data)
}

// 4. Actualizar datos (UPDATE)
async function updateProfileUsername(userId, newUsername) {
  const { data, error } = await supabase
    .from('perfiles')
    .update({ username: newUsername, updated_at: new Date() })
    .eq('id', userId) // Solo actualizar donde el id coincide
    .select()

  if (error) console.error('Error al actualizar perfil:', error)
  else console.log('Perfil Actualizado:', data)
}

// 5. Eliminar datos (DELETE)
async function deleteProfile(userId) {
  const { data, error } = await supabase
    .from('perfiles')
    .delete()
    .eq('id', userId) // Solo eliminar donde el id coincide

  if (error) console.error('Error al eliminar perfil:', error)
  // Nota: Eliminar a menudo devuelve datos mínimos en caso de éxito a menos que se use .select() *antes* de .delete() en algunas versiones/configuraciones.
  else console.log('Perfil eliminado con éxito')
}

// Ejemplo de Uso (suponiendo que tienes un ID de usuario)
// getProfiles();
// createProfile('some-uuid-v4', 'nuevo_usuario');
// updateProfileUsername('some-uuid-v4', 'nombre_usuario_actualizado');
// deleteProfile('some-uuid-v4');

Este inicio rápido demuestra las operaciones CRUD fundamentales (Crear, Leer, Actualizar, Eliminar) utilizando la biblioteca de cliente, que internamente llama a la API REST.

3. La API REST de Supabase Auto-Generada

Si bien las bibliotecas de cliente son convenientes, entender la API REST subyacente generada por PostgREST es crucial.

Estructura del Endpoint API:

La URL base para la API REST es típicamente: https://<tu-referencia-de-proyecto>.supabase.co/rest/v1/

Los endpoints se crean automáticamente para tus tablas:

Autenticación:

Las solicitudes API deben incluir tu clave API en el encabezado apikey y generalmente un encabezado Authorization que contiene Bearer <tu-clave-api> (a menudo la misma clave anon para solicitudes del lado del cliente, o la clave service_role para el lado del servidor).

apikey: <tu-clave-anon-o-service-role>
Authorization: Bearer <tu-clave-anon-o-service-role>

Operaciones Comunes (usando ejemplos de curl):

Replicamos los ejemplos anteriores usando curl directamente contra la API REST. Reemplaza los marcadores de posición según corresponda.

Obtener Datos (GET):

curl 'https://<ref>.supabase.co/rest/v1/perfiles?select=*' \
  -H "apikey: <clave-anon>" \
  -H "Authorization: Bearer <clave-anon>"

Insertar Datos (POST):

curl 'https://<ref>.supabase.co/rest/v1/perfiles' \
  -X POST \
  -H "apikey: <clave-anon>" \
  -H "Authorization: Bearer <clave-anon>" \
  -H "Content-Type: application/json" \
  -H "Prefer: return=representation" \# Opcional: Retorna la(s) fila(s) insertadas \
  -d '{ "id": "some-uuid", "username": "usuario_rest" }'

Actualizar Datos (PATCH): (Actualizar perfil donde el nombre de usuario es 'usuario_rest')

curl 'https://<ref>.supabase.co/rest/v1/perfiles?username=eq.usuario_rest' \
  -X PATCH \
  -H "apikey: <clave-anon>" \
  -H "Authorization: Bearer <clave-anon>" \
  -H "Content-Type: application/json" \
  -H "Prefer: return=representation" \
  -d '{ "website": "https://example.com" }'

Eliminar Datos (DELETE): (Eliminar perfil donde el nombre de usuario es 'usuario_rest')

curl 'https://<ref>.supabase.co/rest/v1/perfiles?username=eq.usuario_rest' \
  -X DELETE \
  -H "apikey: <clave-anon>" \
  -H "Authorization: Bearer <clave-anon>"

Filtrado, Selección, Ordenamiento, Paginación:

La API REST admite consultas poderosas a través de parámetros de URL:

Documentación de API Auto-Generada:

Una de las características más útiles de Supabase es la documentación de API auto-generada disponible directamente dentro del tablero de tu proyecto.

  1. Navega a tu proyecto de Supabase.
  2. Haz clic en el ícono de Documentación de API (generalmente se parece a <>) en la barra lateral izquierda.
  3. Selecciona una tabla bajo "Tablas y Vistas".
  4. Verás documentación detallada para los endpoints REST específicos de esa tabla, incluyendo:

Esta documentación interactiva es invaluable para entender cómo estructurar tus llamadas a la API.

4. Generando Tipos para un Desarrollo Mejorado Usando la API de Supabase

Para proyectos que utilizan TypeScript u otros lenguajes tipados, Supabase proporciona una manera de generar definiciones de tipo directamente desde el esquema de tu base de datos. Esto trae beneficios significativos:

Generando Tipos usando Supabase CLI:

  1. Instala Supabase CLI: Sigue las instrucciones en https://supabase.com/docs/guides/cli.
  2. Inicia sesión: supabase login
  3. Vincula tu proyecto: supabase link --project-ref <tu-referencia-de-proyecto> (Ejecuta esto en el directorio de tu proyecto local). Puede que necesites proporcionar una contraseña de base de datos.
  4. Genera tipos:
supabase gen types typescript --linked > src/database.types.ts
# O especifica el id del proyecto si no está vinculado o en un contexto diferente
# supabase gen types typescript --project-id <tu-referencia-de-proyecto> > src/database.types.ts

Este comando inspecciona el esquema de la base de datos del proyecto Supabase vinculado y genera un archivo TypeScript (database.types.ts en este ejemplo) que contiene interfaces para tus tablas, vistas y tipos de argumentos/retornos de funciones.

Usando Tipos Generados:

Luego, puedes importar estos tipos en tu código de aplicación:

import { createClient } from '@supabase/supabase-js'
// Importar los tipos generados
import { Database } from './database.types' // Ajusta la ruta según sea necesario

const supabaseUrl = 'https://<tu-referencia-de-proyecto>.supabase.co'
const supabaseAnonKey = '<tu-clave-anon>'

// Proporciona el tipo de Base de Datos a createClient
const supabase = createClient<Database>(supabaseUrl, supabaseAnonKey)

// ¡Ahora obtienes seguridad de tipos y autocompletado!
async function getSpecificUserProfile(username: string) {
  // Autocompleta nombres de tablas ('perfiles')
  const { data, error } = await supabase
    .from('perfiles')
    // Autocompleta nombres de columnas ('id', 'username', 'website')
    .select('id, username, website')
    // Verifica el tipo del valor contra el tipo de columna
    .eq('username', username)
    .single() // Espera un único resultado o nulo

  if (error) {
    console.error('Error al obtener perfil:', error)
    return null;
  }

  // 'data' ahora está correctamente tipado según tu consulta select
  if (data) {
    console.log(`ID de Usuario: ${data.id}, Sitio Web: ${data.website}`);
    // console.log(data.non_existent_column); // <-- ¡Error de TypeScript!
  }

  return data;
}

Generar tipos es una práctica altamente recomendada para un desarrollo robusto de aplicaciones con Supabase.

5. Creando Rutas Personalizadas de API de Supabase con Funciones Edge

Si bien la API REST auto-generada cubre operaciones CRUD estándar, a menudo necesitarás lógica personalizada del lado del servidor para:

Las Funciones Edge de Supabase proporcionan una manera de implementar funciones de TypeScript basadas en Deno globalmente en el edge, cerca de tus usuarios.

Creando una Función Edge:

  1. Inicializa Funciones (si no se ha hecho ya): supabase functions new hello-world (ejecuta en el directorio de tu proyecto vinculado). Esto crea un archivo supabase/functions/hello-world/index.ts.

Escribe tu código de función:

// supabase/functions/hello-world/index.ts
import { serve } from 'https://deno.land/std@0.177.0/http/server.ts' // Usa la versión std apropiada

serve(async (req) => {
  // Puedes acceder a los encabezados de la solicitud, método, cuerpo, etc. desde 'req'
  console.log(`Solicitud recibida para: ${req.url}`);

  // Ejemplo: Accediendo a la DB de Supabase desde dentro de la función
  // Nota: Requiere configurar el cliente de Supabase *dentro* de la función
  // Usa variables de entorno para secretos!
  // import { createClient } from '@supabase/supabase-js'
  // const supabaseAdmin = createClient(
  //   Deno.env.get('SUPABASE_URL') ?? '',
  //   Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
  // )
  // const { data: users, error } = await supabaseAdmin.from('perfiles').select('*').limit(10);

  const data = {
    message: `¡Hola desde el Edge!`,
    // users: users // Ejemplo si estás obteniendo datos
  }

  return new Response(
    JSON.stringify(data),
    { headers: { 'Content-Type': 'application/json' } },
  )
})

Implementa la función:

supabase functions deploy hello-world --no-verify-jwt
# Usa --no-verify-jwt para funciones accesibles públicamente
# Omitirlo o establecer --verify-jwt=true para requerir un JWT de Supabase Auth válido

Invocar la función:
Puedes llamar a las funciones implementadas a través de solicitudes HTTP POST (o GET, dependiendo de la lógica de la función) a su endpoint único:
https://<tu-referencia-de-proyecto>.supabase.co/functions/v1/hello-world

Usando curl:

curl -X POST 'https://<ref>.supabase.co/functions/v1/hello-world' \
  -H "Authorization: Bearer <user-jwt-si-se-requiere>" \
  -H "Content-Type: application/json" \
  -d '{"name": "Funciones"}' # Cuerpo de solicitud opcional

O usando el cliente JS de Supabase:

const { data, error } = await supabase.functions.invoke('hello-world', {
  method: 'POST', // o 'GET', etc.
  body: { name: 'Funciones' }
})

Las Funciones Edge son una herramienta poderosa para extender las capacidades de backend de tu Supabase más allá de las operaciones simples de base de datos.

6. Claves de API y Seguridad de Tu API de Supabase

Entender las claves de API e implementar medidas de seguridad adecuadas es innegociable.

Recapitulación de Claves de API:

El Papel Crucial de la Seguridad a Nivel de Fila (RLS):

RLS es la piedra angular de la seguridad de Supabase cuando se utiliza la clave anon. Te permite definir políticas de control de acceso detalladas directamente dentro de la base de datos PostgreSQL. Las políticas son esencialmente reglas SQL que determinan qué filas un usuario puede ver, insertar, actualizar o eliminar en función de su estado autenticado, ID de usuario, rol u otros criterios.

Habilitando RLS:

Por defecto, RLS está deshabilitado en nuevas tablas. Debes habilitarlo para cualquier tabla que pretendas acceder desde el lado del cliente utilizando la clave anon.

-- Habilitar RLS en la tabla 'perfiles'
ALTER TABLE perfiles ENABLE ROW LEVEL SECURITY;

-- IMPORTANTE: Si no se definen políticas después de habilitar RLS,
-- el acceso se deniega implícitamente para todas las operaciones (excepto para el propietario de la tabla).

Creando Políticas RLS:

Las políticas definen la cláusula USING (para acceso de lectura como SELECT, UPDATE, DELETE) y la cláusula WITH CHECK (para acceso de escritura como INSERT, UPDATE).

Ejemplo 1: Permitir que los usuarios autenticados lean todos los perfiles:

CREATE POLICY "Permitir acceso de lectura autenticado"
ON perfiles FOR SELECT
USING ( auth.role() = 'authenticated' );

Ejemplo 2: Permitir que los usuarios vean solo su propio perfil:

CREATE POLICY "Permitir acceso de lectura individual"
ON perfiles FOR SELECT
USING ( auth.uid() = id ); -- Asume que la columna 'id' coincide con el UUID del usuario de Supabase Auth

Ejemplo 3: Permitir que los usuarios actualicen solo su propio perfil:

CREATE POLICY "Permitir acceso de actualización individual"
ON perfiles FOR UPDATE
USING ( auth.uid() = id ) -- Especifica qué filas pueden ser objetivo de la actualización
WITH CHECK ( auth.uid() = id ); -- Asegura que cualquier *nuevo* dato aún cumpla con la condición

Ejemplo 4: Permitir que los usuarios inserten su propio perfil:

CREATE POLICY "Permitir acceso de inserción individual"
ON perfiles FOR INSERT
WITH CHECK ( auth.uid() = id );

Puedes ver, crear y gestionar políticas RLS directamente en el Tablero de Supabase bajo Autenticación > Políticas.

Principios Clave de Seguridad:

  1. Siempre habilita RLS en tablas accesadas a través de la clave anon.
  2. Define políticas explícitas para SELECT, INSERT, UPDATE, DELETE según sea necesario. Comienza con políticas restrictivas y abre el acceso cuidadosamente.
  3. Nunca expongas la clave service_role en código del lado del cliente o en entornos inseguros.
  4. Usa Funciones Edge para operaciones que requieren privilegios elevados o lógica compleja del lado del servidor, protegiendo tu clave service_role dentro de las variables de entorno seguras de la función.
  5. Revisa regularmente tus políticas RLS para asegurarte de que cumplan con los requisitos de seguridad de tu aplicación.

7. Mapeando Conceptos SQL a la API de Supabase (SQL a API)

Si estás familiarizado con SQL, entender cómo las operaciones SQL comunes se mapean a la API de Supabase (tanto REST como bibliotecas de cliente) es útil.

SELECT * FROM mi_tabla;

SELECT columna1, columna2 FROM mi_tabla WHERE id = 1;

INSERT INTO mi_tabla (columna1, columna2) VALUES ('valor1', 'valor2');

UPDATE mi_tabla SET columna1 = 'nuevo_valor' WHERE id = 1;

DELETE FROM mi_tabla WHERE id = 1;

Uniones: Si bien la sintaxis SQL JOIN directa no se utiliza en las llamadas REST básicas, puedes obtener datos relacionados usando:

-- Ejemplo de función SQL
CREATE FUNCTION get_user_posts(user_id uuid)
RETURNS TABLE (post_id int, post_content text) AS $$
  SELECT posts.id, posts.content
  FROM posts
  WHERE posts.author_id = user_id;
$$ LANGUAGE sql;

8. Usando Esquemas Personalizados con la API de Supabase

Por defecto, las tablas que creas en el Editor SQL de Supabase residen en el esquema public. Para mejor organización, espacio de nombres o gestión de permisos, podrías querer usar esquemas PostgreSQL personalizados.

Creando un Esquema Personalizado:

CREATE SCHEMA esquema_privado;

Creando Tablas en un Esquema Personalizado:

CREATE TABLE esquema_privado.datos_sensibles (
  id serial primary key,
  payload jsonb
);

Accediendo a Tablas en Esquemas Personalizados a través de la API:

La capa PostgREST de Supabase detecta automáticamente tablas en esquemas distintos a public.

// Accediendo a una tabla en 'esquema_privado' (suponiendo que RLS/permisos lo permitan)
const { data, error } = await supabase
  .from('datos_sensibles') // No es necesario prefijar con el nombre del esquema aquí
  .select('*')
  .eq('id', 1);

Supabase se encarga de mapear el nombre de la tabla al esquema correcto detrás de escena. Asegúrate de que tus políticas RLS hagan referencia correctamente a las tablas si implican consultas o funciones entre esquemas.

Usar esquemas personalizados es una práctica estándar de PostgreSQL que Supabase admite completamente, permitiendo una organización de base de datos más estructurada.

9. Conclusión

La API de Supabase ofrece una forma notablemente eficiente de construir aplicaciones al proporcionar acceso instantáneo, seguro y escalable a tu base de datos PostgreSQL. Desde los endpoints REST auto-generados y las útiles bibliotecas de cliente hasta la sólida seguridad proporcionada por la Seguridad a Nivel de Fila y la extensibilidad ofrecida por las Funciones Edge, Supabase empodera a los desarrolladores para centrarse en construir características en lugar de infraestructura de backend estándar.

Al entender los conceptos centrales: claves de API, RLS, la estructura REST, generación de tipos y funciones personalizadas, puedes aprovechar eficazmente todo el poder de la plataforma Supabase. Recuerda priorizar la seguridad.

💡
¿Quieres una excelente herramienta de prueba de API que genere documentación de API hermosa?

¿Quieres una plataforma integrada, todo-en-uno para que tu equipo de desarrolladores trabaje juntos con máxima productividad?

Apidog satisface todas tus demandas y reemplaza a Postman a un precio mucho más asequible!
button

Practica el diseño de API en Apidog

Descubre una forma más fácil de construir y usar APIs