# QI Tech — Lending-as-a-Service › Documentos

Documentação da QI Tech em texto corrido, para colar em um LLM.
Fonte: https://docs.qitech.com.br
2 página(s).

Índice:
- Consulta de documentos (/documentation/upload_de_documentos/consulta_documents)
- Upload de documentos (/documentation/upload_de_documentos/)

---

# Consulta de documentos

URL: /documentation/upload_de_documentos/consulta_documents

A consulta do documento poderá ser feita a partir da requisição:

### Request

ENDPOINT /document/[document_key]/url
MÉTODO GET

### Path Params

| Campo          | Descrição                              |
|--------------- |----------------------------------------|
| `document_key` | Chave única do documento               |

:::caution Atenção
A url do documento será gerada com um prazo de expiração de 10 minutos.
:::

### Response

STATUS 200

Response Body

```json
{
	"document_key": "8a1e62f3-7add-4240-a51d-e0f1a2f421fa",
	"document_url": "url_expirável",
	"signed_document_url": "url_expirável",
	"expiration_datetime": "2024-05-01T01:00:00.000Z"
}
```

| Campo 				| Tipo   | Descrição                                                                                               | 
|-----------------------|--------|---------------------------------------------------------------------------------------------------------|
| `document_url`* 		| string | URL expirável do documento original.                                                                    |
| `signed_document_url` | string | URL expirável do documento assinado se houver. Em caso de não existência não iremos retornar esse campo.|
| `expiration_datetime`*| string | Data e hora do momento em que ocorrerá a expiração das urls.                                            |

---

# Upload de documentos

URL: /documentation/upload_de_documentos/

---

A chamada deve ser autenticada seguindo o padrão descrito na seção [1.1.3. Teste de Autenticação](../primeiros_passos/teste_de_autenticacao). Com as seguintes ressalvas:

- O valor da variável **md5_hash** (**md5_body** para a v1 da nossa autenticação) enviada na assinatura do header deverá ser o MD5 do binário do arquivo que está sendo enviado
- O binário do arquivo deve ser enviado no corpo da request como um FormData utilizando como chave a string "file" e no valor o arquivo a ser enviado. (Este conteúdo não é encriptado)
- No body de resposta dessa chamada será enviado um GUID que é o identificador do documento (chamado de DOCUMENT_KEY daqui para frente) e deve ser armazenado para uso futuro.

---

## Request

ENDPOINT /upload
MÉTODO POST

Response Body

```json
{
  "document_key": "cfbc8469-89ea-4a80-9f64-ba7b1566c68b",
  "document_md5": "cd451103fa512frc98ce684d3896698c"
}
```

:::caution Atenção
Lembrar de salvar a **document_key**, chave essa necessária para a consulta do documento.
:::

## Exemplo de chamada

Exemplo para upload de uma imagem a partir de uma URL.

**Python**

```python

import jwt
import hashlib
import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder
import json
from datetime import datetime

BASE_URL = "https://api-auth.sandbox.qitech.app"
API_KEY = "4c268c0a-53ff-429b-92b6-47ef98a6d89a" # Esta chave é um exemplo, por favor utilize sua própria chave
CLIENT_PRIVATE_KEY = ''''
-----BEGIN EC PRIVATE KEY-----
MIHbAgEBBEHh1hIeOPE5XNNhn6bxRAmVswsPZ0wZCmzVvP8Tl/LZK9ofVmRVGzll
srU1uezJEyHKYdOHrE2p52xUj+pHzjJvb6AHBgUrgQQAI6GBiQOBhgAEAAofUz1J
hBSOyGHLsnV9Sz0DSWmhl7U+ljqbfa8PKVFWSV3w16I1v2zME5/UzUhHn1gWsjnv
7/ekcLLAQbvqMPNXAfjIhFXLAPzqbB9iCuVua1v0Vgy52rBemOWrJka/Ws2bnKR8
h1N1OxOYeYr6C2jqMygBLktKMAs+282CEiEb4bIv
-----END EC PRIVATE KEY----- 
''' # Esta chave é um exemplo, por favor utilize sua própria chave

def get_document(url):
    try:
        response = requests.get(url)
        return response.content
    except Exception as error:
        print("Error fetching document:", error)
        raise

def upload_document(array_buffer):
    endpoint = "/upload"
    method = "POST"
    timestamp = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z"
    md5_hash = hashlib.md5(array_buffer).hexdigest()

    jwt_header = {
        "typ": "JWT",
        "alg": "ES512",
    }

    jwt_body = {
        "payload_md5": md5_hash,
        "timestamp": timestamp,
        "method": method,
        "uri": endpoint,
    }

    encoded_header_token = jwt.encode(jwt_body, CLIENT_PRIVATE_KEY, algorithm="ES512", headers=jwt_header)

    signed_header = {
        "Authorization": encoded_header_token,
        "API-CLIENT-KEY": API_KEY,
        "Content-Type": "multipart/form-data",
    }

    url = f"{BASE_URL}{endpoint}"
    multipart_data = MultipartEncoder(
        fields={'file': ('image.jpeg', array_buffer, 'image/jpeg')}
    )
    signed_header['Content-Type'] = multipart_data.content_type

    try:
        response = requests.post(url, headers=signed_header, data=multipart_data)
        response_data = response.json()
        document_key = response_data.get('document_key')
        print(f'Response data is: {response_data} and document_key is: {document_key}')
        return document_key
    except Exception as error:
        print('Error:', error)
        raise

def main():
    file_url = "{FILE_URL}"

    document_buffer = get_document(file_url)

    document_key = upload_document(document_buffer)

    print("document_key is", document_key)

if __name__ == "__main__":
    main()

```
  

