# Documento XML

## Introducción

Permite **enviar comprobantes electrónicos en formato XML (no firmado)** codificados, para su posterior procesamiento.

Este enfoque permite a sistemas que ya generan el XML conforme a los esquemas oficiales del SRI, **delegar el proceso de firmado y envío**, centralizando la gestión del certificado digital en un único punto de control.

## Autenticación

Para acceder al servicio de facturación electrónica a través de nuestra API SOAP deben de identificarse y autenticarse usando una credencial única denominada **Clave**.

La autenticación se realiza incluyendo la credencial en el cuerpo del mensaje SOAP, dentro del nodo `<Clave>`. A continuación, se describe la estructura de la solicitud.

Ejemplo:

```xml
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:emis="https://ec.edocnube.com/api/emision" xmlns:com="https://ec.edocnube.com/api/emision/compretencion" xmlns:ext="https://ec.edocnube.com/api/emision/extensiones">
   <soapenv:Header/>
   <soapenv:Body>
      <emis:EmitirFactura>
         <emis:Clave>{CLAVE_VALOR}</Clave>
         <emis:Factura/>
      </emis:EmitirFactura>
   </soapenv:Body>
</soapenv:Envelope>
```

<table><thead><tr><th width="165">Elemento</th><th>Descripción</th></tr></thead><tbody><tr><td>Clave</td><td><strong>Requerido.</strong> Credencial única proporcionada a la empresa para autenticarse. Esta clave es específica y debe mantenerse confidencial.</td></tr></tbody></table>

{% tabs %}
{% tab title="JavaScript" %}

```javascript
 url = '/URL_SOAP_EMISION/EmitirDocumentoService.svc?wsdl';

// XML del mensaje SOAP
const soapRequest = `
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:emis="https://ec.edocnube.com/api/emision" xmlns:com="https://ec.edocnube.com/api/emision/compretencion" xmlns:ext="https://ec.edocnube.com/api/emision/extensiones">
   <soapenv:Header/>
   <soapenv:Body>
      <emis:EmitirFactura>
         <emis:Clave>{CLAVE_VALOR}</Clave>
         <emis:Factura/>
      </emis:EmitirFactura>
   </soapenv:Body>
</soapenv:Envelope>
`;

// Configuración de la solicitud HTTP
const headers = {
  'Content-Type': 'text/xml; charset=utf-8', // Tipo de contenido para SOAP
  SOAPAction: 'http://tempuri.org/EmitirDocumentoService/EmitirFactura', // Acción SOAP específica
};

// Realizar la solicitud con fetch
fetch(url, {
  method: 'POST',
  headers: headers,
  body: soapRequest,
})
  .then((response) => {
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.text();
  })
  .then((data) => {
    console.log('Respuesta SOAP:', data);
  })
  .catch((error) => {
    console.error('Error en la solicitud SOAP:', error.message);
  });

```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
// URL del servicio WSDL
$wsdl = "/URL_SOAP_EMISION/EmitirDocumentoService.svc?wsdl";

try {
    // Crear un cliente SOAP
    $client = new SoapClient($wsdl, [
        'trace' => true,       // Habilitar trazas para depuración
        'cache_wsdl' => WSDL_CACHE_NONE, // No cachear el WSDL
        'exceptions' => true   // Lanzar excepciones en errores
    ]);

    // Parámetros para el método
    $params = [
        "Clave" => "{CLAVE_VALOR}", // Credencial única
        "Factura" => null
    ];

    // Llamar al método
    $response = $client->__soapCall("EmitirFactura", [$params]);

    // Mostrar la respuesta
    echo "Respuesta SOAP:\n";
    print_r($response);
} catch (SoapFault $fault) {
    // Manejo de errores
    echo "Error SOAP: " . $fault->getMessage() . "\n";
    echo "Código de error: " . $fault->faultcode . "\n";
    echo "Detalles:\n" . $fault->detail . "\n";
}
?>

```

{% endtab %}

{% tab title="C#" %}

```csharp
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        string url = "/URL_SOAP_EMISION/EmitirDocumentoService.svc";
        string soapAction = "http://tempuri.org/EmitirDocumentoService/EmitirFactura";
        
        string soapEnvelope = @"<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:emis="https://ec.edocnube.com/api/emision" xmlns:com="https://ec.edocnube.com/api/emision/compretencion" xmlns:ext="https://ec.edocnube.com/api/emision/extensiones">
           <soapenv:Header/>
           <soapenv:Body>
              <emis:EmitirFactura>
                 <emis:Clave>{CLAVE_VALOR}</Clave>
                 <emis:Factura/>
              </emis:EmitirFactura>
           </soapenv:Body>
        </soapenv:Envelope>";

        using (HttpClient client = new HttpClient())
        {
            var request = new HttpRequestMessage(HttpMethod.Post, url)
            {
                Content = new StringContent(soapEnvelope, Encoding.UTF8, "text/xml")
            };
            request.Headers.Add("SOAPAction", soapAction);

            HttpResponseMessage response = await client.SendAsync(request);
            string responseContent = await response.Content.ReadAsStringAsync();

            Console.WriteLine("Respuesta del servidor:");
            Console.WriteLine(responseContent);
        }
    }
}

