Inovacc Desenvolvedores

Referência da API

Conhecimento e busca vetorial

Ingira documentos, monte coleções de conhecimento e consulte por significado.

URL base https://ai.inovacc.dev

Visão geral

Conhecimento e busca vetorial mantém o conhecimento da sua organização num lugar onde uma aplicação pode fazer perguntas a ele por significado. Tem três partes, todas em https://ai.inovacc.dev:

  • o Banco de Dados Vetorial: um repositório gerenciado de trechos de texto que você ingere e pesquisa, com filtros, escopos e reclassificação opcional;
  • as coleções de conhecimento: envie um lote de arquivos mistos (documentos, imagens, vídeo) e receba-os processados em pacotes de conhecimento; depois baixe o resultado, consulte-o, converse com ele com citações ou peça um relatório escrito sobre ele;
  • os trabalhos de conhecimento: transformam uma gravação longa em uma base de conhecimento que você baixa como um único arquivo compactado.

O problema que ele resolve é tudo o que existe entre "temos arquivos" e "o assistente consegue responder a partir deles": extrair o texto, dividi-lo em trechos, gerar os embeddings, indexar, manter o índice consistente e citar a fonte de cada resposta. A Inovacc executa essas etapas e você chama alguns poucos endpoints.

Use-o quando as respostas precisarem vir do seu próprio material. Quando você já opera o seu próprio índice vetorial, os Embeddings de IA entregam apenas os vetores. Quando a resposta é texto livre sem fontes, use o Chat com IA. Cada parte é habilitada para a sua organização pela Inovacc; uma parte que não está habilitada responde 403 (vector_database_disabled, collections_disabled ou knowledge_disabled).

Conceitos

Banco de Dados Vetorial e seu perfil. Sua organização cria um banco de dados com POST /v1/vector/databases, escolhendo um perfil de embeddings em GET /v1/vector/profiles. Um perfil define a modalidade (text), os idiomas (english ou multilingual), as dimensões e a métrica de distância; os ids têm a forma text-multilingual-1024. Você escolhe um perfil, nunca um modelo. O perfil não pode ser alterado: para usar outro, exclua o banco de dados, crie um novo e ingira tudo de novo.

Documentos, escopos e modos. Você ingere trechos com o seu próprio id, o text deles e metadata plano opcional. Um trecho vai para um escopo: shared (todos os serviços do espaço de trabalho da sua organização) ou local (apenas a chave de API que o escreveu). As consultas usam um modo: shared, local ou hybrid para pesquisar ambos e mesclar por pontuação. Seis chaves de metadados podem ser usadas em filtros: kind, source, category, tag, language, created_at. Blocos que compartilham um document_id formam um documento com uma generation (o seu número de versão), o que permite excluir ou substituir um documento inteiro de uma vez.

Coleções e seu modo. Uma coleção é criada em um de três modos, fixos durante toda a sua vida: download (processa os arquivos, você baixa os pacotes e nada permanece depois), cloud (a Inovacc guarda o conteúdo processado e seus vetores para que você possa usar query, chat e executar uma analysis) ou local_vectors (a Inovacc guarda apenas vetores, nunca texto: você faz embed dos seus próprios blocos e query devolve ids de blocos e pontuações). As coleções são mantidas por 30 dias por padrão; uma organização configurada com retenção zero tem as coleções excluídas uma hora depois do início do download.

Itens. Um arquivo entra em uma coleção na própria requisição (até 16 MiB), a partir de um envio concluído (vídeo acima de 16 MiB), por URL pública ou por uma URL assinada selada com uma chave de uso único, de modo que nunca seja armazenada. Cada item passa por queued, processing e depois done ou failed; um item que falha não interrompe os outros.

Consistência eventual e searchable. O índice vetorial aplica as escritas de forma assíncrona: um vetor fica legível alguns segundos, às vezes minutos, depois de escrito. GET /v1/vector/databases e toda resposta de coleção informam searchable; uma consulta enviada enquanto ele é false pode não encontrar os trechos mais recentes. O indexing.complete de uma coleção cloud só é true quando todos os blocos estão escritos e legíveis.

Trabalhos, potência e orçamento. Um trabalho de conhecimento recebe um envio concluído de uma gravação, uma transcrição e notas opcionais, uma power (light, medium ou max) e um max_price_usd obrigatório. Um trabalho acima do limite da sua organização é recusado antes de qualquer trabalho pago.

Como funciona