**Node.js**

```js
const jwt = require('jsonwebtoken')
const crypto = require('crypto')
const axios = require('axios')
const FormData = require('form-data')
const fs = require('fs')
const fetch = require('node-fetch')

async function getDocument(url) {
  try {
    const response = await axios.get(url, { responseType: 'arraybuffer' })
    return response.data
  } catch (error) {
    console.error('Error fetching document:', error)
    throw error
  }
}

async function uploadDocument(arrayBuffer) {
  const base_url = "[https://api-auth.sandbox.qitech.app](https://api-auth.sandbox.qitech.app)"
  const endpoint = '/upload'
  const method = 'POST'
  const timestamp = new Date().toISOString()
  const md5_hash = crypto.createHash('md5').update(arrayBuffer).digest('hex')
  const client_private_key = `-----BEGIN EC PRIVATE KEY-----
    MIHbAgEBBEHh1hIeOPE5XNNhn6bxRAmVswsPZ0wZCmzVvP8Tl/LZK9ofVmRVGzll
    srU1uezJEyHKYdOHrE2p52xUj+pHzjJvb6AHBgUrgQQAI6GBiQOBhgAEAAofUz1J
    hBSOyGHLsnV9Sz0DSWmhl7U+ljqbfa8PKVFWSV3w16I1v2zME5/UzUhHn1gWsjnv
    7/ekcLLAQbvqMPNXAfjIhFXLAPzqbB9iCuVua1v0Vgy52rBemOWrJka/Ws2bnKR8
    h1N1OxOYeYr6C2jqMygBLktKMAs+282CEiEb4bIv
    -----END EC PRIVATE KEY-----`; // This key is an example, please use your own
  const api_key = '4c268c0a-53ff-429b-92b6-47ef98a6d89a' // This key is an example, please use your own

  try {
    const jwt_header = {
      typ: 'JWT',
      alg: 'ES512',
    }

    const jwt_body = {
      payload_md5: md5_hash,
      timestamp: timestamp,
      method: method,
      uri: endpoint,
    }

    const encoded_header_token = jwt.sign(jwt_body, client_private_key, {
      algorithm: 'ES512',
      header: jwt_header,
    })

    const signed_header = {
      AUTHORIZATION: encoded_header_token,
      'API-CLIENT-KEY': api_key,
    }

    const url = `${base_url}${endpoint}`
    const formData = new FormData()
    formData.append('file', Buffer.from(arrayBuffer), {
      filename: 'image.jpeg',
    })

    const response = await fetch(url, {
      method: 'POST',
      headers: {
        ...signed_header,
        ...formData.getHeaders(),
      },
      body: formData,
    })

    if (!response.ok) {
      const errorText = await response.text()
      console.log(`Error: ${response.status} ${response.statusText}`, errorText)
      return
    }

    const data = await response.json()
    console.log('Response data is: ', data)
    return data.document_key
    
  } catch (error) {
    console.error('Error:', error)
  }
}

async function main() {
  const fileUrl = '<URL_LINK_TO_DOCUMENT_IMAGE>'
  const documentBuffer = await getDocument(fileUrl)
  const documentKey = await uploadDocument(documentBuffer)

  console.log('Document key is: ' + documentKey)
}

main()
```

- OBS: O exemplo acima utiliza a biblioteca [node-fetch](https://www.npmjs.com/package/node-fetch) para realizar a chamada, mas você pode utilizar a biblioteca de sua preferência. O importante é que a chamada seja feita com o método POST, com o header `Content-Type` com o valor `multipart/form-data` e o body seja um FormData com a chave `file` e o valor o binário do arquivo a ser enviado.

:::warning Aviso
A blibioteca 'Axios' está com um bug que faz com que o FormData seja enviado vazio. A issue pode ser vista no [repositório no GitHub](https://github.com/axios/axios/issues/5986). Caso este problema ainda não tenha sido resolvido no momento de sua integração, sugerimos a utilização da biblioteca 'node-fetch' para realizar esta chamada.
:::