Inovacc Desarrolladores

Referencia de la API

Registro de actividad

Lee el registro de tu organización con las llamadas a la API y los eventos de archivos y registros.

URL base https://data.inovacc.dev

Descripción general

El Registro de actividad es el registro propio de tu organización de lo que ocurrió en Inovacc: cada llamada a la API, y cada evento de archivo y de registro que esas llamadas causaron. Lo lees con un solo endpoint, GET /v1/activity en https://data.inovacc.dev, filtrado por tiempo, tipo de evento o hash de archivo.

El problema que resuelve es responder "quién hizo qué, y cuándo" sin construir tu propia pista de auditoría. Inovacc mantiene el registro de toda llamada a las API de Datos, de IA y de Eventos, sin importar si tu aplicación se acuerda de escribir algo. El registro es un hecho del servicio, no una opción, y una organización solo ve sus propios registros.

Úsalo para auditorías, para investigar una integración fallida ("¿qué llamadas se rechazaron esta mañana, y con qué código?"), para demostrar que un archivo fue entregado (el evento de descarga lleva el SHA-256 del archivo), y para una vista del tráfico por clave. Para ver cuánto costó tu uso de IA, usa el resumen de uso del Chat con IA (GET /v1/usage/summary): el Registro de actividad registra eventos, nunca precios.

Conceptos

Eventos y tipos. Cada registro es un evento con un kind:

TipoSe escribe cuando
api.callcualquier llamada autenticada, incluidas las rechazadas (403, 429)
record.write, record.deletese crea, cambia o elimina un registro (uno por operación de un lote)
blob.write, blob.read, blob.deletese carga, descarga o elimina un blob de una base de datos
file.upload.completed, file.download, file.deletese escribe, descarga o elimina un archivo
file.upload.started, file.processedlos escriben otros servicios de Inovacc, como las cargas y conversiones de IA

Qué contiene un registro. La hora (at_ms, milisegundos Unix), la organización, quién actuó (actor_kind: user, key o service, y actor_id), el servicio de origen source, el method, la route (una plantilla como /v1/databases/{database}/collections/{collection}/records/{record_id}, nunca los ids en sí), el status, el outcome, el error_code de un fallo, la latencia, los tamaños de entrada y salida, y para un archivo su tamaño, tipo y SHA-256. related apunta a la base de datos, la colección y el registro, o a la carga o el trabajo, de que se trate. Todas las claves están siempre presentes, con null cuando no aplican.

Lo que nunca contiene. Un prompt, el cuerpo de una respuesta ni el contenido de un archivo. Las llamadas de IA nunca registran el nombre de un archivo.

País. Un registro api.call lleva country: el país de quien llama tal como lo ve el borde de red de Inovacc (dos letras, XX cuando se desconoce). Quien llama no puede establecerlo, y el registro no contiene ciudad, dirección IP ni coordenadas.

Retención. Los registros se conservan un año. Los últimos 30 días responden de inmediato; los registros más antiguos vienen del archivo y tardan más.

Cómo funciona

Llama a GET /v1/activity con Authorization: Bearer <credential>. La credencial necesita el permiso de lectura de actividad a nivel de organización; una credencial limitada a registros no lo tiene. La organización es siempre la de la credencial: no hay ningún parámetro que nombre otra.

Todos los parámetros son opcionales:

ParámetroSignificado
from, tomilisegundos Unix, UTC; from inclusivo, to exclusivo
kinduno o más tipos, separados por comas
file_sha25664 caracteres hexadecimales en minúscula: todos los eventos de ese archivo
limitde 1 a 500, por defecto 100
cursorel next_cursor de la página anterior, sin cambios

Cualquier otro parámetro, uno repetido o vacío, o un valor no válido es 400 invalid_query, y no se lee nada. La respuesta viene con lo más reciente primero: {"items":[...],"next_cursor":<string|null>,"archive_searched":<bool>}. Sigue next_cursor hasta que sea null. archive_searched te indica que la lectura llegó más allá de los últimos 30 días. Una lectura puede retroceder como máximo 366 días por llamada.

Los registros aparecen unos segundos después de la llamada, no al instante. El registro ocurre después de la respuesta y nunca la modifica: si no se puede escribir en el registro, la llamada se responde como de costumbre. Una descarga desde Datos o Archivos se registra cuando comienza; una descarga desde la API de IA se registra cuando la transferencia se completa. La API de IA también ofrece GET /v1/activity en https://ai.inovacc.dev para sus propias llamadas, con from y to como instantes RFC 3339; leerlo allí no se cobra.

Primeros pasos

Necesitas una credencial con el permiso de lectura de actividad (Autenticación).

  1. Haz una llamada para registrar. Escribe un registro en Datos o carga un archivo en Archivos.
  2. Lee los eventos más recientes. GET /v1/activity?limit=10 (consulta los ejemplos). Tu llamada está ahí como api.call, con su plantilla de ruta y su estado, seguida de su record.write o file.upload.completed.
  3. Filtra por tipo. GET /v1/activity?kind=api.call&limit=50 muestra solo llamadas; mira status y error_code para encontrar rechazos.
  4. Sigue un archivo. Toma el file_sha256 de tu carga y llama a GET /v1/activity?file_sha256=<hash>: se listan todas las cargas, descargas y eliminaciones de ese contenido.
  5. Pagina. Pasa el next_cursor de vuelta como cursor hasta que sea null.

Casos de uso

Una respuesta de auditoría. Un cliente pregunta quién eliminó un registro el martes pasado. Filtra kind=record.delete con from y to alrededor de ese día; el evento nombra al actor y related nombra la base de datos, la colección y el registro.