```

{% endtab %}

{% tab title="Python" %}

```python
import requests

# URL del servicio SOAP
url = "/URL_SOAP_EMISION/EmitirDocumentoService.svc"

# Cabeceras HTTP
headers = {
    "Content-Type": "text/xml; charset=utf-8",
    "SOAPAction": "http://tempuri.org/EmitirDocumentoService/EmitirFactura"
}

# Cuerpo del mensaje SOAP
soap_body = """<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:emis="https://ec.edocnube.com/api/emision" xmlns:com="https://ec.edocnube.com/api/emision/compretencion" xmlns:ext="https://ec.edocnube.com/api/emision/extensiones">
   <soapenv:Header/>
   <soapenv:Body>
      <emis:EmitirFactura>
         <emis:Clave>{CLAVE_VALOR}</Clave>
         <emis:Factura/>
      </emis:EmitirFactura>
   </soapenv:Body>
</soapenv:Envelope>"""

try:
    # Enviar la solicitud POST
    response = requests.post(url, data=soap_body, headers=headers)

    # Verificar el estado de la respuesta
    if response.status_code == 200:
        print("Respuesta del servidor:")
        print(response.text)
    else:
        print(f"Error en la solicitud: {response.status_code}")
        print(response.text)

except requests.exceptions.RequestException as e:
    print(f"Error al realizar la solicitud: {e}")

```

{% endtab %}

{% tab title="Curl" %}

```bash
curl -X POST "/URL_SOAP_EMISION/EmitirDocumentoService.svc" \
-H "Content-Type: text/xml; charset=utf-8" \
-H "SOAPAction: http://tempuri.org/EmitirDocumentoService/EmitirFactura" \
-d '<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:emis="https://ec.edocnube.com/api/emision" xmlns:com="https://ec.edocnube.com/api/emision/compretencion" xmlns:ext="https://ec.edocnube.com/api/emision/extensiones">
   <soapenv:Header/>
   <soapenv:Body>
      <emis:EmitirFactura>
         <emis:Clave>{CLAVE_VALOR}</Clave>
         <emis:Factura/>
      </emis:EmitirFactura>
   </soapenv:Body>
</soapenv:Envelope>'