Toda chamada leva Authorization: Bearer <key>. Sua organização vem da chave. X-Operation-Id é obrigatório nas chamadas POST de coleção, envio e trabalho e as torna idempotentes: uma nova tentativa com o mesmo id devolve a primeira resposta (X-Idempotent-Replay: true) e não acrescenta nada; o mesmo id com um arquivo diferente retorna 409 operation_id_reused. No Banco de Dados Vetorial ele é opcional, porque ingestão e exclusão são idempotentes por construção: ingerir um id existente o substitui.

Uma consulta (POST /v1/vector/query) recebe mode, query (de 1 a 8.000 caracteres), top_k (de 1 a 50) e um filter opcional; devolve as correspondências da melhor para a pior, cada uma com id, score, text e metadata. Com "retrieval": "vector_rerank" e um rerank_profile, uma lista de candidatos mais ampla é reordenada por uma etapa de reclassificação; o objeto retrieval da resposta informa se a reclassificação foi aplicada ou se voltou à ordem vetorial.

Uma coleção funciona em etapas que você pode observar: crie-a, adicione itens (202, queued), leia-a até que status seja complete e então baixe, consulte ou converse. Ler uma coleção cloud também avança a sua indexação, em uma quantidade limitada por chamada, e toda resposta traz o progresso de indexing. O chat responde apenas a partir das fontes recuperadas, numera cada citação com o item, o pacote, o bloco e o localizador, e diz que não consegue responder quando as fontes não cobrem a pergunta. Uma analysis é construída ao longo de várias requisições: repita POST ou GET a cada poucos segundos até que ela responda 200 com o relatório.

Um trabalho é assíncrono: POST /v1/knowledge/jobs responde 202 com job_id, status_url e poll_after_seconds (também como Retry-After). Leia o status quando for indicado; o serviço prevê o tempo até a conclusão e inclui eta_seconds enquanto consegue. Quando state for done, baixe o arquivo compactado; ele é mantido por 24 horas.

O que é medido: tokens de embeddings e vetores escritos na ingestão e na indexação, consultas, reclassificações como unidade própria, chamadas de chat na sua rota de chat e trabalhos pelo seu preço. POST /v1/knowledge/estimates precifica uma gravação antes de você enviá-la, sem custo.

Primeiros passos

Você precisa de uma chave de API e da parte que deseja habilitada para a sua organização (Autenticação).

  1. Crie o banco de dados. GET /v1/vector/profiles, escolha um perfil e então POST /v1/vector/databases com {"profile":"<id>"}. A resposta é 201 com o banco de dados.
  2. Ingira trechos. POST /v1/vector/ingest com "scope":"shared" e dois ou três documentos (veja os exemplos). A resposta informa quantos foram ingested e lista os skipped, se houver, com o motivo.
  3. Espere por searchable. GET /v1/vector/databases até que searchable seja true.
  4. Consulte. POST /v1/vector/query com "mode":"shared" e uma pergunta redigida de forma diferente dos seus trechos. O trecho mais próximo vem primeiro, com o seu score.
  5. Experimente uma coleção. POST /v1/collections com {"mode":"cloud"}, adicione um PDF a /items, leia a coleção até que indexing.complete seja true, depois POST /v1/collections/{id}/chat e confira as citations.

Casos de uso

Um assistente baseado no seu manual. Sua intranet ingere cada página de política como blocos sob o seu document_id, com metadados de category. O assistente consulta com um filtro de category e passa os melhores trechos ao seu próprio prompt. Quando uma página muda, ela é ingerida de novo com uma generation mais alta, e os blocos que a nova versão não tem mais deixam de aparecer imediatamente.

Perguntas sobre os arquivos entregues por um cliente. Um consultor cria uma coleção cloud por projeto, adiciona os contratos e planilhas que o cliente enviou e faz perguntas por meio de chat. Cada resposta cita o item e a página em que se baseia, de modo que cada afirmação possa ser conferida antes de entrar em um relatório; analysis produz um resumo, entidades e contradições entre os arquivos.

De gravações de reuniões a uma base de conhecimento. Depois de cada reunião gravada, o aplicativo estima o preço, envia o vídeo em partes de 64 MiB com a transcrição da própria chamada como referência e inicia um trabalho com max_price_usd. Quando o trabalho está done, o arquivo compactado (áudio, quadros-chave e a base de conhecimento) é arquivado junto com a reunião.

Limites e preços