Prueba de entrega. Un equipo de cumplimiento debe demostrar que un informe llegó a un socio. El evento file.download lleva el SHA-256 y el tamaño de los bytes enviados, y la hora, que se pueden cotejar con el archivo original.

Salud de una integración. Una integración empieza a fallar por la noche. Filtrar kind=api.call para esa ventana muestra el status y el error_code de cada llamada hecha con la clave de la integración, por ejemplo una racha de 429 rate_limited que señala la falta de una espera creciente.

Límites y precios

LímiteValor
Retenciónun año; los últimos 30 días responden de inmediato
Rango de una lectura366 días
Tamaño de página1 a 500 (por defecto 100)
Demora antes de que un evento sea legibleunos segundos
Tasa600 solicitudes por minuto por titular de credencial, por ubicación

Precios: a consultar.

Errores

EstadoCódigoQué significa y qué hacer
400invalid_queryUn parámetro es desconocido, está repetido, vacío o no es válido; corrige la consulta.
401invalid_credentialsEnvía una credencial válida.
403forbiddenLa credencial no tiene el permiso de lectura de actividad.
429rate_limitedReduce el ritmo.
503service_unavailableNo se puede leer el registro ahora; reintenta más tarde.

Buenas prácticas

  • Filtra en el servidor: pasa kind, from y to en lugar de leer todo y filtrar en tu código.
  • Conserva el at_ms más reciente que procesaste y lee desde ahí en la siguiente ejecución, siguiendo los cursores hasta el final.
  • Usa file_sha256 para rastrear un archivo a través de cargas, descargas y procesamiento de IA.
  • Espera unos segundos de demora; no trates como un fallo la ausencia de un evento recién generado.
  • Ignora las claves que no conozcas: los registros pueden ganar campos.
  • Da a cada integración su propia clave, para que actor_id te diga cuál actuó.

Autenticación

Toda llamada lleva tu clave; tu organización viene de ella. Consulta la guía de autenticación.

EncabezadoAuthorizationBearer <clave de API>

Endpoints

GET /v1/activity

Ejemplo

Lenguaje

⋮
GET /v1/activityEjemplo

cURL

curl "https://data.inovacc.dev/v1/activity" \
  -H "Authorization: Bearer $INOVACC_API_KEY"

TypeScript

const url = "https://data.inovacc.dev/v1/activity";

const response = await fetch(url, {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
  },
});

console.log(response.status, await response.text());

Python

import os
import urllib.request

request = urllib.request.Request(
    "https://data.inovacc.dev/v1/activity",
    method="GET",
    headers={
        "User-Agent": "inovacc-python-sample",
        "Authorization": "Bearer " + os.environ["INOVACC_API_KEY"],
    },
)

with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

Go

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

const url = "https://data.inovacc.dev/v1/activity"

func main() {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INOVACC_API_KEY"))

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	out, err := io.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(res.Status, string(out))
}

Rust

// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api_key = std::env::var("INOVACC_API_KEY")?;
    let response = reqwest::blocking::Client::new()
        .get("https://data.inovacc.dev/v1/activity")
        .bearer_auth(api_key)
        .send()?;
    println!("{} {}", response.status(), response.text()?);
    Ok(())
}

JavaScript

const url = "https://data.inovacc.dev/v1/activity";

const response = await fetch(url, {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
  },
});

console.log(response.status, await response.text());

PHP

<?php

$curl = curl_init('https://data.inovacc.dev/v1/activity');
curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('INOVACC_API_KEY'),
    ],
]);

$response = curl_exec($curl);
echo curl_getinfo($curl, CURLINFO_HTTP_CODE), ' ', $response, "\n";
curl_close($curl);

Ruby

require "net/http"
require "uri"

uri = URI('https://data.inovacc.dev/v1/activity')

request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch('INOVACC_API_KEY')}"

response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
  http.request(request)
end

puts "#{response.code} #{response.body}"

Java

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Main {
    public static void main(String[] args) throws Exception {
        String apiKey = System.getenv("INOVACC_API_KEY");

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://data.inovacc.dev/v1/activity"))
                .header("Authorization", "Bearer " + apiKey)
                .GET()
                .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
                .send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.statusCode() + " " + response.body());
    }
}

C#

var url = "https://data.inovacc.dev/v1/activity";
var apiKey = Environment.GetEnvironmentVariable("INOVACC_API_KEY");

using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Add("Authorization", $"Bearer {apiKey}");

using var response = await client.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");

Kotlin

import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse

fun main() {
    val apiKey = System.getenv("INOVACC_API_KEY")

    val request = HttpRequest.newBuilder()
        .uri(URI.create("https://data.inovacc.dev/v1/activity"))
        .header("Authorization", "Bearer " + apiKey)
        .GET()
        .build()

    val response = HttpClient.newHttpClient()
        .send(request, HttpResponse.BodyHandlers.ofString())
    println("${response.statusCode()} ${response.body()}")
}

Swift

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

let apiKey = ProcessInfo.processInfo.environment["INOVACC_API_KEY"] ?? ""

let url = URL(string: "https://data.inovacc.dev/v1/activity")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")

let (data, response) = try await URLSession.shared.data(for: request)
let status = (response as? HTTPURLResponse)?.statusCode ?? 0
print(status, String(decoding: data, as: UTF8.self))
Detalles de la fuente

Entrada del catálogo

Id
identity/component-taxonomy/capabilities#activity
Repositorio
identity
Ruta
contracts/component-taxonomy/catalog/capabilities.json
Commit
08ef3cd75d82

Ejemplo

Id
identity/component-taxonomy/quickstart#activity
Repositorio
identity
Ruta
contracts/component-taxonomy/catalog/capabilities.json
Commit
08ef3cd75d82
Actualizado el 2026-10-10.