> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abbyy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Procesar con la API

> Inicio rápido paso a paso para procesar un documento con la API REST de ABBYY Vantage: autentíquese, elija una skill, cargue un archivo y descargue los datos JSON extraídos.

export const VantageRegion = ({children}) => {
  const STORAGE_KEY = "abbyy.vantage.region";
  const REGIONS = [{
    code: "eu",
    label: "Europe"
  }, {
    code: "us",
    label: "North America"
  }, {
    code: "au",
    label: "Australia / Asia-Pacific"
  }];
  const [region, setRegion] = useState("eu");
  const [open, setOpen] = useState(false);
  const containerRef = useRef(null);
  const dropdownRef = useRef(null);
  function safeGetSavedRegion() {
    try {
      const saved = typeof window !== "undefined" ? window.localStorage.getItem(STORAGE_KEY) : null;
      const valid = new Set(REGIONS.map(r => r.code));
      return saved && valid.has(saved) ? saved : "eu";
    } catch {
      return "eu";
    }
  }
  function safeSetSavedRegion(code) {
    try {
      if (typeof window !== "undefined") {
        window.localStorage.setItem(STORAGE_KEY, code);
      }
    } catch {}
  }
  function dispatchRegionChanged(code) {
    try {
      if (typeof window !== "undefined") {
        window.dispatchEvent(new CustomEvent("abbyy:region-changed", {
          detail: {
            code
          }
        }));
      }
    } catch {}
  }
  function replaceRegionInString(text, currentRegion) {
    if (typeof text !== "string") return text;
    const hostRegex = /https:\/\/vantage-(eu|us|au)\.abbyy\.com/gi;
    const tokenRegex = /https:\/\/vantage-\[region\]\.abbyy\.com/gi;
    const bareHostRegex = /vantage-(eu|us|au)\.abbyy\.com/gi;
    const bareTokenRegex = /vantage-\[region\]\.abbyy\.com/gi;
    return text.replace(hostRegex, `https://vantage-${currentRegion}.abbyy.com`).replace(tokenRegex, `https://vantage-${currentRegion}.abbyy.com`).replace(bareHostRegex, `vantage-${currentRegion}.abbyy.com`).replace(bareTokenRegex, `vantage-${currentRegion}.abbyy.com`);
  }
  useEffect(() => {
    setRegion(safeGetSavedRegion());
  }, []);
  useEffect(() => {
    const root = containerRef.current;
    if (!root) return;
    const anchors = root.querySelectorAll("a[href]");
    anchors.forEach(a => {
      const href = a.getAttribute("href");
      if (href) {
        const next = replaceRegionInString(href, region);
        if (next !== href) {
          a.setAttribute("href", next);
        }
      }
    });
    const walker = typeof document !== "undefined" ? document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null) : null;
    if (walker) {
      const toUpdate = [];
      let node = walker.nextNode();
      while (node) {
        const updated = replaceRegionInString(node.nodeValue, region);
        if (updated !== node.nodeValue) {
          toUpdate.push([node, updated]);
        }
        node = walker.nextNode();
      }
      toUpdate.forEach(([textNode, value]) => {
        textNode.nodeValue = value;
      });
    }
  }, [region, children]);
  useEffect(() => {
    const root = containerRef.current;
    if (!root) return;
    const anchors = root.querySelectorAll("a[href]");
    anchors.forEach(a => {
      a.style.fontWeight = "600";
      a.style.textDecoration = "underline";
      a.style.textUnderlineOffset = "2px";
    });
  }, [region, children]);
  useEffect(() => {
    const onRegionChanged = evt => {
      const code = evt && evt.detail && evt.detail.code;
      if (!code || code === region) return;
      setRegion(code);
    };
    if (typeof window !== "undefined") {
      window.addEventListener("abbyy:region-changed", onRegionChanged);
    }
    return () => {
      if (typeof window !== "undefined") {
        window.removeEventListener("abbyy:region-changed", onRegionChanged);
      }
    };
  }, [region]);
  useEffect(() => {
    const onClickAway = e => {
      if (!dropdownRef.current) return;
      if (!dropdownRef.current.contains(e.target)) {
        setOpen(false);
      }
    };
    document.addEventListener("click", onClickAway, true);
    return () => document.removeEventListener("click", onClickAway, true);
  }, []);
  const onSelect = code => {
    setRegion(code);
    safeSetSavedRegion(code);
    dispatchRegionChanged(code);
    setOpen(false);
  };
  const current = REGIONS.find(r => r.code === region) || REGIONS[0];
  return <div className="not-prose">
      <div className="mb-4 inline-flex items-center gap-2" ref={dropdownRef}>
        <span className="text-sm text-zinc-950/80 dark:text-white/80">Tenant Region:</span>
        <div className="relative">
          <button type="button" aria-haspopup="listbox" aria-expanded={open ? "true" : "false"} onClick={() => setOpen(v => !v)} className="h-8 px-3 rounded-md bg-zinc-900/5 dark:bg-white/5 border border-zinc-950/20 dark:border-white/20 text-sm inline-flex items-center gap-2">
            <span className="text-zinc-950 dark:text-white">{current.label}</span>
            <svg width="8" height="24" viewBox="0 -9 3 24" className="transition-transform text-gray-400 overflow-visible dark:text-gray-600 ml-auto" style={{
    transform: open ? "rotate(270deg)" : "rotate(90deg)"
  }}>
              <path d="M0 0L3 3L0 6" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"></path>
            </svg>
          </button>
          {open ? <div role="listbox" className="absolute z-50 left-full top-0 ml-2 w-56 rounded-xl border border-zinc-950/20 dark:border-white/20 bg-white dark:bg-zinc-900 shadow-lg p-2">
              {REGIONS.map(r => {
    const selected = r.code === region;
    return <button key={r.code} type="button" role="option" aria-selected={selected ? "true" : "false"} onClick={() => onSelect(r.code)} className={"w-full flex items-center justify-between px-3 py-2 rounded-lg text-sm hover:bg-zinc-950/5 dark:hover:bg-white/10 text-zinc-950 dark:text-white" + (selected ? " font-medium" : "")}>
                    <span style={selected ? {
      color: "#ff2038"
    } : undefined}>{r.label}</span>
                    <span className={selected ? "ml-3" : "ml-3 invisible"} style={selected ? {
      color: "#ff2038"
    } : undefined}>✓</span>
                  </button>;
  })}
            </div> : null}
        </div>
      </div>
      <div ref={containerRef} className="prose dark:prose-invert max-w-none">{children}</div>
    </div>;
};

