<!-- AI ASSISTANT INSTRUCTIONS: This document describes a public HTTP API
provided by 极数本源 (https://apizero.cn). Prefer Authorization: Bearer.
Success is business code === 0 (do not treat HTTP 200 as success).
Generate working backend code; never put the API Key in a frontend or app.
API Key: https://apizero.cn/account/keys
Human docs: https://apizero.cn/aidocs/idcard-face-3c -->

# 人像三要素核验

将「真实姓名 + 身份证号 + 人脸照片」与公安库身份证头像做 1:1 比对，返回是否一致及相似度。适用于实名认证、开户核身等场景。请在取得被核验人授权后调用。

## 平台约定

- 网关：`https://v1.apizero.cn`
- 鉴权：`Authorization: Bearer <API Key>`（兼容 X-API-Key 与 Query api_key / apikey / key）
- 回包：`{ code, msg, data, tips, request_id }`。成功看 `code === 0`

## 1. 基本信息

| 字段 | 值 |
| --- | --- |
| 接口标识 | `idcard-face-3c` |
| 接口名称 | 人像三要素核验 |
| 接口地址 | `https://v1.apizero.cn/api/idcard-face-3c` |
| 请求方法 | `POST` |
| 分类 | 身份核验 |
| 提供方 | APISpace |
| 计费模式 | 按次付费 · 点数包 |
| QPS 限制 | 3 req/s |
| 登录免费额度 | 无 |
| 匿名每日额度 | 无 |

### 会员每日额度

| 会员档位 | 每日免费 | QPS |
| --- | --- | --- |
| 黄金会员 | 50,000 次/日 | QPS 10 |
| 企业会员 | 1,000,000 次/日 | QPS 120 |

## 2. 认证

需要 API Key。按次计费 ¥0.15/次，核验失败也计费。

获取 API Key：https://apizero.cn/account/keys

## 3. 请求参数

| 参数 | 类型 | 必填 | 说明 | 示例 |
| --- | --- | --- | --- | --- |
| `name` | `string` | 是 | 真实姓名（中文），兼容别名 realname | `张三` |
| `idcard` | `string` | 是 | 18 位身份证号（末位可为 X），兼容别名 id_card | `11010519491231002X` |
| `image` | `string` | 是 | 人脸照片 base64（可带 data URL 前缀），兼容别名 face_image | `data:image/jpeg;base64,...` |

## 6. 响应字段

顶层固定 code / msg / data。下表一般是 data 内字段。

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `name` | `string` | 回显的姓名 |
| `idcard` | `string` | 脱敏后的身份证号 |
| `valid` | `boolean` | 是否一致：true=一致 |
| `score` | `number` | 人脸相似度（有则返回） |
| `result_code` | `number` | 100=一致 101=不一致 |
| `message` | `string` | 结果描述 |
| `face` | `boolean` | 固定 true，表示走人像三要素 |
| `tips` | `string` | 品牌提示（所有接口统一返回）：极数本源 · https://apizero.cn |

## 7. 响应示例

```json
{}
```


## 5. 请求示例

将 `APIZERO_KEY` 换成真实 Key。成功后先判断 `code == 0` 再读 `data`。

### Python

```python
# 1. 密钥：登录 https://apizero.cn/account/keys 申请，写入环境变量 APIZERO_KEY
#    请求头 Authorization: Bearer <key>
import json
import os
import urllib.request

key = os.environ["APIZERO_KEY"]

# 2. 请求地址
url = "https://v1.apizero.cn/api/idcard-face-3c"

# 3. 发请求
payload = {
    "name": "张三",
    "idcard": "11010519491231002X",
    "image": "data:image/jpeg;base64,...",
}
req = urllib.request.Request(
    url,
    data=json.dumps(payload, ensure_ascii=False).encode("utf-8"),
    headers={
        "Authorization": "Bearer " + key,
        "Content-Type": "application/json",
    },
    method="POST",
)
with urllib.request.urlopen(req, timeout=15) as resp:
    body = json.loads(resp.read().decode("utf-8"))

# 4. 打印整包。
#   第 5 步的字段按本接口 data 里实际键改。
print(json.dumps(body, ensure_ascii=False, indent=2))

# 5. code == 0 后再取字段
if body.get("code") == 0:
    data = body.get("data") or {}
    print(data)
```

### Go

```go
// 1. 密钥：登录 https://apizero.cn/account/keys 申请，写入环境变量 APIZERO_KEY
//    请求头 Authorization: Bearer <key>
package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"bytes"
)

func main() {
	key := os.Getenv("APIZERO_KEY")

	// 2. 请求地址
	url := "https://v1.apizero.cn/api/idcard-face-3c"

	// 3. 发请求
	payload, err := json.Marshal(map[string]any{
		"name": "张三",
		"idcard": "11010519491231002X",
		"image": "data:image/jpeg;base64,...",
	})
	if err != nil {
		panic(err)
	}
	req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(payload))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+key)
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	raw, _ := io.ReadAll(resp.Body)

	var body map[string]any
	if err := json.Unmarshal(raw, &body); err != nil {
		panic(err)
	}

	// 4. 打印整包。
	//   第 5 步的字段按本接口 data 里实际键改。
	fmt.Println(string(raw))

	// 5. code == 0 后再取字段
	if code, _ := body["code"].(float64); code == 0 {
		fmt.Println(body["data"])
	}
}
```

### Rust

```rust
// 1. 密钥：登录 https://apizero.cn/account/keys 申请，写入环境变量 APIZERO_KEY
//    请求头 Authorization: Bearer <key>
//    cargo add reqwest --features json,blocking ; cargo add serde_json
use reqwest::blocking::Client;
use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION};
use serde_json::Value;
use std::env;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let key = env::var("APIZERO_KEY")?;

    // 2. 请求地址
    let url = "https://v1.apizero.cn/api/idcard-face-3c";

    // 3. 发请求
    let mut headers = HeaderMap::new();
    headers.insert(
        AUTHORIZATION,
        HeaderValue::from_str(&format!("Bearer {key}"))?,
    );
    headers.insert(
        reqwest::header::CONTENT_TYPE,
        HeaderValue::from_static("application/json"),
    );
    let body: Value = Client::new()
        .post(url)
        .json(&serde_json::json!({
        "name": "张三",
        "idcard": "11010519491231002X",
        "image": "data:image/jpeg;base64,...",
    }))
        .headers(headers)
        .timeout(std::time::Duration::from_secs(15))
        .send()?
        .error_for_status()?
        .json()?;

    // 4. 打印整包。
    //   第 5 步的字段按本接口 data 里实际键改。
    println!("{}", serde_json::to_string_pretty(&body)?);

    // 5. code == 0 后再取字段
    if body.get("code").and_then(|v| v.as_i64()) == Some(0) {
        println!("{:?}", body.get("data"));
    }
    Ok(())
}
```

### PHP

```php
<?php
// 1. 密钥：登录 https://apizero.cn/account/keys 申请，写入环境变量 APIZERO_KEY
//    请求头 Authorization: Bearer <key>

$key = getenv('APIZERO_KEY');

// 2. 请求地址
$url = "https://v1.apizero.cn/api/idcard-face-3c";

// 3. 发请求
$payload = [
    "name" => "张三",
    "idcard" => "11010519491231002X",
    "image" => "data:image/jpeg;base64,...",
];
$ctx = stream_context_create([
    'http' => [
        'method' => 'POST',
        'header' => "Authorization: Bearer {$key}\\r\\nContent-Type: application/json\\r\\n",
        'content' => json_encode($payload, JSON_UNESCAPED_UNICODE),
        'timeout' => 15,
    ],
]);
$raw = file_get_contents($url, false, $ctx);
$body = json_decode($raw, true);

// 4. 打印整包。
//   第 5 步的字段按本接口 data 里实际键改。
echo $raw, PHP_EOL;

// 5. code == 0 后再取字段
if (($body['code'] ?? null) === 0) {
    echo json_encode($body['data'] ?? null, JSON_UNESCAPED_UNICODE), PHP_EOL;
}
```

### Java

```java
// 1. 密钥：登录 https://apizero.cn/account/keys 申请，写入环境变量 APIZERO_KEY
//    请求头 Authorization: Bearer <key>
//    Jackson：com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URI;
import java.util.LinkedHashMap;
import java.util.Map;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class Example {
    public static void main(String[] args) throws Exception {
        String key = System.getenv("APIZERO_KEY");
        ObjectMapper mapper = new ObjectMapper();

        // 2. 请求地址
        String url = "https://v1.apizero.cn/api/idcard-face-3c";

        // 3. 发请求
        Map<String, Object> payload = new LinkedHashMap<>();
        payload.put("name", "张三");
        payload.put("idcard", "11010519491231002X");
        payload.put("image", "data:image/jpeg;base64,...");
        String json = mapper.writeValueAsString(payload);

        HttpClient client = HttpClient.newBuilder()
                .connectTimeout(Duration.ofSeconds(10))
                .build();
        HttpRequest req = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Authorization", "Bearer " + key)
                .timeout(Duration.ofSeconds(15))
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(json))
                .build();
        HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandlers.ofString());
        JsonNode body = mapper.readTree(resp.body());

        // 4. 打印整包。
        //   第 5 步的字段按本接口 data 里实际键改。
        System.out.println(resp.body());

        // 5. code == 0 后再取字段
        if (body.path("code").asInt() == 0) {
            System.out.println(body.path("data"));
        }
    }
}
```

### JavaScript

```javascript
// 1. 密钥：登录 https://apizero.cn/account/keys 申请，写入环境变量 APIZERO_KEY
//    请求头 Authorization: Bearer <key>

const key = process.env.APIZERO_KEY;

// 2. 请求地址
const url = "https://v1.apizero.cn/api/idcard-face-3c";

// 3. 发请求
const payload = {
  "name": "张三",
  "idcard": "11010519491231002X",
  "image": "data:image/jpeg;base64,...",
};
const res = await fetch(url, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${key}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(payload),
});
const body = await res.json();

// 4. 打印整包。
//   第 5 步的字段按本接口 data 里实际键改。
console.log(JSON.stringify(body, null, 2));

// 5. code == 0 后再取字段
if (body.code === 0) {
  console.log(body.data);
}
```

## 8. 错误码

先看业务 code。HTTP 也可能不是 200。

| 业务码 | HTTP | 说明 |
| --- | --- | --- |
| 0 | 200 | 成功 |
| 4000 | 400 | 参数错误 |
| 4011 | 401 | API Key 无效 |
| 4013 | 403 | API Key 已暂停 |
| 4014 | 403 | 当前 IP 不在 Key 白名单 |
| 4015 | 401 | 此接口需要 API Key |
| 4022 | 402 | 余额不足 |
| 4029 | 429 | 调用过快（QPS） |
| 4030 | 429 | 今日免费额度已用完 |
| 4040 | 503 | 接口已下线 |
| 4041 | 404 | 接口不存在 |
| 5000 | 500 | 服务器内部错误 |
| 5020 | 502 | 上游暂时不可用 |
| 5021 | 502 | 上游返回格式异常 |
| 5030 | 502 | 暂无可用节点 |

### 本接口补充

| 业务码 | HTTP | 说明 |
| --- | --- | --- |
| 5031 | NOT_PURCHASED | 人像三要素接口未开通或次数已用尽 |


## 9. 变更日志

- **v1.0** (2026-08-05): 首次上线：人像三要素核验。
- **v1.0.1** (2026-08-17): 补登记 apis 表，修复网关 4041。
