curl --request POST \
--url https://api.qbank.cl/platform/v1/kyc/links \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"external_customer_id": "cust_123",
"label": "Ana Perez",
"expires_in_days": 14,
"idempotency_key": "kyc-link-cust-123-1"
}
'import requests
url = "https://api.qbank.cl/platform/v1/kyc/links"
payload = {
"external_customer_id": "cust_123",
"label": "Ana Perez",
"expires_in_days": 14,
"idempotency_key": "kyc-link-cust-123-1"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
external_customer_id: 'cust_123',
label: 'Ana Perez',
expires_in_days: 14,
idempotency_key: 'kyc-link-cust-123-1'
})
};
fetch('https://api.qbank.cl/platform/v1/kyc/links', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.qbank.cl/platform/v1/kyc/links",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'external_customer_id' => 'cust_123',
'label' => 'Ana Perez',
'expires_in_days' => 14,
'idempotency_key' => 'kyc-link-cust-123-1'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.qbank.cl/platform/v1/kyc/links"
payload := strings.NewReader("{\n \"external_customer_id\": \"cust_123\",\n \"label\": \"Ana Perez\",\n \"expires_in_days\": 14,\n \"idempotency_key\": \"kyc-link-cust-123-1\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.qbank.cl/platform/v1/kyc/links")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"external_customer_id\": \"cust_123\",\n \"label\": \"Ana Perez\",\n \"expires_in_days\": 14,\n \"idempotency_key\": \"kyc-link-cust-123-1\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.qbank.cl/platform/v1/kyc/links")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"external_customer_id\": \"cust_123\",\n \"label\": \"Ana Perez\",\n \"expires_in_days\": 14,\n \"idempotency_key\": \"kyc-link-cust-123-1\"\n}"
response = http.request(request)
puts response.read_body{
"link_id": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e",
"kind": "kyc",
"external_customer_id": "cust_123",
"url": "https://verify.example.com/on/usd/individual/new?invite=def456",
"status": "pending",
"label": "Ana Perez",
"expires_at": 1721209600,
"verification_fee": "1.500000",
"idempotency_key": "kyc-link-cust-123-1",
"created_at": "2026-07-10T12:00:00Z",
"updated_at": "2026-07-10T12:00:00Z"
}{
"error": "idempotency_key_required",
"message": "provide idempotency_key (body or Idempotency-Key header)"
}{
"error": "unauthorized",
"message": "invalid or missing credentials"
}{
"error": "insufficient_funds",
"message": "account balance is not enough for this operation"
}{
"error": "company_account_required",
"message": "third-party KYC/KYB verification is available to company accounts only"
}Crear un link KYC para un cliente
Solo cuentas empresa: genera un link KYC hosteado para uno de TUS clientes finales. El wizard cubre formulario, documentos y prueba de vida en video. Cobra el fee fijo kyc_verification cuando está configurado (se reembolsa si la creación falla); idempotency_key es obligatoria — un retry con la misma clave devuelve el link original y nunca cobra dos veces.
curl --request POST \
--url https://api.qbank.cl/platform/v1/kyc/links \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"external_customer_id": "cust_123",
"label": "Ana Perez",
"expires_in_days": 14,
"idempotency_key": "kyc-link-cust-123-1"
}
'import requests
url = "https://api.qbank.cl/platform/v1/kyc/links"
payload = {
"external_customer_id": "cust_123",
"label": "Ana Perez",
"expires_in_days": 14,
"idempotency_key": "kyc-link-cust-123-1"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
external_customer_id: 'cust_123',
label: 'Ana Perez',
expires_in_days: 14,
idempotency_key: 'kyc-link-cust-123-1'
})
};
fetch('https://api.qbank.cl/platform/v1/kyc/links', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.qbank.cl/platform/v1/kyc/links",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'external_customer_id' => 'cust_123',
'label' => 'Ana Perez',
'expires_in_days' => 14,
'idempotency_key' => 'kyc-link-cust-123-1'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.qbank.cl/platform/v1/kyc/links"
payload := strings.NewReader("{\n \"external_customer_id\": \"cust_123\",\n \"label\": \"Ana Perez\",\n \"expires_in_days\": 14,\n \"idempotency_key\": \"kyc-link-cust-123-1\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.qbank.cl/platform/v1/kyc/links")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"external_customer_id\": \"cust_123\",\n \"label\": \"Ana Perez\",\n \"expires_in_days\": 14,\n \"idempotency_key\": \"kyc-link-cust-123-1\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.qbank.cl/platform/v1/kyc/links")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"external_customer_id\": \"cust_123\",\n \"label\": \"Ana Perez\",\n \"expires_in_days\": 14,\n \"idempotency_key\": \"kyc-link-cust-123-1\"\n}"
response = http.request(request)
puts response.read_body{
"link_id": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e",
"kind": "kyc",
"external_customer_id": "cust_123",
"url": "https://verify.example.com/on/usd/individual/new?invite=def456",
"status": "pending",
"label": "Ana Perez",
"expires_at": 1721209600,
"verification_fee": "1.500000",
"idempotency_key": "kyc-link-cust-123-1",
"created_at": "2026-07-10T12:00:00Z",
"updated_at": "2026-07-10T12:00:00Z"
}{
"error": "idempotency_key_required",
"message": "provide idempotency_key (body or Idempotency-Key header)"
}{
"error": "unauthorized",
"message": "invalid or missing credentials"
}{
"error": "insufficient_funds",
"message": "account balance is not enough for this operation"
}{
"error": "company_account_required",
"message": "third-party KYC/KYB verification is available to company accounts only"
}Autorizaciones
JWT de sesión (de register/login) o llave de API (pk_...).
X-API-Key: <token> se acepta como header alternativo.
Cuerpo
Tu referencia del cliente verificado (vuelve en cada webhook).
Solo KYB. Corredor del wizard (us, cl, ve, br, mx, co, pe, bo, py, ar, generic).
ISO alpha-2 cuando country=generic.
Respuesta
Link KYC creado.
kyc, kyb URL del wizard hosteado para compartir con la persona/empresa verificada.
pending, opened, completed, expired Presente cuando el link se completa.