LimiteValor
Corpo da requisição do Banco de Dados Vetorial1 MiB
Documentos por ingestão, ids por exclusão100
Um documento (id + text + metadata)10 KiB
Texto da consulta; top_k8.000 caracteres; 50
Valores de $in no filtro20
Item no corpo de uma requisição, ou buscado por URL16 MiB
Itens por coleção100; 1 GiB de arquivos enviados em requisições; 20 GiB de vídeo por envio
top_k da consulta à coleção; mensagens de chat20; de 1 a 20 mensagens de até 8.000 caracteres
Blocos por chamada embed100, cada um com até 8.000 caracteres
Chamadas de modelo da análise por relatório32
Tamanho da parte de um envio64 MiB (todas as partes, exceto a última)
Envio que não é vídeo (transcrição, notas)16 MiB
Envio de gravaçãoo limite da sua organização
Chaves de busca mantidas sem uso16, cada uma válida uma vez por 60 segundos
Resultado do trabalho mantido24 horas
Retenção da coleção30 dias por padrão

Preços: sob consulta. Uma gravação processada por um trabalho é precificada em minutos de vídeo, e POST /v1/knowledge/estimates devolve o preço linha por linha antes de você enviar qualquer coisa. O chat sobre uma coleção é medido como Chat com IA na sua rota de chat.

Erros

StatusCódigoO que significa e o que fazer
400invalid_body, unsupported_fieldUm campo ou valor que a rota não aceita; confira os campos da rota.
400invalid_profileEscolha um perfil listado por GET /v1/vector/profiles.
400confirmation_requiredExcluir o banco de dados exige {"confirm":"delete-database-and-all-vectors"}.
400invalid_url, signed_url_must_be_sealedApenas URLs https públicas na porta 443; uma URL assinada deve ser selada.
400fetch_key_invalid, invalid_sealed_urlSolicite uma nova chave de busca e sele novamente.
403vector_database_disabled, collections_disabled, knowledge_disabledEssa parte não está habilitada para a sua organização.
403budget_exceededO max_price_usd do trabalho está acima do limite da sua organização.
404collection_not_found, job_not_found, upload_not_found, analysis_not_foundConfira o id; o download de um trabalho também retorna 404 até que ele esteja done.
409vector_database_not_created, vector_database_exists, vector_database_deletingCrie o banco de dados primeiro; um por organização; aguarde a conclusão de uma exclusão.
409mode_not_supportedA operação não existe no modo desta coleção.
409collection_incomplete, collection_fullAguarde os itens terminarem; a coleção está no limite.
409upload_incomplete, operation_id_reused, operation_in_progressConclua o envio; use um novo id de operação para um arquivo diferente; aguarde.
410collection_expired, result_expiredA retenção terminou; processe novamente.
413request_too_large, url_too_largeUse POST /v1/uploads para arquivos grandes.
415, 422unsupported_media_type, input_rejected, archive_rejectedO tipo de arquivo não é lido, ou o arquivo foi recusado (reason diz o motivo).
429too_many_fetch_keys e os códigos de cotaUse ou deixe expirar as chaves que você mantém; veja Erros.
502, 504url_fetch_failed, url_fetch_timeout, upstream_error, timeout_errorA URL ou o processamento falhou; tente novamente.
503service_unavailableTente novamente mais tarde; nada foi presumido.

Boas práticas

  • Agrupe os blocos sob um document_id e incremente generation quando a fonte mudar; a exclusão e a substituição passam então a funcionar por documento.
  • Envie content_sha256 com cada bloco e compare-o com GET /v1/vector/documents para ressincronizar a sua cópia sem ingerir tudo de novo.
  • Verifique searchable (ou indexing.complete) antes de confiar nos trechos mais novos.
  • Mantenha a resposta de um trecho dentro dos seus primeiros 2.000 caracteres quando usar a reclassificação; apenas essa parte é lida pelo reclassificador.
  • Compare vector_rerank com vector simples nos seus próprios dados, especialmente fora do inglês, antes de confiar nele.
  • Estime sempre antes de um trabalho e defina max_price_usd; consulte o status em poll_after_seconds, não mais rápido.
  • Sele as URLs assinadas; nunca envie uma URL que carregue um login. Envie os bytes em vez disso.
  • Confira as citações: um modelo pode citar uma fonte real para algo que ela não diz.

Autenticação

Toda chamada leva a sua chave; a sua organização vem dela. Veja o guia de autenticação.

CabeçalhoAuthorizationBearer <chave de API>
CabeçalhoX-Operation-Idum id único que você escolhe, em toda chamada exceto GET

Endpoints

POST /v1/vector/ingest

POST /v1/vector/query

POST /v1/collections

POST /v1/collections/{id}/query

POST /v1/knowledge/jobs

Exemplo

Linguagem

⋮
POST /v1/vector/ingestExemplo

cURL

