Lee y modifica las colecciones y los artículos de un usuario de Owlect por HTTPS. Cada petición lleva un token de acceso OAuth que el usuario concedió a tu app, y solo ve los datos de ese usuario.
Owlect es un servidor de autorización OAuth 2.1. Las apps son clientes públicos que se identifican con PKCE, así que no hay ningún secreto que se pueda filtrar.
1. Registra un cliente
Las URI de retorno deben ser https, o http en localhost. El registro es abierto y tiene límite de frecuencia.
bash
curl -X POST https://owlect.app/api/oauth/register \
-H "Content-Type: application/json" \
-d '{"client_name": "My app", "redirect_uris": ["https://myapp.example/callback"]}'
2. Envía al usuario a autorizar
Usa response_type=code, un code_challenge PKCE S256, tu redirect_uri, un valor de state y scope="read create update delete" (pide solo lo que necesites). El usuario inicia sesión con Google, ve una pantalla de consentimiento con la dirección de tu app y marca qué permitir: lectura y creación vienen seleccionadas. El campo scope de la respuesta del token indica lo concedido.
Envía por POST el código y tu code_verifier al endpoint de tokens. Recibes un token de acceso (1 hora) y un token de actualización (30 días) que rota en cada uso: guarda siempre el más reciente.
Ver tus colecciones y artículos. Siempre activado.
create
Añadir colecciones y artículos. Activado por defecto.
update
Cambiar colecciones y artículos. Desactivado salvo que lo marques.
delete
Eliminar colecciones y artículos. Desactivado salvo que lo marques.
Todavía no hay claves de API personales: cada token nace de un usuario que aprueba tu app, y el usuario puede revocarlo cuando quiera en Ajustes -> Apps conectadas.
Todos los endpoints reciben y devuelven JSON. Los ids son UUID.
Cuenta
GET/api/v1/account(getAccount)
Plan y uso, la tabla de planes Free, Plus y Pro (límites, funciones, precio), el acceso de este token, lo que queda de los límites diarios de escritura y eliminación los tamaños de lote, la suscripción (estado, fecha de renovación o fin, URL para gestionarla) y enlaces a las páginas de la app. Consúltalo primero; no gasta límite.
Sin parámetros.
Colecciones
GET/api/v1/collections(listCollections)
Todas las colecciones del usuario, primero las modificadas más recientemente.
Sin parámetros.
POST/api/v1/collections(createCollection)
Crea una colección. Los tipos integrados reciben sus campos estándar si no envías fieldDefinitions. El tipo personalizado (custom) requiere Owlect Plus.
Añade hasta 50 artículos en una petición. Los valores de campos personalizados se validan antes; si algún artículo no es válido, no se guarda nada.
collectionIdrutaObligatorio
uuid
Colección a la que se añade.
itemscuerpoObligatorio
array, 1-50 items
Los artículos que se crean.
items[].namecuerpoObligatorio
string, 1-200
Nombre del artículo.
items[].descriptioncuerpo
string, max 1000
Notas en texto libre.
items[].quantitycuerpo
integer 1-999
Cuántos ejemplares tienes.
items[].customFieldValuescuerpo
object: field key -> string | number | boolean | null
Valores por clave de los campos de la colección (lee primero la colección para conocerlas). Las claves desconocidas se rechazan con la lista de las válidas.
items[].forSalecuerpo
boolean
Pone el artículo a la venta.
items[].wantedcuerpo
boolean (true = wishlist item; not with forSale: true)
Marca el artículo como buscado (en tu lista de deseos) en lugar de tenerlo. Un artículo buscado no puede estar a la venta.
Enlace a una imagen de portada. Se guarda como enlace, no se sube.
Parámetro
Dónde
Tipo
Obligatorio
Descripción
collectionId
ruta
uuid
sí
Colección a la que se añade.
items
cuerpo
array, 1-50 items
sí
Los artículos que se crean.
items[].name
cuerpo
string, 1-200
sí
Nombre del artículo.
items[].description
cuerpo
string, max 1000
no
Notas en texto libre.
items[].quantity
cuerpo
integer 1-999
no
Cuántos ejemplares tienes.
items[].customFieldValues
cuerpo
object: field key -> string | number | boolean | null
no
Valores por clave de los campos de la colección (lee primero la colección para conocerlas). Las claves desconocidas se rechazan con la lista de las válidas.
items[].forSale
cuerpo
boolean
no
Pone el artículo a la venta.
items[].wanted
cuerpo
boolean (true = wishlist item; not with forSale: true)
no
Marca el artículo como buscado (en tu lista de deseos) en lugar de tenerlo. Un artículo buscado no puede estar a la venta.
Ids de los artículos que se eliminan, separados por comas.
Parámetro
Dónde
Tipo
Obligatorio
Descripción
collectionId
ruta
uuid
sí
Colección a la que pertenecen los artículos.
ids
consulta
comma-separated uuids
sí
Ids de los artículos que se eliminan, separados por comas.
GET/api/v1/items/{itemId}(getItem)
Un artículo con todos sus campos.
itemIdrutaObligatorio
uuid
Id de un artículo (de la lista o la búsqueda de una colección).
Parámetro
Dónde
Tipo
Obligatorio
Descripción
itemId
ruta
uuid
sí
Id de un artículo (de la lista o la búsqueda de una colección).
PATCH/api/v1/items/{itemId}(updateItem)
Cambia solo los campos que envías. customFieldValues se combina por clave y null borra un campo.
itemIdrutaObligatorio
uuid
Artículo que se cambia.
namecuerpo
string, 1-200
Nuevo nombre.
descriptioncuerpo
string, max 1000
Notas en texto libre.
quantitycuerpo
integer 1-999
Cuántos ejemplares tienes.
customFieldValuescuerpo
object: field key -> string | number | boolean | null
Valores por clave de los campos de la colección (lee primero la colección para conocerlas). Las claves desconocidas se rechazan con la lista de las válidas.
forSalecuerpo
boolean
Pone el artículo a la venta.
wantedcuerpo
boolean (true = wishlist item; not with forSale: true)
Marca el artículo como buscado (en tu lista de deseos) en lugar de tenerlo. Un artículo buscado no puede estar a la venta.
Enlace a una imagen de portada. Se guarda como enlace, no se sube.
Parámetro
Dónde
Tipo
Obligatorio
Descripción
itemId
ruta
uuid
sí
Artículo que se cambia.
name
cuerpo
string, 1-200
no
Nuevo nombre.
description
cuerpo
string, max 1000
no
Notas en texto libre.
quantity
cuerpo
integer 1-999
no
Cuántos ejemplares tienes.
customFieldValues
cuerpo
object: field key -> string | number | boolean | null
no
Valores por clave de los campos de la colección (lee primero la colección para conocerlas). Las claves desconocidas se rechazan con la lista de las válidas.
forSale
cuerpo
boolean
no
Pone el artículo a la venta.
wanted
cuerpo
boolean (true = wishlist item; not with forSale: true)
no
Marca el artículo como buscado (en tu lista de deseos) en lugar de tenerlo. Un artículo buscado no puede estar a la venta.
No hay token, o no es válido, ha caducado o se revocó. Actualízalo o vuelve a pasar por la autorización.
403 insufficient_scope
El token solo tiene el ámbito read.
403 plan_limit
Se alcanzó un límite del plan del usuario. details incluye el límite y una upgradeUrl.
404 not_found
Este usuario no tiene esa colección o artículo.
409 confirmation_required
confirmName no coincide con el nombre de la colección.
413 payload_too_large
El cuerpo de la petición supera 1 MB. Envía menos artículos por petición.
422 invalid_input
Los datos no pasaron la validación, o el cuerpo tenía una clave que el endpoint no conoce (details.unknownKeys). Si un campo personalizado es desconocido, details.validKeys lista las claves de la colección.
429 rate_limited
Demasiadas peticiones. Espera lo que indica la cabecera Retry-After.
503 unavailable
Un problema temporal en Owlect. Vuelve a intentarlo en breve.
500 internal
Un error inesperado. Reintenta; si se repite, contacta con soporte.
GET /collections/{collectionId}/items devuelve { items, nextCursor }. Envía nextCursor como ?cursor= para la página siguiente; en la última página es null. Las páginas son estables aunque escribas mientras paginas.
Los límites se aplican por app conectada (concesión). La API REST y el servidor MCP los comparten.
120 peticiones por minuto.
500 peticiones de escritura al día, de las cuales hasta 20 pueden ser eliminaciones.
Por usuario, entre todas sus apps conectadas: 1000 peticiones de escritura y 40 eliminaciones al día.
Hasta 50 artículos por petición de creación y 25 por petición de eliminación.
Los límites de artículos y colecciones del plan del usuario se aplican igual que en la app.
Cada respuesta autenticada incluye RateLimit-Policy (la cuota por minuto, p. ej. "minute";q=120;w=60) y RateLimit (lo que queda y los segundos hasta que se reinicia, p. ej. "minute";r=57;t=18), según el borrador de IETF sobre las cabeceras RateLimit. Un 429 incluye también Retry-After. Los límites diarios los devuelve GET /account.
Un Custom GPT puede usar la API de Owlect como acción (Action).
Especificación OpenAPI
https://owlect.app/api/v1/openapi.json
1En el editor del GPT, abre Actions -> Create new action -> Import from URL y pega la URL de la especificación OpenAPI.
2En Authentication elige OAuth. Authorization URL: https://owlect.app/oauth/authorize. Token URL: https://owlect.app/api/oauth/token. Scope: read create update delete (el usuario igualmente elige en la pantalla de consentimiento). Token exchange method: Default (POST request).
3Introduce el client ID y el client secret que Owlect te dé para el GPT, y copia la callback URL que muestra ChatGPT para que se registre.
Las acciones de GPT usan un secreto de cliente, que Owlect emite para cada GPT bajo petición. Escribe a support@owlect.app con la callback URL de tu GPT.
Esta es la v1, y la versión forma parte de la ruta. Añadir endpoints, parámetros opcionales o campos de respuesta no rompe a los clientes; lo que pueda romper un cliente irá solo en una versión nueva. Antes de retirar un endpoint o una versión, durante al menos 6 meses responde con una cabecera Deprecation (RFC 9745) y una cabecera Sunset (RFC 8594) con la fecha de retirada, y el cambio se anuncia en la página de novedades. Hoy no hay nada obsoleto.