Desarrolladores · API REST

API REST de Owlect

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.

URL base

https://owlect.app/api/v1
v1JSONOAuth 2.1 + PKCEOpenAPI 3.111 endpointsEspecificación OpenAPI →Ver como Markdown →

Inicio rápido

  1. 1

    Registra tu app

    Envía por POST tu URI de retorno al endpoint de registro y guarda el client_id que devuelve.

  2. 2

    Obtén un token

    Envía al usuario a la URL de autorización: inicia sesión con Google y pulsa Permitir. Después cambia el código por un token de acceso.

  3. 3

    Llama a la API

    Envía Authorization: Bearer <token> en cada petición. Empieza por GET /account.

Autenticación

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.

url
https://owlect.app/oauth/authorize?response_type=code
  &client_id=CLIENT_ID
  &redirect_uri=https%3A%2F%2Fmyapp.example%2Fcallback
  &code_challenge=CODE_CHALLENGE&code_challenge_method=S256
  &scope=read%20create%20update%20delete&state=STATE

3. Cambia el código

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.

bash
curl -X POST https://owlect.app/api/oauth/token \
  -d grant_type=authorization_code \
  -d code=CODE -d client_id=CLIENT_ID \
  -d redirect_uri=https://myapp.example/callback \
  -d code_verifier=CODE_VERIFIER

4. Llama a la API

Envía Authorization: Bearer <access_token>. Cuando caduque, usa grant_type=refresh_token para obtener un par nuevo.

bash
curl -X POST https://owlect.app/api/oauth/token \
  -d grant_type=refresh_token \
  -d refresh_token=REFRESH_TOKEN -d client_id=CLIENT_ID

Ámbitos

read

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.

Endpoints

Todos los endpoints reciben y devuelven JSON. Los ids son UUID.

Cuenta

GET/api/v1/account(getAccount)

El plan del usuario y cuánto ha usado de sus límites de artículos y colecciones.

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.

  • namecuerpoObligatorio

    string, 1-100

    Nombre de la colección.

  • typecuerpoObligatorio

    dolls | board_games | coins | stamps | music | pokemon_cards | sneakers | retro_games | funko_pop | lego | comic_books | books | watches | cars | hot_wheels | custom

    Tipo de colección. Define los campos por defecto y las búsquedas que usa la app.

  • descriptioncuerpo

    string, max 500

    Se muestra en la página de la colección.

  • fieldDefinitionscuerpo

    array of { key, label, type, options?, required? }

    Campos personalizados. Omítelo para usar los campos estándar del tipo.

GET/api/v1/collections/{collectionId}(getCollection)

Una colección con las definiciones de sus campos personalizados. Léelas antes de escribir customFieldValues.

  • collectionIdrutaObligatorio

    uuid

    Id de una de las colecciones del usuario (de la lista de colecciones).

PATCH/api/v1/collections/{collectionId}(updateCollection)

Cambia el nombre, la descripción o las definiciones de campos. Lo que no envíes se queda igual.

  • collectionIdrutaObligatorio

    uuid

    Colección que se cambia.

  • namecuerpo

    string, 1-100

    Nuevo nombre.

  • descriptioncuerpo

    string, max 500

    Nueva descripción.

  • fieldDefinitionscuerpo

    array of { key, label, type, options?, required? }

    Sustituye toda la lista de campos.

DELETE/api/v1/collections/{collectionId}(deleteCollection)