```

{% endtab %}
{% endtabs %}

## Estados eDoc

La gestión adecuada de los estados eDoc es crucial en el sistema de facturación electrónica, ya que cada estado refleja una etapa específica en el proceso de validación y envío de documentos a la entidad tributaria. A continuación, se presenta una tabla que describe cada uno de los estados eDoc, proporcionando claridad sobre las acciones necesarias según el estado en que se encuentre el documento.

<table><thead><tr><th width="88" align="center">Valor</th><th>Descripción</th><th>Causa</th><th>Solución</th></tr></thead><tbody><tr><td align="center">2</td><td>Documento autorizado por el ente tributario</td><td>Documento autorizado por el SRI</td><td>Ninguna</td></tr><tr><td align="center">3</td><td>Documento no autorizado por el ente tributario</td><td>Documento no superó la validación debido al incumplimiento de las reglas de negocio establecidas por el SRI</td><td>Realizar la corrección de los datos del documento y emitirlo nuevamente</td></tr><tr><td align="center">4</td><td>Error al emitir o consultar el documento en eDoc</td><td>Ha ocurrido un error en eDoc, el cual ha sido identificado con un código para su seguimiento y solución</td><td>Levantar un ticket de atención en el portal de soporte técnico de GuruSoft</td></tr><tr><td align="center">5</td><td>Documento en espera de autorización por parte del ente tributario</td><td>eDoc no pudo establecer una conexión con el SRI para consultar la autorización del documento, se realizará una reconsulta automática posteriormente</td><td>Realizar la consulta del estado del documento mediante la API correspondiente, una vez transcurrido un intervalo de tiempo adecuado</td></tr><tr><td align="center">6</td><td>Documento rechazado por el ente tributario</td><td>Documento no cumplió con las validaciones de estructura y/o formato XML requeridas por el SRI</td><td>Realizar la corrección de los datos del documento y emitirlo nuevamente</td></tr><tr><td align="center">7</td><td>Documento en espera de recepción por parte del ente tributario</td><td>eDoc no pudo establecer una conexión con el SRI para transmitir el documento, se realizará un reenvío automático posteriormente</td><td>Realizar la consulta del estado del documento mediante la API correspondiente, una vez transcurrido un intervalo de tiempo adecuado</td></tr><tr><td align="center">11</td><td>Documento anulado en eDoc</td><td>Documento ha sido anulado por el emisor mediante el portal web del SRI</td><td>Una vez alcanzado este estado, el documento no puede ser modificado ni revertido</td></tr><tr><td align="center">15</td><td>Solicitud de emisión o consulta rechazada por eDoc</td><td>Solicitud de emisión o consulta no cumplió con las validaciones de estructura y/o formato XML requeridas por eDoc</td><td>Realizar la corrección de los datos del documento y emitirlo nuevamente</td></tr><tr><td align="center">18</td><td>Documento no encontrado en eDoc</td><td>Documento consultado no fue encontrando en eDoc</td><td>Realizar la corrección de los parámetros de la consulta y repetir el proceso</td></tr></tbody></table>

## Diccionario de datos

{% embed url="<https://wiki.edocnube.com/diccionario/Documentation/FromXml?classname=&p1=AJkuNFFcBIW7i1zn63Wd0zMug5qnw8YUIJVZZ4GV6wKJLsD/zqmX3g7ojWIfC7B6g7sCzj3eGRxTklfJ+lpnkcR7fXoHZszbiUl1yOPVS6JaBlwF/lISIm/ED8KEQVmI&p2=EoWbYb/FBQ7+HIWWn+AakB3g3J1gzmJ9kA8zwIvk7Vw=&p3=ASz1RE4QhWU=&p4=L5lbnPmTSNE=&p5=42yljgltFnM=&p6=0h6AVWZOsDA=>" %}

## Consumo

### Request

{% tabs %}
{% tab title="JavaScript" %}

```javascript
 url = '/URL_SOAP_EMISION/EmitirDocumentoXmlService.svc?wsdl';

// XML del mensaje SOAP
const soapRequest = `
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:emis="https://ec.edocnube.com/api/emision" xmlns:ns="https://ec.edocnube.com/api/emision/xml" xmlns:ext="https://ec.edocnube.com/api/emision/extensiones">
   <soapenv:Header/>
   <soapenv:Body>
      <emis:EmitirDocumentoXml>
         <emis:Clave>{CLAVE_VALOR}</Clave>
         <emis:DocumentoXml/>
      </emis:EmitirDocumentoXml>
   </soapenv:Body>
</soapenv:Envelope>
`;

// Configuración de la solicitud HTTP
const headers = {
  'Content-Type': 'text/xml; charset=utf-8', // Tipo de contenido para SOAP
  SOAPAction: 'http://tempuri.org/EmitirDocumentoXmlService/EmitirDocumentoXml', // Acción SOAP específica
};

// Realizar la solicitud con fetch
fetch(url, {
  method: 'POST',
  headers: headers,
  body: soapRequest,
})
  .then((response) => {
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.text();
  })
  .then((data) => {
    console.log('Respuesta SOAP:', data);
  })
  .catch((error) => {
    console.error('Error en la solicitud SOAP:', error.message);
  });

```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
// URL del servicio WSDL
$wsdl = "/URL_SOAP_EMISION/EmitirDocumentoXmlService.svc?wsdl";

try {
    // Crear un cliente SOAP
    $client = new SoapClient($wsdl, [
        'trace' => true,       // Habilitar trazas para depuración
        'cache_wsdl' => WSDL_CACHE_NONE, // No cachear el WSDL
        'exceptions' => true   // Lanzar excepciones en errores
    ]);

    // Parámetros para el método
    $params = [
        "Clave" => "{CLAVE_VALOR}", // Credencial única
        "DocumentoXml" => null
    ];

    // Llamar al método
    $response = $client->__soapCall("EmitirDocumentoXml", [$params]);

    // Mostrar la respuesta
    echo "Respuesta SOAP:\n";
    print_r($response);
} catch (SoapFault $fault) {
    // Manejo de errores
    echo "Error SOAP: " . $fault->getMessage() . "\n";
    echo "Código de error: " . $fault->faultcode . "\n";
    echo "Detalles:\n" . $fault->detail . "\n";
}
?>

```

{% endtab %}

{% tab title="C#" %}

