## Arquivos do contrato público

- [Especificação OpenAPI em JSON](/downloads/kyc/openapi.json)
- [Coleção Postman](/downloads/kyc/postman-collection.json)
- [Ambiente Postman sem credenciais](/downloads/kyc/postman-environment.json)

Importe os arquivos e configure somente no seu ambiente privado a URL oficial e a chave habilitada. Não publique um workspace com segredos. Os exemplos abaixo usam dados fictícios; os timeouts são escolhas demonstrativas do cliente, não um SLA.

## Exemplos HTTP no backend

Criar transação KYC

### cURL

```bash
# Server-side only. Configure KYC_API_BASE_URL with your authorized base (https://api.example.invalid is illustrative), and KYC_API_KEY privately. Never expose credentials in browser code.
set -eu
: "${KYC_API_BASE_URL:?Set authorized base}" "${KYC_API_KEY:?Set API key}"
: "${KYC_IDEMPOTENCY_KEY:?Persist the key for this creation intent}"
curl --fail-with-body --max-time 15 --request POST \
  "${KYC_API_BASE_URL%/}/v1/face-auth/transactions" \
  --header "X-API-Key: ${KYC_API_KEY}" \
  --header "Idempotency-Key: ${KYC_IDEMPOTENCY_KEY}" \
  --header 'Content-Type: application/json' \
  --data-binary '{"country_code":"BR","external_id":"docs-example-0001","locale":"pt-BR","subject":{"identity":{"country":"BR","number":"00000000000","type":"CPF"}}}'
# Persist transaction_id and business correlation; use the returned links.webview_url. Read status, decision and decision_reason together. Reuse the SAME idempotency key AND original payload only for the same creation intent; never silently bypass a 409 conflict.
```

### JavaScript / Node.js

```javascript
import process from "node:process";
// Server-side only. Configure KYC_API_BASE_URL with your authorized base (https://api.example.invalid is illustrative), and KYC_API_KEY privately. Never expose credentials in browser code.
function required(name) {
  const value = process.env[name];
  if (!value) throw new Error("Missing configuration: " + name);
  return value;
}
const base = required("KYC_API_BASE_URL").replace(/\/$/, "");
const response = await fetch(base + "/v1/face-auth/transactions", {
  method: "POST",
  headers: { "X-API-Key": required("KYC_API_KEY"), "Content-Type": "application/json", "Idempotency-Key": required("KYC_IDEMPOTENCY_KEY") },
  body: "{\"country_code\":\"BR\",\"external_id\":\"docs-example-0001\",\"locale\":\"pt-BR\",\"subject\":{\"identity\":{\"country\":\"BR\",\"number\":\"00000000000\",\"type\":\"CPF\"}}}",
  signal: AbortSignal.timeout(15_000),
});
if (response.status !== 201) throw new Error("KYC HTTP " + response.status);
const transaction = await response.json();
console.log("HTTP " + response.status);
// Persist transaction_id and business correlation; use the returned links.webview_url. Read status, decision and decision_reason together. Reuse the SAME idempotency key AND original payload only for the same creation intent; never silently bypass a 409 conflict.
```

### TypeScript / Node.js

```typescript
import process from "node:process";
// Server-side only. Configure KYC_API_BASE_URL with your authorized base (https://api.example.invalid is illustrative), and KYC_API_KEY privately. Never expose credentials in browser code.
function required(name: string): string {
  const value = process.env[name];
  if (!value) throw new Error("Missing configuration: " + name);
  return value;
}
const base = required("KYC_API_BASE_URL").replace(/\/$/, "");
const response = await fetch(base + "/v1/face-auth/transactions", {
  method: "POST",
  headers: { "X-API-Key": required("KYC_API_KEY"), "Content-Type": "application/json", "Idempotency-Key": required("KYC_IDEMPOTENCY_KEY") },
  body: "{\"country_code\":\"BR\",\"external_id\":\"docs-example-0001\",\"locale\":\"pt-BR\",\"subject\":{\"identity\":{\"country\":\"BR\",\"number\":\"00000000000\",\"type\":\"CPF\"}}}",
  signal: AbortSignal.timeout(15_000),
});
if (response.status !== 201) throw new Error("KYC HTTP " + response.status);
const transaction: unknown = await response.json();
// Validate the response against the curated OpenAPI before using it.
console.log("HTTP " + response.status);
// Persist transaction_id and business correlation; use the returned links.webview_url. Read status, decision and decision_reason together. Reuse the SAME idempotency key AND original payload only for the same creation intent; never silently bypass a 409 conflict.
```