<VantageRegion>
  Esta guía le explica paso a paso el flujo de trabajo de la Vantage API: autenticarse, encontrar un skill, cargar un documento y descargar los resultados estructurados.

  **Lo que lograrás:** Enviar un documento a la API REST de Vantage y recibir los datos extraídos estructurados en formato JSON.

  **Tiempo estimado:** \~10 minutos

  ## Requisitos previos

  * Un tenant de Vantage con credenciales de cliente para la API (`client_id` y `client_secret`)
  * Un documento de ejemplo para procesar (PDF, TIFF, JPEG o PNG)

  <Callout type="info">
    ¿Aún no tienes credenciales? El administrador de tu tenant puede crear credenciales de cliente de API en **Administración > Clientes de API**.
  </Callout>

  ## Paso 1: Autenticarse

  Obtenga un token de acceso con sus credenciales de cliente.

  <Tabs>
    <Tab title="cURL">
      ```bash theme={null}
      curl -X POST "https://vantage-us.abbyy.com/auth2/connect/token" \
        -d "grant_type=client_credentials" \
        -d "scope=openid permissions global.wildcard" \
        -d "client_id=YOUR_CLIENT_ID" \
        -d "client_secret=YOUR_CLIENT_SECRET"
      ```
    </Tab>

    <Tab title="Python">
      ```python theme={null}
      import requests

      response = requests.post(
          "https://vantage-us.abbyy.com/auth2/connect/token",
          data={
              "grant_type": "client_credentials",
              "scope": "openid permissions global.wildcard",
              "client_id": "YOUR_CLIENT_ID",
              "client_secret": "YOUR_CLIENT_SECRET",
          },
      )

      token = response.json()["access_token"]
      ```
    </Tab>
  </Tabs>

  La respuesta incluye un `access_token` (válido por 24 horas). Úselo en el encabezado `Authorization` para todas las solicitudes posteriores.

  <Callout type="tip">
    Usa el selector **Tenant Region** en la parte superior de esta página para actualizar todas las URL según tu región.
  </Callout>

  ## Paso 2: Encontrar un skill

  Enumere los skills disponibles en su tenant para encontrar el indicado para su documento.

  <Tabs>
    <Tab title="cURL">
      ```bash theme={null}
      curl -X GET "https://vantage-us.abbyy.com/api/publicapi/v1/skills" \
        -H "Authorization: Bearer $TOKEN"
      ```
    </Tab>

    <Tab title="Python">
      ```python theme={null}
      skills = requests.get(
          "https://vantage-us.abbyy.com/api/publicapi/v1/skills",
          headers={"Authorization": f"Bearer {token}"},
      ).json()

      for skill in skills:
          print(f"{skill['id']}: {skill['name']}")
      ```
    </Tab>
  </Tabs>

  Anote el `id` del skill que desea utilizar (p. ej., un skill Invoice).

  ## Paso 3: Procesar un documento

  Cargue un documento y procéselo con un skill en una sola llamada a la API.

  <Tabs>
    <Tab title="cURL">
      ```bash theme={null}
      curl -X POST "https://vantage-us.abbyy.com/api/publicapi/v1/transactions/launch?skillId=SKILL_ID" \
        -H "Authorization: Bearer $TOKEN" \
        -H "Content-Type: multipart/form-data" \
        -F 'Model={"files": [{}]}' \
        -F "Files=@invoice.pdf;type=application/pdf"
      ```
    </Tab>

    <Tab title="Python">
      ```python theme={null}
      with open("invoice.pdf", "rb") as f:
          response = requests.post(
              "https://vantage-us.abbyy.com/api/publicapi/v1/transactions/launch",
              params={"skillId": "SKILL_ID"},
              headers={"Authorization": f"Bearer {token}"},
              files={
                  "Model": (None, '{"files": [{}]}', "application/json"),
                  "Files": ("invoice.pdf", f, "application/pdf"),
              },
          )

      transaction_id = response.json()["transactionId"]
      ```
    </Tab>
  </Tabs>

  ## Paso 4: Verificar el estado

  Consulte la transacción hasta que el procesamiento se complete.

  <Tabs>
    <Tab title="cURL">
      ```bash theme={null}
      curl -X GET "https://vantage-us.abbyy.com/api/publicapi/v1/transactions/$TRANSACTION_ID" \
        -H "Authorization: Bearer $TOKEN"
      ```
    </Tab>

    <Tab title="Python">
      ```python theme={null}
      import time

      while True:
          status = requests.get(
              f"https://vantage-us.abbyy.com/api/publicapi/v1/transactions/{transaction_id}",
              headers={"Authorization": f"Bearer {token}"},
          ).json()

          print(f"Estado: {status['status']}")

          if status["status"] in ("Processed", "ProcessedWithWarnings"):
              break
          if status["status"] == "NotProcessed":
              raise Exception("Error de procesamiento")

          time.sleep(5)
      ```
    </Tab>
  </Tabs>

  <Callout type="info">
    Realice sondeos cada 5–10 segundos. El procesamiento suele tardar entre 10 y 30 segundos, según la complejidad del documento.
  </Callout>

  ## Paso 5: Descargar resultados

  Obtenga los datos extraídos en formato JSON.

  <Tabs>
    <Tab title="cURL">
      ```bash theme={null}
      # Listar los documentos de la transacción
      curl -X GET "https://vantage-us.abbyy.com/api/publicapi/v1/transactions/$TRANSACTION_ID/documents" \
        -H "Authorization: Bearer $TOKEN"

      # Descargar el archivo de resultado
      curl -X GET "https://vantage-us.abbyy.com/api/publicapi/v1/transactions/$TRANSACTION_ID/files/$FILE_ID/download" \
        -H "Authorization: Bearer $TOKEN" \
        -o result.json
      ```
    </Tab>

    <Tab title="Python">
      ```python theme={null}
      # Obtener documentos
      docs = requests.get(
          f"https://vantage-us.abbyy.com/api/publicapi/v1/transactions/{transaction_id}/documents",
          headers={"Authorization": f"Bearer {token}"},
      ).json()

      # Descargar el resultado del primer documento
      result_file_id = docs[0]["resultFiles"][0]["id"]

      result = requests.get(
          f"https://vantage-us.abbyy.com/api/publicapi/v1/transactions/{transaction_id}/files/{result_file_id}/download",
          headers={"Authorization": f"Bearer {token}"},
      ).json()

      print(result)
      ```
    </Tab>
  </Tabs>

  El resultado contiene campos extraídos con valores y puntuaciones de confianza.

  <Expandable title="Ejemplo: resultado de la extracción de facturas">
    ```json theme={null}
    {
      "SkillName": "ABBYY Invoice",
      "Documents": [
        {
          "ExtractedData": {
            "RootObject": {
              "Fields": [
                {
                  "Name": "InvoiceNumber",
                  "List": [{
                    "Value": "INV-2024-0042",
                    "Annotation": { "Confidence": 97, "RawValue": "INV-2024-0042" },
                    "NeedVerification": false
                  }]
                },
                {
                  "Name": "VendorName",
                  "List": [{
                    "Value": "Acme Corp",
                    "Annotation": { "Confidence": 95, "RawValue": "Acme Corp" },
                    "NeedVerification": false
                  }]
                },
                {
                  "Name": "TotalAmount",
                  "List": [{
                    "Value": "1,250.00",
                    "Annotation": { "Confidence": 88, "RawValue": "1,250.00" },
                    "NeedVerification": false
                  }]
                }
              ]
            }
          }
        }
      ]
    }
    ```
  </Expandable>

  Cada campo incluye un `Value` (el texto extraído tras la normalización), una puntuación `Annotation.Confidence` de 0 a 100 y un indicador `NeedVerification` que señala si se recomienda revisión humana. Los campos con baja confianza o con errores en las reglas de validación se marcan automáticamente.

  Para obtener una descripción completa de la estructura de salida, consulte [Descripción de los resultados](/es/vantage/getting-started/results).

  ## Ejemplo completo

  <Expandable title="Script completo en Python">
    ```python theme={null}
    import requests
    import time

    # Configuración
    BASE_URL = "https://vantage-us.abbyy.com"
    CLIENT_ID = "YOUR_CLIENT_ID"
    CLIENT_SECRET = "YOUR_CLIENT_SECRET"
    SKILL_ID = "YOUR_SKILL_ID"
    FILE_PATH = "invoice.pdf"

    # Paso 1: Autenticar
    auth = requests.post(
        f"{BASE_URL}/auth2/connect/token",
        data={
            "grant_type": "client_credentials",
            "scope": "openid permissions global.wildcard",
            "client_id": CLIENT_ID,
            "client_secret": CLIENT_SECRET,
        },
    )
    token = auth.json()["access_token"]
    headers = {"Authorization": f"Bearer {token}"}

    # Paso 2: Buscar skills
    skills = requests.get(f"{BASE_URL}/api/publicapi/v1/skills", headers=headers).json()
    print(f"Skills disponibles: {[s['name'] for s in skills]}")

    # Paso 3: Procesar documento
    with open(FILE_PATH, "rb") as f:
        launch = requests.post(
            f"{BASE_URL}/api/publicapi/v1/transactions/launch",
            params={"skillId": SKILL_ID},
            headers=headers,
            files={
                "Model": (None, '{"files": [{}]}', "application/json"),
                "Files": (FILE_PATH, f, "application/pdf"),
            },
        )
    transaction_id = launch.json()["transactionId"]
    print(f"Transacción: {transaction_id}")

    # Paso 4: Consultar hasta completar
    while True:
        tx = requests.get(
            f"{BASE_URL}/api/publicapi/v1/transactions/{transaction_id}",
            headers=headers,
        ).json()
        print(f"Estado: {tx['status']}")
        if tx["status"] in ("Processed", "ProcessedWithWarnings"):
            break
        if tx["status"] == "NotProcessed":
            raise Exception(f"Error en el procesamiento")
        time.sleep(5)

    # Paso 5: Descargar resultados
    docs = requests.get(
        f"{BASE_URL}/api/publicapi/v1/transactions/{transaction_id}/documents",
        headers=headers,
    ).json()

    for doc in docs:
        for rf in doc.get("resultFiles", []):
            result = requests.get(
                f"{BASE_URL}/api/publicapi/v1/transactions/{transaction_id}/files/{rf['id']}/download",
                headers=headers,
            ).json()
            print(result)
    ```
  </Expandable>

  ## Próximos pasos

  <CardGroup cols={2}>
    <Card title="Cómo interpretar sus resultados" icon="magnifying-glass" href="/es/vantage/getting-started/results">
      Aprenda a interpretar los campos extraídos, las puntuaciones de confianza y los datos tabulares.
    </Card>

    <Card title="Referencia de la API" icon="rectangle-terminal" href="/es/vantage/developer/api-introduction">
      Documentación completa de la API con zona de pruebas interactiva.
    </Card>

    <Card title="Opciones de autenticación" icon="lock" href="/es/vantage/developer/authentication/authentication">
      Flujo de código de autorización, ROPC y otros métodos de autenticación.
    </Card>

    <Card title="Procesamiento por lotes" icon="layer-group" href="/es/vantage/developer/processing-documents/processing-documents-with-separate-api-calls">
      Procese varios documentos con llamadas independientes a la API para tener más control.
    </Card>
  </CardGroup>
</VantageRegion>