```csharp
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        string url = "/URL_SOAP_EMISION/EmitirDocumentoXmlService.svc";
        string soapAction = "http://tempuri.org/EmitirDocumentoXmlService/EmitirDocumentoXml";
        
        string soapEnvelope = @"<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:emis="https://ec.edocnube.com/api/emision" xmlns:ns="https://ec.edocnube.com/api/emision/xml" xmlns:ext="https://ec.edocnube.com/api/emision/extensiones">
           <soapenv:Header/>
           <soapenv:Body>
              <emis:EmitirDocumentoXml>
                 <emis:Clave>{CLAVE_VALOR}</Clave>
                 <emis:DocumentoXml/>
              </emis:EmitirDocumentoXml>
           </soapenv:Body>
        </soapenv:Envelope>";

        using (HttpClient client = new HttpClient())
        {
            var request = new HttpRequestMessage(HttpMethod.Post, url)
            {
                Content = new StringContent(soapEnvelope, Encoding.UTF8, "text/xml")
            };
            request.Headers.Add("SOAPAction", soapAction);

            HttpResponseMessage response = await client.SendAsync(request);
            string responseContent = await response.Content.ReadAsStringAsync();

            Console.WriteLine("Respuesta del servidor:");
            Console.WriteLine(responseContent);
        }
    }
}

```

{% endtab %}

{% tab title="Python" %}

```python
import requests

# URL del servicio SOAP
url = "/URL_SOAP_EMISION/EmitirDocumentoXmlService.svc"

# Cabeceras HTTP
headers = {
    "Content-Type": "text/xml; charset=utf-8",
    "SOAPAction": "http://tempuri.org/EmitirDocumentoXmlService/EmitirDocumentoXml"
}

# Cuerpo del mensaje SOAP
soap_body = """<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:emis="https://ec.edocnube.com/api/emision" xmlns:ns="https://ec.edocnube.com/api/emision/xml" xmlns:ext="https://ec.edocnube.com/api/emision/extensiones">
   <soapenv:Header/>
   <soapenv:Body>
      <emis:EmitirDocumentoXml>
         <emis:Clave>{CLAVE_VALOR}</Clave>
         <emis:DocumentoXml/>
      </emis:EmitirDocumentoXml>
   </soapenv:Body>
</soapenv:Envelope>"""

try:
    # Enviar la solicitud POST
    response = requests.post(url, data=soap_body, headers=headers)

    # Verificar el estado de la respuesta
    if response.status_code == 200:
        print("Respuesta del servidor:")
        print(response.text)
    else:
        print(f"Error en la solicitud: {response.status_code}")
        print(response.text)

except requests.exceptions.RequestException as e:
    print(f"Error al realizar la solicitud: {e}")
```

{% endtab %}

{% tab title="Curl" %}

```bash
curl -X POST "/URL_SOAP_EMISION/EmitirDocumentoXmlService.svc" \
-H "Content-Type: text/xml; charset=utf-8" \
-H "SOAPAction: http://tempuri.org/EmitirDocumentoXmlService/EmitirDocumentoXml" \
-d '<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:emis="https://ec.edocnube.com/api/emision" xmlns:ns="https://ec.edocnube.com/api/emision/xml" xmlns:ext="https://ec.edocnube.com/api/emision/extensiones">
   <soapenv:Header/>
   <soapenv:Body>
      <emis:EmitirDocumentoXml>
         <emis:Clave>{CLAVE_VALOR}</Clave>
         <emis:DocumentoXml/>
      </emis:EmitirDocumentoXml>
   </soapenv:Body>
</soapenv:Envelope>'
```

{% endtab %}
{% endtabs %}

### Response

En una comunicación SOAP, las respuestas HTTP pueden variar según el estado y el contenido de la comunicación:

* **200 (OK)**: La solicitud se procesó correctamente y devuelve un mensaje SOAP en XML con los detalles de la respuesta.

Estas respuestas permiten manejar adecuadamente los distintos escenarios de comunicación.

{% tabs %}
{% tab title="Estado HTTP 200" %}

```xml
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <EmitirDocumentoXmlResponse xmlns="https://ec.edocnube.com/api/emision" xmlns:a="https://ec.edocnube.com/api/emision/xml" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
         <a:Estado>2</a:Estado>
         <a:ClaveAcceso>2404202501099273796400110010150000000224276851318</a:ClaveAcceso>
         <a:NumAutorizacion>2404202501099273796400110010150000000224276851318</a:NumAutorizacion>
         <a:FechaAutorizacion>2025-06-09T17:29:24.000-05:00</a:FechaAutorizacion>
      </EmitirDocumentoXmlResponse>
   </s:Body>
</s:Envelope>
```

{% endtab %}
{% endtabs %}