### Python

```python
import json
import os
from urllib.parse import quote
from urllib.request import Request, urlopen
# Server-side only. Configure KYC_API_BASE_URL with your authorized base (https://api.example.invalid is illustrative), and KYC_API_KEY privately. Never expose credentials in browser code.
base = os.environ["KYC_API_BASE_URL"].rstrip("/")
request = Request(base + "/v1/face-auth/transactions",
    method="POST",
    headers={"X-API-Key": os.environ["KYC_API_KEY"], "Content-Type": "application/json",
             "Idempotency-Key": os.environ["KYC_IDEMPOTENCY_KEY"]},
    data="{\"country_code\":\"BR\",\"external_id\":\"docs-example-0001\",\"locale\":\"pt-BR\",\"subject\":{\"identity\":{\"country\":\"BR\",\"number\":\"00000000000\",\"type\":\"CPF\"}}}".encode("utf-8"),
)
with urlopen(request, timeout=15) as response:
    if response.status != 201:
        raise RuntimeError("KYC HTTP " + str(response.status))
    transaction = json.load(response)
    print("HTTP " + str(response.status))
# Persist transaction_id and business correlation; use the returned links.webview_url. Read status, decision and decision_reason together. Reuse the SAME idempotency key AND original payload only for the same creation intent; never silently bypass a 409 conflict.
```

### PHP

```php
<?php
// PHP 8+, standard HTTP streams. Server-side only. Configure KYC_API_BASE_URL with your authorized base (https://api.example.invalid is illustrative), and KYC_API_KEY privately. Never expose credentials in browser code.
function required(string $name): string {
    $value = getenv($name);
    if ($value === false || $value === '') throw new RuntimeException("Missing configuration: " . $name);
    return $value;
}
$url = rtrim(required('KYC_API_BASE_URL'), '/') . '/v1/face-auth/transactions';
$headers = ['X-API-Key: ' . required('KYC_API_KEY'), 'Content-Type: application/json', 'Idempotency-Key: ' . required('KYC_IDEMPOTENCY_KEY')];
$context = stream_context_create(['http' => ['method' => 'POST', 'header' => implode("\r\n", $headers),
    'timeout' => 15, 'ignore_errors' => true, 'content' => '{"country_code":"BR","external_id":"docs-example-0001","locale":"pt-BR","subject":{"identity":{"country":"BR","number":"00000000000","type":"CPF"}}}']]);
$body = file_get_contents($url, false, $context);
if ($body === false) throw new RuntimeException('KYC transport failure');
if (!preg_match('/^HTTP\/\S+ ([0-9]{3})/', $http_response_header[0] ?? '', $matches)) throw new RuntimeException('Invalid HTTP response');
$status = (int) $matches[1];
if ($status !== 201) throw new RuntimeException('KYC HTTP ' . $status);
$transaction = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
echo 'HTTP ' . $status . PHP_EOL;
// Persist transaction_id and business correlation; use the returned links.webview_url. Read status, decision and decision_reason together. Reuse the SAME idempotency key AND original payload only for the same creation intent; never silently bypass a 409 conflict.
```

### C# / .NET

```csharp
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
// .NET 8+. Server-side only. Configure KYC_API_BASE_URL with your authorized base (https://api.example.invalid is illustrative), and KYC_API_KEY privately. Never expose credentials in browser code.
static string Required(string name) => Environment.GetEnvironmentVariable(name) is { Length: > 0 } value ? value : throw new Exception("Missing configuration: " + name);
using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(15) };
using var request = new HttpRequestMessage(HttpMethod.Post, Required("KYC_API_BASE_URL").TrimEnd('/') + "/v1/face-auth/transactions");
request.Headers.Add("X-API-Key", Required("KYC_API_KEY"));
request.Headers.Add("Idempotency-Key", Required("KYC_IDEMPOTENCY_KEY"));
request.Content = new StringContent("{\"country_code\":\"BR\",\"external_id\":\"docs-example-0001\",\"locale\":\"pt-BR\",\"subject\":{\"identity\":{\"country\":\"BR\",\"number\":\"00000000000\",\"type\":\"CPF\"}}}", Encoding.UTF8, "application/json");
using var response = await client.SendAsync(request);
if ((int)response.StatusCode != 201) throw new Exception("KYC HTTP " + (int)response.StatusCode);
using var transaction = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
Console.WriteLine("HTTP " + (int)response.StatusCode);
// Persist transaction_id and business correlation; use the returned links.webview_url. Read status, decision and decision_reason together. Reuse the SAME idempotency key AND original payload only for the same creation intent; never silently bypass a 409 conflict.
```