curl -X POST "https://ai.inovacc.dev/v1/vector/ingest" \
  -H "Authorization: Bearer $INOVACC_API_KEY" \
  -H "X-Operation-Id: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "scope": "shared",
  "documents": [
    {
      "id": "handbook-leave-1",
      "text": "Employees accrue two and a half days of paid leave per month.",
      "metadata": {
        "category": "hr"
      },
      "document_id": "handbook-leave",
      "generation": 1
    }
  ]
}'

TypeScript

import crypto from "node:crypto";

const body: Record<string, unknown> = {
  "scope": "shared",
  "documents": [
    {
      "id": "handbook-leave-1",
      "text": "Employees accrue two and a half days of paid leave per month.",
      "metadata": {
        "category": "hr"
      },
      "document_id": "handbook-leave",
      "generation": 1
    }
  ]
};

const url = "https://ai.inovacc.dev/v1/vector/ingest";

const response = await fetch(url, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
    "X-Operation-Id": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify(body),
});

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

Python

import json
import os
import urllib.request
import uuid

body = {
    "scope": "shared",
    "documents": [
        {
            "id": "handbook-leave-1",
            "text": "Employees accrue two and a half days of paid leave per month.",
            "metadata": {
                "category": "hr",
            },
            "document_id": "handbook-leave",
            "generation": 1,
        },
    ],
}

request = urllib.request.Request(
    "https://ai.inovacc.dev/v1/vector/ingest",
    data=json.dumps(body).encode(),
    method="POST",
    headers={
        "User-Agent": "inovacc-python-sample",
        "Authorization": "Bearer " + os.environ["INOVACC_API_KEY"],
        "X-Operation-Id": str(uuid.uuid4()),
        "Content-Type": "application/json",
    },
)

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

Go

package main

import (
	"crypto/rand"
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

const url = "https://ai.inovacc.dev/v1/vector/ingest"

const body = `{
  "scope": "shared",
  "documents": [
    {
      "id": "handbook-leave-1",
      "text": "Employees accrue two and a half days of paid leave per month.",
      "metadata": {
        "category": "hr"
      },
      "document_id": "handbook-leave",
      "generation": 1
    }
  ]
}`

// newUUID returns a random (version 4) UUID, from the standard library alone.
func newUUID() string {
	b := make([]byte, 16)
	if _, err := rand.Read(b); err != nil {
		panic(err)
	}
	b[6] = b[6]&0x0f | 0x40
	b[8] = b[8]&0x3f | 0x80
	return fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
}

func main() {
	req, err := http.NewRequest("POST", url, strings.NewReader(body))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INOVACC_API_KEY"))
	req.Header.Set("X-Operation-Id", newUUID())
	req.Header.Set("Content-Type", "application/json")

	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"] }
// Cargo.toml: serde_json = "1"
// Cargo.toml: uuid = { version = "1", features = ["v4"] }

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api_key = std::env::var("INOVACC_API_KEY")?;
    let body = serde_json::json!({
        "scope": "shared",
        "documents": [
            {
                "id": "handbook-leave-1",
                "text": "Employees accrue two and a half days of paid leave per month.",
                "metadata": {
                    "category": "hr"
                },
                "document_id": "handbook-leave",
                "generation": 1
            }
        ]
    });
    let response = reqwest::blocking::Client::new()
        .post("https://ai.inovacc.dev/v1/vector/ingest")
        .bearer_auth(api_key)
        .header("X-Operation-Id", uuid::Uuid::new_v4().to_string())
        .json(&body)
        .send()?;
    println!("{} {}", response.status(), response.text()?);
    Ok(())
}

JavaScript

import crypto from "node:crypto";

const body = {
  "scope": "shared",
  "documents": [
    {
      "id": "handbook-leave-1",
      "text": "Employees accrue two and a half days of paid leave per month.",
      "metadata": {
        "category": "hr"
      },
      "document_id": "handbook-leave",
      "generation": 1
    }
  ]
};

const url = "https://ai.inovacc.dev/v1/vector/ingest";

const response = await fetch(url, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
    "X-Operation-Id": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify(body),
});

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

PHP

<?php

$body = <<<'JSON'
{
  "scope": "shared",
  "documents": [
    {
      "id": "handbook-leave-1",
      "text": "Employees accrue two and a half days of paid leave per month.",
      "metadata": {
        "category": "hr"
      },
      "document_id": "handbook-leave",
      "generation": 1
    }
  ]
}
JSON;

function uuid4(): string
{
    $bytes = random_bytes(16);
    $bytes[6] = chr(ord($bytes[6]) & 0x0f | 0x40);
    $bytes[8] = chr(ord($bytes[8]) & 0x3f | 0x80);
    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($bytes), 4));
}

