FluentaAPI

Inicio rápido

De cero a tu primera respuesta en cinco pasos, con curl, JavaScript y Python.

Al terminar esta página habrás creado un token de API, sabrás a qué organizaciones llega y habrás leído los módulos y una cifra de eficiencia de una de ellas.

La URL base es https://api.fluenta.io/v1/external. Cada solicitud lleva el token en el encabezado Authorization.

1. Crea un token

  1. Entra a app.fluenta.io y abre «Configuración» → «Tokens de API».
  2. Pulsa «Crear token». Escribe un «Nombre», deja el permiso «Leer» y elige un «Vencimiento».
  3. En la ventana «Token creado», pulsa «Copiar token». El token se muestra una sola vez.

Guárdalo en una variable de entorno:

export FLUENTA_TOKEN='fluenta_live_xxxxxxxxxxxxxxxx'

2. Comprueba el token

curl https://api.fluenta.io/v1/external/me \
  -H "Authorization: Bearer $FLUENTA_TOKEN"
{
  "user": { "name": "Ana Pérez", "roles": ["ADMIN"] },
  "connection": {
    "app": "Reporte semanal",
    "scopes": ["read"],
    "expiresAt": "2027-02-09T15:04:05.000Z"
  },
  "credential": {
    "kind": "personal",
    "name": "Reporte semanal",
    "prefix": "fluenta_live_xxx",
    "expiresAt": "2027-02-09T15:04:05.000Z"
  },
  "rateLimit": { "limit": 60, "remaining": 59, "reset": 1794355260 },
  "organizations": [
    { "id": 42, "name": "Confecciones Ejemplo", "connectorEnabled": true }
  ],
  "organizationsTotal": 1,
  "reachesAllOrganizations": false
}

user es la persona como la que actúa el token: tú. credential.kind es personal para un token de API.

3. Lista tus organizaciones

/me trae las primeras 50. Esta ruta las pagina y las busca por nombre:

curl https://api.fluenta.io/v1/external/organizations \
  -H "Authorization: Bearer $FLUENTA_TOKEN"
{
  "items": [
    { "id": 42, "name": "Confecciones Ejemplo", "connectorEnabled": true }
  ],
  "page": 1,
  "total": 1
}

El id es el organizationId de todas las demás rutas.

4. Lee los módulos de una organización

curl https://api.fluenta.io/v1/external/organizations/42/modules \
  -H "Authorization: Bearer $FLUENTA_TOKEN"
[
  { "id": 7, "name": "Módulo 1", "position": 0, "stationCount": 12, "colorHue": null }
]

GET /organizations/42/floor responde los módulos con sus puestos en una sola respuesta. Cuenta contra un límite de uso más bajo: mira Límites de uso.

5. Lee una cifra

La eficiencia de la planta hoy, desde el tablero en vivo. Esta ruta está en todos los planes:

curl https://api.fluenta.io/v1/external/organizations/42/board \
  -H "Authorization: Bearer $FLUENTA_TOKEN"

La respuesta, aquí sin su lista modules (una fila por módulo):

{
  "day": "2026-11-10",
  "plant": {
    "produced": 1840,
    "goal": 2000,
    "efficiency": 92,
    "modules": 1,
    "producing": 1,
    "lastClosed": { "day": "2026-11-09", "efficiency": 88.5 },
    "closed": { "average": 91.3, "modules": 1 }
  }
}

plant.efficiency es un porcentaje: 92 quiere decir 92% de la meta.

Opcional: un rango de días

La eficiencia día por día sale de una ruta de reportes. Los días van como YYYY-MM-DD, en el reloj de la planta:

curl "https://api.fluenta.io/v1/external/organizations/42/analytics/efficiency?from=2026-11-10&to=2026-11-10" \
  -H "Authorization: Bearer $FLUENTA_TOKEN"
{
  "from": "2026-11-10",
  "to": "2026-11-10",
  "groupBy": "day",
  "page": 1,
  "pageSize": 100,
  "total": 1,
  "items": [
    { "day": "2026-11-10", "units": 1840, "goal": 2000, "efficiency": 92 }
  ]
}

Esta ruta sigue el plan. Una organización cuyo plan no incluye reportes responde 403 con "code": "PLAN_LIMIT": el token está bien, y /board sigue respondiendo. Los dos programas de abajo leen /board primero, luego intentan el rango y avisan cuando el plan no lo incluye. El detalle está en Planes.

Lo mismo en JavaScript

Guárdalo como inicio.mjs y ejecútalo con Node.js:

const BASE = 'https://api.fluenta.io/v1/external';
const headers = { Authorization: `Bearer ${process.env.FLUENTA_TOKEN}` };

async function get(path) {
  const response = await fetch(`${BASE}${path}`, { headers });
  const body = await response.json();
  if (!response.ok) {
    const error = new Error(`${body.code}: ${body.message}`);
    error.code = body.code;
    throw error;
  }
  return body;
}

const me = await get('/me');
const { items } = await get('/organizations');
const organizationId = items[0].id;
const modules = await get(`/organizations/${organizationId}/modules`);
const board = await get(`/organizations/${organizationId}/board`);

console.log(me.user.name, modules.length, board.plant.efficiency);

// Opcional: un rango de días. Esta ruta sigue el plan.
try {
  const range = await get(
    `/organizations/${organizationId}/analytics/efficiency?from=2026-11-10&to=2026-11-10`
  );
  console.log(range.items);
} catch (error) {
  if (error.code !== 'PLAN_LIMIT') throw error;
  console.log('Este plan no incluye reportes.');
}

Lo mismo en Python

import os

import requests

BASE = "https://api.fluenta.io/v1/external"
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['FLUENTA_TOKEN']}"


class ApiError(RuntimeError):
    def __init__(self, body):
        super().__init__(f"{body['code']}: {body['message']}")
        self.code = body["code"]


def get(path, params=None):
    response = session.get(f"{BASE}{path}", params=params, timeout=30)
    body = response.json()
    if not response.ok:
        raise ApiError(body)
    return body


me = get("/me")
organization_id = get("/organizations")["items"][0]["id"]
modules = get(f"/organizations/{organization_id}/modules")
board = get(f"/organizations/{organization_id}/board")

print(me["user"]["name"], len(modules), board["plant"]["efficiency"])

# Opcional: un rango de días. Esta ruta sigue el plan.
try:
    efficiency = get(
        f"/organizations/{organization_id}/analytics/efficiency",
        {"from": "2026-11-10", "to": "2026-11-10"},
    )
    print(efficiency["items"])
except ApiError as error:
    if error.code != "PLAN_LIMIT":
        raise
    print("Este plan no incluye reportes.")

Qué leer después

En esta página