Elimina la colección y todos sus artículos. confirmName debe coincidir exactamente con el nombre de la colección.

  • collectionIdrutaObligatorio

    uuid

    Colección que se elimina.

  • confirmNameconsultaObligatorio

    string (the collection's exact name)

    Debe coincidir exactamente con el nombre de la colección.

Artículos

GET/api/v1/collections/{collectionId}/items(searchItems)

Artículos de una colección, primero los más nuevos, con búsqueda opcional por nombre y filtro de venta. Paginado con cursor.

  • collectionIdrutaObligatorio

    uuid

    Colección en la que buscar.

  • queryconsulta

    string, max 200

    Coincidencia con el nombre del artículo, sin distinguir mayúsculas.

  • forSaleconsulta

    boolean

    true para artículos a la venta, false para el resto.

  • limitconsulta

    integer 1-50, default 20

    Artículos por página.

  • cursorconsulta

    string (nextCursor from the previous page)

    nextCursor de la página anterior. Omítelo en la primera página.

POST/api/v1/collections/{collectionId}/items(createItems)

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[].salePricecuerpo

    integer (whole currency units) | null

    Precio en unidades enteras, p. ej. 40 para 40 $.

  • items[].saleCurrencycuerpo

    currency code, e.g. USD, EUR, UAH

    Moneda del precio. Por defecto USD.

  • items[].completenesscuerpo

    complete | incomplete | partial | sealed | unknown | null

    Si el artículo está completo, precintado, etc.

  • items[].barcodecuerpo

    string, max 64 | null

    EAN, UPC o ISBN.

  • items[].coverUrlcuerpo

    https URL | null

    Enlace a una imagen de portada. Se guarda como enlace, no se sube.

DELETE/api/v1/collections/{collectionId}/items(deleteItems)

Elimina hasta 25 artículos de la colección.

  • collectionIdrutaObligatorio

    uuid

    Colección a la que pertenecen los artículos.

  • idsconsultaObligatorio

    comma-separated uuids

    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).

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.

  • salePricecuerpo

    integer (whole currency units) | null

    Precio en unidades enteras, p. ej. 40 para 40 $.

  • saleCurrencycuerpo

    currency code, e.g. USD, EUR, UAH

    Moneda del precio. Por defecto USD.

  • completenesscuerpo

    complete | incomplete | partial | sealed | unknown | null

    Si el artículo está completo, precintado, etc.

  • barcodecuerpo

    string, max 64 | null

    EAN, UPC o ISBN.

  • coverUrlcuerpo

    https URL | null

    Enlace a una imagen de portada. Se guarda como enlace, no se sube.

Ejemplos

Sustituye $TOKEN por un token de acceso y los ids por ids reales.

Listar colecciones

bash
curl https://owlect.app/api/v1/collections \
  -H "Authorization: Bearer $TOKEN"

Añadir artículos a una colección

bash
curl -X POST https://owlect.app/api/v1/collections/COLLECTION_ID/items \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"items": [
    {"name": "Wingspan", "customFieldValues": {"game_type": "Base Game"}},
    {"name": "Scythe", "quantity": 2}
  ]}'

Buscar artículos a la venta

bash
curl "https://owlect.app/api/v1/collections/COLLECTION_ID/items?forSale=true&limit=20" \
  -H "Authorization: Bearer $TOKEN"

Poner un artículo a la venta

bash
curl -X PATCH https://owlect.app/api/v1/items/ITEM_ID \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"forSale": true, "salePrice": 40, "saleCurrency": "USD"}'

Errores

Los errores tienen un formato JSON único y un estado HTTP significativo. `code` es estable; `message` es para personas y puede cambiar.

json
{
  "error": {
    "code": "invalid_input",
    "message": "Unknown field \"publsher\". This collection's fields are: ...",
    "details": {
      "validKeys": [
        "publisher",
        "players"
      ]
    }
  }
}
401 unauthorized
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.

Paginación

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.

Límites

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.

Custom GPTs (acciones de ChatGPT)

Un Custom GPT puede usar la API de Owlect como acción (Action).

Especificación OpenAPI

https://owlect.app/api/v1/openapi.json
  1. 1En el editor del GPT, abre Actions -> Create new action -> Import from URL y pega la URL de la especificación OpenAPI.
  2. 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).
  3. 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.

Versiones

Esta es la v1. Añadir endpoints, parámetros opcionales o campos de respuesta no rompe a los clientes; lo que pueda romper un cliente irá en una versión nueva, con aviso.