$curl = curl_init('https://ai.inovacc.dev/v1/vector/ingest');
curl_setopt_array($curl, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('INOVACC_API_KEY'),
        'X-Operation-Id: ' . uuid4(),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => $body,
]);

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

Ruby

require "net/http"
require "securerandom"
require "uri"

uri = URI('https://ai.inovacc.dev/v1/vector/ingest')
body = <<~'JSON'
{
  "scope": "shared",
  "documents": [
    {
      "id": "handbook-leave-1",
      "text": "Employees accrue two and a half days of paid leave per month.",
      "metadata": {
        "category": "hr"
      },
      "document_id": "handbook-leave",
      "generation": 1
    }
  ]
}
JSON

request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch('INOVACC_API_KEY')}"
request["X-Operation-Id"] = SecureRandom.uuid
request["Content-Type"] = "application/json"
request.body = body

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;
import java.util.UUID;

public class Main {
    public static void main(String[] args) throws Exception {
        String apiKey = System.getenv("INOVACC_API_KEY");
        String body = "{" +
                "\"scope\": \"shared\"," +
                "\"documents\": [" +
                "{" +
                "\"id\": \"handbook-leave-1\"," +
                "\"text\": \"Employees accrue two and a half days of paid leave per month.\"," +
                "\"metadata\": {" +
                "\"category\": \"hr\"" +
                "}," +
                "\"document_id\": \"handbook-leave\"," +
                "\"generation\": 1" +
                "}" +
                "]" +
                "}";

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://ai.inovacc.dev/v1/vector/ingest"))
                .header("Authorization", "Bearer " + apiKey)
                .header("X-Operation-Id", UUID.randomUUID().toString())
                .header("Content-Type", "application/json")
                .method("POST", HttpRequest.BodyPublishers.ofString(body))
                .build();

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

C#

using System.Text;

var body = "{" +
    "\"scope\": \"shared\"," +
    "\"documents\": [" +
    "{" +
    "\"id\": \"handbook-leave-1\"," +
    "\"text\": \"Employees accrue two and a half days of paid leave per month.\"," +
    "\"metadata\": {" +
    "\"category\": \"hr\"" +
    "}," +
    "\"document_id\": \"handbook-leave\"," +
    "\"generation\": 1" +
    "}" +
    "]" +
    "}";

var url = "https://ai.inovacc.dev/v1/vector/ingest";
var apiKey = Environment.GetEnvironmentVariable("INOVACC_API_KEY");

using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.Add("Authorization", $"Bearer {apiKey}");
request.Headers.Add("X-Operation-Id", Guid.NewGuid().ToString());
request.Content = new StringContent(body, Encoding.UTF8, "application/json");

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
import java.util.UUID

fun main() {
    val apiKey = System.getenv("INOVACC_API_KEY")
    val body = "{" +
        "\"scope\": \"shared\"," +
        "\"documents\": [" +
        "{" +
        "\"id\": \"handbook-leave-1\"," +
        "\"text\": \"Employees accrue two and a half days of paid leave per month.\"," +
        "\"metadata\": {" +
        "\"category\": \"hr\"" +
        "}," +
        "\"document_id\": \"handbook-leave\"," +
        "\"generation\": 1" +
        "}" +
        "]" +
        "}"

    val request = HttpRequest.newBuilder()
        .uri(URI.create("https://ai.inovacc.dev/v1/vector/ingest"))
        .header("Authorization", "Bearer " + apiKey)
        .header("X-Operation-Id", UUID.randomUUID().toString())
        .header("Content-Type", "application/json")
        .method("POST", HttpRequest.BodyPublishers.ofString(body))
        .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 body = #"""
{
  "scope": "shared",
  "documents": [
    {
      "id": "handbook-leave-1",
      "text": "Employees accrue two and a half days of paid leave per month.",
      "metadata": {
        "category": "hr"
      },
      "document_id": "handbook-leave",
      "generation": 1
    }
  ]
}
"""#

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

let url = URL(string: "https://ai.inovacc.dev/v1/vector/ingest")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue(UUID().uuidString, forHTTPHeaderField: "X-Operation-Id")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = Data(body.utf8)

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))
Detalhes da fonte

Entrada do catálogo

Id
identity/component-taxonomy/capabilities#knowledge
Repositório
identity
Caminho
contracts/component-taxonomy/catalog/capabilities.json
Commit
08ef3cd75d82

Exemplo

Id
identity/component-taxonomy/quickstart#knowledge
Repositório
identity
Caminho
contracts/component-taxonomy/catalog/capabilities.json
Commit
08ef3cd75d82
Atualizado em 2026-10-10.