### Java

```java
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.*;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
// Java 17+. Server-side only. Configure KYC_API_BASE_URL with your authorized base (https://api.example.invalid is illustrative), and KYC_API_KEY privately. Never expose credentials in browser code.
class Example {
  static String required(String name) {
    String value = System.getenv(name);
    if (value == null || value.isEmpty()) throw new IllegalStateException("Missing configuration: " + name);
    return value;
  }
  public static void main(String[] args) throws Exception {
    String base = required("KYC_API_BASE_URL").replaceAll("/+$", "");
    String url = base + "/v1/face-auth/transactions";
    var builder = HttpRequest.newBuilder(URI.create(url)).timeout(Duration.ofSeconds(15))
        .header("X-API-Key", required("KYC_API_KEY"));
    builder.header("Idempotency-Key", required("KYC_IDEMPOTENCY_KEY"))
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString("{\"country_code\":\"BR\",\"external_id\":\"docs-example-0001\",\"locale\":\"pt-BR\",\"subject\":{\"identity\":{\"country\":\"BR\",\"number\":\"00000000000\",\"type\":\"CPF\"}}}", StandardCharsets.UTF_8));
    var response = HttpClient.newHttpClient().send(builder.build(), HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
    if (response.statusCode() != 201) throw new IllegalStateException("KYC HTTP " + response.statusCode());
    System.out.println("HTTP " + response.statusCode());
    // Parse response.body() with your application's JSON parser and validate against OpenAPI.
    // Persist transaction_id and business correlation; use the returned links.webview_url. Read status, decision and decision_reason together. Reuse the SAME idempotency key AND original payload only for the same creation intent; never silently bypass a 409 conflict.
  }
}
```

### Go

```go
package main
import (
  "encoding/json"
  "fmt"
  "net/http"
  "net/url"
  "os"
  "strings"
  "time"
)
// Server-side only. Configure KYC_API_BASE_URL with your authorized base (https://api.example.invalid is illustrative), and KYC_API_KEY privately. Never expose credentials in browser code.
func required(name string) string {
  value := os.Getenv(name); if value == "" { panic("Missing configuration: " + name) }; return value
}
func main() {
  _ = url.PathEscape // Used by the GET variant.
  endpoint := strings.TrimRight(required("KYC_API_BASE_URL"), "/") + "/v1/face-auth/transactions"
  request, err := http.NewRequest("POST", endpoint, strings.NewReader(`{"country_code":"BR","external_id":"docs-example-0001","locale":"pt-BR","subject":{"identity":{"country":"BR","number":"00000000000","type":"CPF"}}}`)); if err != nil { panic(err) }
  request.Header.Set("X-API-Key", required("KYC_API_KEY"))
  request.Header.Set("Content-Type", "application/json")
  request.Header.Set("Idempotency-Key", required("KYC_IDEMPOTENCY_KEY"))
  response, err := (&http.Client{Timeout: 15*time.Second}).Do(request); if err != nil { panic(err) }; defer response.Body.Close()
  if response.StatusCode != 201 { panic(fmt.Sprintf("KYC HTTP %d", response.StatusCode)) }
  var transaction map[string]any
  if err := json.NewDecoder(response.Body).Decode(&transaction); err != nil { panic(err) }
  fmt.Printf("HTTP %d\n", response.StatusCode)
  // Persist transaction_id and business correlation; use the returned links.webview_url. Read status, decision and decision_reason together. Reuse the SAME idempotency key AND original payload only for the same creation intent; never silently bypass a 409 conflict.
}
```


Esses trechos mostram a criação básica; não são SDKs oficiais nem consumidores completos. Acrescente validação de configuração, persistência, tratamento de erros e repetição idempotente conforme sua aplicação. Uma intenção de criação nova deve receber outra chave; uma tentativa técnica deve preservar a anterior e o mesmo payload.

Para cURL, veja o [início rápido](/pt-BR/desenvolvedores/kyc/inicio-rapido). Para o receptor de eventos, siga [validação HMAC](/pt-BR/desenvolvedores/kyc/validar-assinatura-hmac) e [reconciliação](/pt-BR/desenvolvedores/kyc/reentrega-e-reconciliacao). O [simulador](/pt-BR/desenvolvedores/kyc/simulador) demonstra cenários fixos sem acessar a API real.
