添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
  • 该文档基于 牛客网API 牛客网API通讯协议V2 改写。接口调用协议没有发生变化。
  • 线下测试环境域名为: https://dapi.nowcoder.com ,线上正式环境域名为: https://api.nowcoder.com
  • 请注意所有请求都需要带上 /v1 前缀
  • 接口协议及规范

    接口支持https传输协议,URL接口遵循RESTful相关设计规范。如果使用HTTP协议调用,接口会尝试将请求重定向。

    牛客网api验证与授权基于标准OAuth2.0。使用牛客网开放平台API接口之前,请先获取与账号相关联的 apiKey token 。 具体获取方式为登录 牛客网企业版 后,点击 设置->账户设置->查看API KEY 来查看 apiKey token , 若未显示出 token 可以刷新页面重试。

    apiKey String 标识唯一调用者的Key,这里传参使用 api_key token String 基于OAuth2.0的token值,使用时加前缀 "Bearer "

    api_key 为接口调用时必须要带上的参数,其值为 apiKey 需登录 牛客网企业版 获取。在使用 Postman 执行HTTP请求时, GET请求的这个参数需要放在 Query Params 中,其他类型请求的这个参数需要放在 Body 中的 x-www-form-unlencoded 中, 值得注意的是,除了 api_key 之外,接口的特异化参数也需要按照这个规则传参。

    api_key String 标识唯一调用者的Key

    某些接口需要传递多个参数,比如在批量创建考生时,就需要传多个考生的信息。对于这种情况,我们需要知道HTTP请求是可以传递键值重复的参数的, 在调用接口时,需要要顺序一次将多个参数填入,比如 a=1&a=3&a=3 。在需要传递多个对象形式的参数时,调用接口时可以这样处理: v1=1&v2=1&v1=2&v2=2 ,在牛客服务中,我们使用数组来处理重复参数,参数的在数组中的顺序与HTTP请求时传入的顺序相同。在批量创建考生的场景下, 对于多个考生的不同信息,比如:姓名和考号,我们会同时循环两个数组。分别从每个数组的固定位置取出姓名和考号,组成一个考生信息。最后如果信息无误,才会执行后面的操作。 而调用方在传递参数时,只需按考生顺序,传递所有考生的信息即可,比如: name=user1&key=key1&name=user2&key=key2 , 具体示例可参考 添加考生 接口。

    import org.apache.commons.lang3.StringUtils;
    import org.apache.commons.lang3.math.NumberUtils;
    import java.util.regex.Matcher;
    public class IsPhone {
       * 是不是手机号
      public static boolean isPhone(String s) {
        if (StringUtils.isBlank(s)) {
          return false;
        boolean containLeft = s.contains("(");
        boolean containRight = s.contains(")");
        if (!(containLeft == containRight)) {
          return false;
        String phone = s.trim().replace("+", "").replace("(", "").replace(")", "");
        if (phone.startsWith("86")) {
          phone = phone.substring(2);
        if (phone.length() < 3) {
          return false;
        if (!NumberUtils.isDigits(phone)) {
          return false;
        if (isNativePhonePrefix(phone.substring(0, 3)) && !isOverSeaPhonePreFix(s)) {
          // +153076137580 这个是海外手机,但是去掉+,会被判断是国内手机开头,所以加上isOverSeaPhonePreFix判断
          return phone.length() == 11;
        } else {
          //如果是数字而又不是国内手机号,返回true
          return true;
      public static boolean isNativePhonePrefix(String prefix) {
        java.lang.String regexMobile = "^1([3-9][0-9])$";
        java.util.regex.Pattern p = java.util.regex.Pattern.compile(regexMobile);
        Matcher m = p.matcher(prefix.trim());
        return m.matches();
      public static boolean isOverSeaPhonePreFix(String s) {
        if (!s.startsWith("+")) {
          return false;
        if (s.startsWith("+86")) {
          return false;
        return true;
    
  • 牛客手机号的校验规则
  • 如果是国内手机号在符合正则表达式:^1([3-9][0-9])\d{8}$的基础上,手机号开头可以不带"+86",带上的话和后面手机号之间不能有空格如: +8615205201314
  • 如果是国外手机号需包含+和国际地区前缀号码,如:+93701234567
  • import org.apache.commons.lang3.StringUtils;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    public class IsEmail {
      public static Pattern emailPattern =
          Pattern.compile("^([a-zA-Z0-9_\\+\\.-])+@(([a-zA-Z0-9-])+\\.)+([a-zA-Z0-9]{2,8})");
       * 是不是邮箱
      public static boolean isEmail(String email) {
        if (StringUtils.length(email) <= 40 && StringUtils.length(email) > 0) {
          Matcher matcher = emailPattern.matcher(email);
          return matcher.matches();
        } else {
          return false;
    
  • 牛客邮箱的校验规则
  • 需要符合正则表达式:^([a-zA-Z0-9_+.-])+@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,8})且字符长度不超过40个。校验逻辑见java代码示例。

  • 接口返回格式
  • 如无特殊说明,接口采用json格式来描述返回信息且接口返回头中带有Content-Type: application/json, 比如:{"code":0,"msg":"OK","data": 接口返回信息}code=0在业务上表示成功;code!=0在业务上表示失败,msg中为具体错误信息。 data字段可能为空,它的数据结构可能是字符串、数字、json对象等。data具体的内容见接口文档。

  • 时间格式返回字段
  • 如无特殊说明,接口中返回的时间均为unix时间戳(毫秒级)

  • 接口是否正常工作
  • 接口没有返回200code!=0可以视为发生了异常。异常绝大部分是传参不合法,比如请求了不存在的资源、参数传递出现了问题。 接口有可能在传参异常时返回4xx4xx错误通常可以在返回的json中msg处获取出错原因。若出错原因无法直接解读,可以联系我们。 如果出现了5xx错误,请联系我们。 建议非200情况下打印出牛客网返回的完整response,其中40x错误建议将msg中信息在界面中展示给用户,方便用户处理。

  • 常见错误:{"code" : 999,"msg" : "缺少认证参数","details" : null}
  • 这个报错信息代表接口授权失败,需要检查api_key参数和Authorization请求头是否传递正确。

    如果认为接口出现了问题。在向牛客技术反馈问题需提供如下信息:账号id、接口地址、接口入参、调用时间、牛客返回的完整response

    示例代码提供了HTTP接口的调用样例。目前提供了shell和Java语言示例代码。点击右侧的shell标签或java标签即可查看。 示例代码,用于帮助开发者快速理解牛客api调用规范。代码仅供测试用。

    shell示例代码

    shell代码示例提供了接口的curl调用示例。开发者替换脚本中的api_key参数和Authorization校验头即可进行接口调用。 除此之外,代码示例中还包含了以json形式表示的接口的返回数据结构。

    java示例代码

    java代码示例提供了在Java程序中调用的示例。 为了消除重复代码,简化代码示例代码逻辑,示例代码中使用了NowcoderApiRequestUtils工具类对HTTP调用过程进行了封装。示例代码中仅保留了接口地址和请求参数信息。 NowcoderApiRequestUtils工具类和文档中的代码示例均托管在gitee。 下载代码至本地即可调试。

    示例代码下载地址:https://gitee.com/nowcoder-guokaijun/nowcoder-api-http-call-demo/tree/master

    下面是代码主要结构介绍

    ConfigUtils

    https://gitee.com/nowcoder-guokaijun/nowcoder-api-http-call-demo/blob/master/src/main/java/com/nowcoder/enterprise/javademo/utils/ConfigUtils.java

    该类为牛客网企业版账户配置类,需要该类中的将TODO标注的配置改为开发者自己账户的配置。

    全局配置类

    public class ConfigUtils {
      private static final boolean USE_NOWCODER_API_ONLINE =
          false; // TODO 牛客接口环境,false的是线下测试环境、需要根据您的代码运行环境灵活配置
      private static final long NOWCODER_HR_ID_DEV = 0; // TODO 需要替换为您牛客线下测试环境的HrID
      private static final long NOWCODER_HR_ID_ONLINE = 0; // TODO 需要替换为您牛客线上正式环境的HrID
      private static final String API_KEY = "[email protected]"; // TODO 需要替换为您的api_key
      private static final String TOKEN =
          "95da5da5da5da5da5da5da5da5da5ff81aa9c7a8512638f4c73a4e338f650a5c"; // TODO 需要替换为您的token
      private ConfigUtils() throws IllegalAccessException {
        throw new IllegalAccessException("Can not instantiate an util class.");
      private static boolean useNowcoderAPIOnline() {
        return USE_NOWCODER_API_ONLINE;
      public static long getNowcoderHrId() {
        if (useNowcoderAPIOnline()) {
          return NOWCODER_HR_ID_ONLINE;
        return NOWCODER_HR_ID_DEV;
      public static String getApiBaseUrl() {
        // 线上正式环境
        if (useNowcoderAPIOnline()) {
          return "https://api.nowcoder.com/v1";
        // 线下测试环境
        return "https://dapi.nowcoder.com/v1";
      public static String getApiKey() {
        return API_KEY;
      public static String getAuthorization() {
        return "Bearer " + TOKEN;
    

    NowcoderApiRequestUtils

    https://gitee.com/nowcoder-guokaijun/nowcoder-api-http-call-demo/blob/master/src/main/java/com/nowcoder/enterprise/javademo/utils/NowcoderApiRequestUtils.java

    该类为封装了符合牛客API的传输协议的HTTP调用逻辑的静态工具类。在该类中,有两个出口方法request()getNowcoderHrId()。 其中request()方法的作用是将接口的特异化参数传入并执行HTTP调用,方法支持HTTP的GET、POST、PUT、DELETE方法的请求, 并根据不同的HTTP方法规范设置了api_key参数、Authorization校验头、Content-Type请求参数内容类型。 getNowcoderHrId()方法的作用是获取用户的HRId,以便在调用需要拼接接口url的方法时使用。

    请求牛客API工具类

    public class NowcoderApiRequestUtils {
       * HTTP调用牛客API并返回字符串,在调用之前根据请求方法设置了通用的请求头和请求参数,并将方法传入的参数置入HTTP请求中。
       * @param path 请求路径,形如"/users/self"的字符串
       * @param params 请求参数,需传递除api_key参数之外的每个接口独有的参数。一个key能对应多个值,值不能为null。
       *               如果接口不需要其他参数,需要传递空Map,不能传null。
       * @param methodName http方法名称。取值范围为 GET、POST、PUT、DELETE 中的一个
       * @return 牛客接口json返回的字符串表示
      public static String request(
          String path, MultiValuedMap<String, Object> params, String methodName) {
        if (HttpGet.METHOD_NAME.equals(methodName)) {
          return getRequest(path, params);
        HttpEntityEnclosingRequestBase uriRequest;
        if (HttpPost.METHOD_NAME.equals(methodName)) {
          uriRequest = new HttpPost();
        } else if (HttpPut.METHOD_NAME.equals(methodName)) {
          uriRequest = new HttpPut();
        } else if (HttpDelete.METHOD_NAME.equals(methodName)) {
          uriRequest = new NowcoderHttpDelete();
        } else {
          throw new IllegalArgumentException("Bad methodName.");
        uriRequest.setURI(URI.create(ConfigUtils.getApiBaseUrl() + path));
        List<NameValuePair> pairList = new ArrayList<>();
        pairList.add(new BasicNameValuePair("api_key", ConfigUtils.getApiKey()));
        params
            .entries()
            .forEach(
                (entry) -> {
                  String key = entry.getKey();
                  Object val = entry.getValue();
                  if (key == null || val == null) return;
                  pairList.add(new BasicNameValuePair(key, val.toString()));
        uriRequest.setEntity(new UrlEncodedFormEntity(pairList, StandardCharsets.UTF_8));
        uriRequest.addHeader("Authorization", ConfigUtils.getAuthorization());
        return sendRequest(uriRequest);
      // 执行GET请求
      private static String getRequest(String path, MultiValuedMap<String, Object> params) {
        List<String> pairs = new ArrayList<>();
        pairs.add("api_key=" + ConfigUtils.getApiKey());
        params
            .entries()
            .forEach(
                (entry) -> {
                  String key = entry.getKey();
                  Object val = entry.getValue();
                  if (key == null || val == null) return;
                  pairs.add(key + "=" + val);
        String queryParams = StringUtils.join(pairs, "&");
        HttpGet get = new HttpGet(ConfigUtils.getApiBaseUrl() + path + "?" + queryParams);
        get.addHeader("Authorization", ConfigUtils.getAuthorization());
        return sendRequest(get);
      // 发送请求并打印CURL
      private static String sendRequest(HttpRequestBase requestBase) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String responseString = null;
        try {
          CloseableHttpResponse response = httpClient.execute(requestBase);
          HttpEntity entity = response.getEntity();
          responseString = EntityUtils.toString(entity, StandardCharsets.UTF_8);
        } catch (IOException e) {
          e.printStackTrace();
        String curlStr = toCurlStr(requestBase);
        System.out.println(curlStr);
        return responseString;
      // 将一次HTTP请求转换成CURL
      private static String toCurlStr(HttpRequestBase requestBase) {
        String httpMethod = requestBase.getMethod();
        String uri = requestBase.getURI().toString();
        List<String> headers = new ArrayList<>();
        for (Header header : requestBase.getAllHeaders()) {
          headers.add(header.getName() + ": " + header.getValue());
        String headersStr = "";
        if (CollectionUtils.isNotEmpty(headers)) {
          for (String header : headers) {
            headersStr += "\\\n --header '" + header + "' ";
        String dataRawStr = "";
        if (requestBase instanceof HttpEntityEnclosingRequestBase) {
          HttpEntity entity = ((HttpEntityEnclosingRequestBase) requestBase).getEntity();
          try {
            dataRawStr = EntityUtils.toString(entity, StandardCharsets.UTF_8);
          } catch (IOException e) {
            e.printStackTrace();
        if (StringUtils.isNotEmpty(dataRawStr)) {
          dataRawStr = String.format("\\\n --data-raw '%s'", dataRawStr);
        String template = "curl --location --request %s '%s' %s %s";
        return String.format(template, httpMethod, uri, headersStr, dataRawStr);
    

    NowcoderHTTPDelete

    https://gitee.com/nowcoder-guokaijun/nowcoder-api-http-call-demo/blob/master/src/main/java/com/nowcoder/enterprise/javademo/utils/NowcoderHttpDelete.java

    由于HTTPDelete类不支持传递参数内容,故实现了NowcoderHttpDelete类以便在使用DELETE请求时传递参数。该类仅在NowcoderApiRequestUtils中使用。

    DELETE请求类

    public class NowcoderHttpDelete extends HttpEntityEnclosingRequestBase {
      public static final String METHOD_NAME = HttpDelete.METHOD_NAME;
      public NowcoderHttpDelete() {
        super();
      public NowcoderHttpDelete(final URI uri) {
        super();
        setURI(uri);
      /** @throws IllegalArgumentException if the uri is invalid. */
      public NowcoderHttpDelete(final String uri) {
        super();
        setURI(URI.create(uri));
      @Override
      public String getMethod() {
        return METHOD_NAME;
    

    src/test/java包下的测试类

    使用NowcoderApiRequestUtils工具类对牛客API的接口进行了测试。

    具体的测试代码

    public class Test {
      @Test
      public void testGetUserTestInfo() {
        String path = "/users/self";
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "GET");
        System.out.println(responseString);
    

    接口文档组织形式

    ## 一句话描述接口
    > 右侧为 java语言 和 shell语言的代码示例
    阐明接口的业务背景、作用以及对接中常见问题。
    ### 接口地址`$method $uri`的形式表示接口地址,实际请求时,需要拼接`https://api.nowcoder.com/v1`的前缀。
    ### 请求参数
    以表格形式展现的接口全部或部分主要的请求参数。
    ### 返回数据
    以表格形式展现的接口全部或部分主要的返回数据。
    

    接口文档模版

    每一个接口除了描述接口的调用协议,还讲述了业务背景和对接中的常见问题。具体的组织形式见右侧示例代码。

    在请求参数和返回参数仅列出部分字段为的是降低开发人员理解成本和对接难度,如发现字段不全或者接口不能满足需求的情况,请联系我们。

    接口目录简述

    已“笔试-”开头的为笔试系统对接需要关注的接口。 已“面试-”开头的为面试系统对接需要关注的接口。 系统接口为获取用户信息所需接口。

    牛客网回调服务介绍

    牛客网回调服务提供了实现了一种事件发布订阅机制。开发者在订阅某些事件之后,牛客网回调服务将会在事件发生时,通过HTTP请求的形式通知开发者。

  • 开发者系统:需要与牛客进行信息互通且支持HTTP调用的系统。
  • 回调:指从牛客回调服务发送HTTP请求至开发者系统这一动作。一般来说,开发者系统通过HTTP请求的方式调用牛客API来获取牛客系统中的信息, 如果我们将这个过程逆向,由牛客中调用开发者系统,向开发者系统传递信息,就成了“回调”。
  • 回调时机:回调发生的时间节点,一般是指牛客系统中发生了某一关键业务需要告知开发者系统。
  • 回调参数:在回调时,需要告知开发者系统的信息。
  • 回调类型:按照业务、回调参数等信息划分的回调抽象。不同的回调类型也对应着不同的回调时机、回调参数以及回调配置形式。
  • 回调配置:如需触发回调,需要开发者通过某些方式进行配置。
  • 目前来说回调支持两种配置方式:

  • 在调用创建实体接口(比如:笔试考生、面试房间)时订阅一个实体的回调。
  • 由牛客开发者来配置回调。
  • 一种回调类型只支持其中的一种回调配置方式,一种配置可能同时对多种回调类型生效。

    回调接口协议

    回调协议包含一次HTTP调用时牛客的请求形式和期望开发者系统的返回形式。

    回调请求格式

    对于GET请求,所有参数都放在HTTP的Query params中;对于POST请求,请求头为application/x-www-form-urlencoded,参数放在了Body中。

    如果开发者系统使用了Java中的SpringMVC框架,请求参数声明既不用声明@RequestBody注解,也不用声明@RequestParam注解, 详情见: https://stackoverflow.com/q/33796218/10532034

    回调成功/失败判定

    开发者系统的服务返回success这6个字符,视为回调成功。如果没有返回这六个字符,则视为回调失败。回调失败将会触发重试机制。

    回调成功示例:纯HTTP响应格式如下:

      HTTP/1.1 200 OK
      Content-Type: text/plain
      Content-Length: 7
      success
    

    回调重试机制

    对于一次回调,牛客回调服务可能会尝试进行两次HTTP调用。 牛客回调服务会先尝试发送GET请求、如果请求失败,然后尝试发送POST请求。如果两次请求都失败了,牛客回调服务会认为这次请求失败了,并触发重试机制。

    因为回调机制会采取重试机制,所有要求开发者的HTTP接口都是幂等的。 如果期望只进行POST请求,可以联系牛客开发人员进行配置。

    回调频率、次数

    如果遇到回调失败,牛客回调服务会尝试重试4次,带上第一次失败的请求,总共尝试5次。

    第几次调用 第一次调用 第二次调用 第一次失败10分钟后 第三次调用 第二次失败30分钟后 第四次调用 第三次失败60分钟后 第五次调用 第四次失败120分钟后

    其他事项

    回调类型

    不同的回调类型有不同的回调配置方式,会携带不同的回调参数并在不同的回调时机回调开发者。

    关于回调类型的具体信息见:笔试-回调服务面试-回调服务

    回调服务地址

    线下测试服务ip为:47.114.96.253,线上回调服务ip:47.99.92.255

    如开发者有配置接口调用白名单的需求,可以将上面两个IP加入接口调用白名单。

    牛客系统对接最佳实践

    牛客网企业版作为成熟的技术人才招聘解决方案提供商,根据多年系统对接经验,总结了下面几种系统对接最佳实践。

    ATS:applicant tracking system,求职跟踪系统。在这里也可以指开发者需要与牛客对接的系统。
    牛客/牛客网企业版:指牛客提供的接口服务以及回调服务

    笔试系统对接最佳实践

    对接模式一(推荐)

    系统交互流程

  • 企业的HR或者牛客项目同学,使用牛客网企业版管理后台在牛客系统创建试卷。
  • ATS通过调用牛客API接口,可以查询在牛客中已经创建好的试卷。
  • ATS中通过调用牛客API接口的方式,安排考生到牛客的试卷中。安排成功后,可以获取到考生的考试链接。在调用接口创建考生的同时,传递需要回调的地址。
  • 在考生完成考试、作弊检测完成、人工判题完成等动作触发之后,牛客将考试成绩、成绩报告通过回调地址回传给ATS。 同时,ATS也可以选择在某一个时间点调用牛客API接口获取考生成绩。
  • 代表企业:字节跳动、网易、moka、大易等绝大部分企业

    对接模式二

    系统交互流程

  • 企业的HR或者牛客项目同学,使用牛客网企业版管理后台在牛客系统创建好试卷,并填好职位id(这个职位id用于关联企业ATS中的职位)。
  • 试卷创建完成之后,可通过职位id定位一张试卷来创建考生。在调用接口创建考生的同时,传递需要回调的地址。
  • 在考生完成考试、作弊检测完成、人工判题完成等动作触发之后,牛客将考试成绩、成绩报告通过回调地址回传给ATS。 同时,ATS也可以选择在某一个时间点调用牛客API接口获取考生成绩。
  • 如需开启“配置职位id”功能,需要联系牛客开发人员进行配置。

    代表企业:阿里巴巴、中兴、OPPO等部分企业

    对接模式三

    系统交互流程:

  • 企业的HR或者牛客项目同学,使用牛客网企业版管理后台在牛客系统创建试卷。
  • 试卷创建完成之后,在ATS系统中关联岗位、试卷。在ATS中将候选人转移状态即可安排笔试、拿到考生考试链接。
  • 在考生完成考试、作弊检测完成、人工判题完成等动作触发之后,牛客将考试成绩、成绩报告回传给ATS。 同时,ATS也可以选择在某一个时间点调用牛客API接口获取考生成绩。
  • 与对接模式二相比,该对接模式中岗位与试卷的关系在ATS中进行维护。ATS与牛客信息交互使用牛客试卷id。

    代表企业:北森

    面试系统对接最佳实践

    对接模式一

    系统交互流程

  • 客户在牛客端创建账号,到对接方配置认证使用的api_key
  • 在对接方推进面试流程,在牛客端进行面试
  • 对接方、牛客端之间进行面试结果同步
  • 面试结果同步可以分为对接方同步到牛客,对接方式一般为面试结束跳转对接方评价链接、牛客内嵌对接方面评表,然后通过评分接口同步到牛客。 牛客同步到对接方一般为面试轮次评价回调功能

    笔试-试卷管理

    一张试卷包含考试时长、考试起止时间、防作弊机制配置以及添加考生时需要录入信息等配置元信息。 在牛客系统中试卷可以认为是一场考试的抽象,在校园招聘业务场景下,一场考试应与一张试卷一一对应; 在社会招聘业务场景下,一张试卷可以认为是相似职位的通用考题。 一张试卷可以对应多个考生,所有的考生都属于一张试卷。考生在试卷之间没有关联关系,不同的试卷中可以创建唯一编号(添加考生接口的key字段)相同的考生。

    试卷实体的关键字段

    试卷实体的创建、删除和查询可调用试卷管理接口获取,下面是试卷实体的一些关键字段。

    试卷id,唯一标识一张试卷。 paperName String 试卷名字。 duration 试卷考试时长。 beginTime 试卷的开始时间。 endTime 试卷结束时间(对长期有效试卷,默认取值'2114-10-10T00:00')。 forever boolean 试卷是否长期有效,true是,false否。 createTime 试卷的创建时间。 beenTested boolean 试卷是否已经被使用。 started boolean 试卷是否已经开始。 finished boolean 试卷是否已结束。 summary String 试卷简介,考生在考试开始前会看到这些信息。 questionCount 试卷试题的数量。 testCount 试卷测评的数量。 needJudge 试卷是否需要人工判题, 0表示需要,1表示不需要。 assignedCount 已经分配的判卷数量。 setting Object 试卷相关配置信息, json格式。其中,试卷适用的职位id列表为该json下的"otherJobIds"字段,取值为int类型的职位id列表,职位id之间用","分隔,取值示例:""10000001,10000002" score Float 试卷总分。 passScoreLine Float antiCheatStr String 防作弊机制。 signUpFieldTitles String 考生需要录入信息的所有字段,逗号拼接。 paperCodeLangInfo Object 试卷中编程题语言信息,对象结构见右侧说明
    paperCodeLangInfo结构
      "codeQuestionCount": 2, // 编程题的数量,为0表示没有编程题
      "ojExerciseUrl": "https://xxx", // codeQuestionCount大于0时有值,表示:OJ在线编程常见输入输出练习地址
      "codeLangList": [ //codeQuestionCount大于0时有值,表示:对应题目数量和其支持的编程语言
          "count": 2, // 题目数量
          "langList": ["C","C#","C++","Go","Groovy","Java","Javascript"] // 编程语言列表,为null表示不限语言
    

    获取试卷列表

    public class Main {
    @Test
      public void testGetPaperList() {
        String path = String.format("/papers/oid-%d", ConfigUtils.getNowcoderHrId());
        long projectId = 1643;
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        mvMap.put("page", 1);
        mvMap.put("pageCount", 20);
        mvMap.put("orderBy", 0);
        mvMap.put("order", 2);
        mvMap.put("filter", 0);
        mvMap.put("query", "");
        mvMap.put("progressType", 0);
        mvMap.put("projectIdList", projectId);
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "GET");
        System.out.println(responseString);
    
    curl --location --request GET 'https://dapi.nowcoder.com/v1/papers/[email protected]&filter=0&pageCount=20&progressType=0&query=&orderBy=0&page=1&projectIdList=1643&order=2' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "totalCount" : 1,
        "totalPage" : 1,
        "currentPage" : 1,
        "datas" : [ {
          "id" : 17131890,
          "paperName" : "一张很久才开始的试卷",
          "createTime" : 1628137829000,
          "duration" : 120,
          "score" : 20,
          "personTotal" : 0,
          "avgTotal" : 0.0,
          "summary" : "1、考前请关闭其他浏览器窗口,关闭QQ、微信等即时通信软件,关闭屏保、Outlook等弹窗提示软件,考试中不要切换到考试窗口之外的区域。<br/>\n2、请在规定时间内完成题目,答题过程中系统自动即时,到时自动交卷,请掌握好答题进度;<br/>\n3、请诚信答题,考试全程不要跳出考试页面(在线编程题除外),后台将记录你的跳出次数。编程题交卷后,我们将进行代码相似度判断,标示作弊嫌疑代码。<br/>\n4、笔试过程中遇到任务问题,请通过在线咨询小窗发消息给我们,我们会有相应人员解答。<br/>",
          "logo" : null,
          "questionCount" : 1,
          "diffcult" : 0,
          "beginTime" : 1735660800000,
          "endTime" : 1738339200000,
          "previewUrl" : "https://examd.nowcoder.com/cts/preview/papers/17131890?p_token=L9mTCQXQaLsBUEfFzKlJMrKLgROj5Xk4",
          "testUrl" : "https://examd.nowcoder.com/cts/17131890/summary",
          "mobileTestUrl" : null,
          "assigned" : true,
          "testCount" : 0,
          "assignedCount" : 0,
          "paperSetting" : null,
          "presetUserCount" : 3,
          "paperExcelDownloadUrl" : null,
          "excelTaskStatus" : 0,
          "finished" : false,
          "started" : false,
          "setting" : {
            "logo" : "https://dev-private-public.oss-cn-hangzhou.aliyuncs.com/images/20201130/30_1606732062638/3669B06677BFB1053B71DAA1400C3083",
            "paperSummary" : "1. 请使用最新版Chrome浏览器作答(不低于82版),如考试需开启摄像头,请确保电脑带有摄像头。\n2. 一旦开始考试,请勿离开答题页面,除非当前目录明确提醒可以离开,前三次离开会有提醒,之后将不再提醒。各目录是否支持离开答题页面则取决于试卷具体设置,进入每个目录会有提示。\n3. 考试过程中允许使用草稿纸,请提前准备纸笔。允许上厕所等短暂离开,请控制离开时间。\n4. 考试期间如遇到断电、断网、死机等问题,关闭浏览器重新打开试卷链接即可继续做题。\n5. 遇到问题请即时反馈给考试主办方。",
            "examDisclaimer" : null,
            "antiJumpOut" : false,
            "antiDesignJumpOut" : true,
            "antiCodingJumpOut" : false,
            "codeSimilarRate" : 80,
            "setSourceCoderCheat" : false,
            "monitorPhone" : false,
            "allowMobileTest" : false,
            "noQueueUp" : true,
            "signUpFields" : [ {
              "title" : "姓名",
              "name" : "name",
              "format" : "",
              "need" : true,
              "edit" : 0,
              "valueType" : 0,
              "valueList" : null
            }, {
              "title" : "投递编号",
              "name" : "key",
              "format" : "",
              "need" : true,
              "edit" : 0,
              "valueType" : 0,
              "valueList" : null
            }, {
              "title" : "手机号码",
              "name" : "phone",
              "format" : "Phone",
              "need" : false,
              "edit" : 0,
              "valueType" : 0,
              "valueList" : null
            }, {
              "title" : "邮箱",
              "name" : "email",
              "format" : "Email",
              "need" : false,
              "edit" : 0,
              "valueType" : 0,
              "valueList" : null
            }, {
              "title" : "职位",
              "name" : "zhi2_wei4",
              "format" : "",
              "need" : false,
              "edit" : 0,
              "valueType" : 0,
              "valueList" : null
            }, {
              "title" : "学校",
              "name" : "xue2_xiao4",
              "format" : "",
              "need" : false,
              "edit" : 0,
              "valueType" : 0,
              "valueList" : null
            }, {
              "title" : "学历",
              "name" : "xue2_li4",
              "format" : "",
              "need" : false,
              "edit" : 0,
              "valueType" : 0,
              "valueList" : null
            } ],
            "relationType" : 0,
            "questionCategories" : {
              "5" : "问答"
            "questionIdsTypes" : { },
            "questionScores" : null,
            "questionNewCounts" : null,
            "relationJsonString" : null,
            "questionCategoryRule" : null,
            "questionCategoryOrder" : "1,2,3,4,5",
            "randomQuestion" : false,
            "customCategory" : false,
            "randomFrequentType" : 0,
            "version" : "1.0",
            "questionTagNames" : { },
            "codingScoreRule" : 1,
            "chooseScoreRule" : 3,
            "checkCheat" : true,
            "allowCopy" : false,
            "allowCalculator" : false,
            "contestDomain" : null,
            "navLogoUrl" : null,
            "hideNowcoder" : false,
            "simulation" : false,
            "languageLimit" : false,
            "languageList" : [ ],
            "reportPlatform" : true,
            "forbidPreview" : true,
            "needMobileCamera" : false,
            "codePlayback" : false,
            "timeLimitType" : 0,
            "timeLimitDetail" : null,
            "tiankongScores" : "{}",
            "otherJobIds" : null,
            "subPaperSetting" : null,
            "uploadFileTimeRange" : 0,
            "videoAnswerQuestionRule" : null,
            "lateNoticeSetting" : null,
            "paper_end_summary" : "本场考试已结束,请保持您的手机、邮箱畅通,方便接收后续通知。",
            "allow_new" : false,
            "allow_camera" : false,
            "allow_screen_record" : false,
            "allow_message" : false,
            "question_disorder" : false,
            "option_disorder" : false,
            "not_need_judge_type" : "3_4",
            "need_judge_type" : "5",
            "faq" : [ ],
            "hide_return_button" : true
          "beenTested" : false,
          "passScoreLine" : null,
          "projectId" : 1643,
          "projectName" : "liumeng测试",
          "departmentList" : null,
          "previewOverdueTime" : null,
          "paperType" : null,
          "hasNotAttendTestUser" : false,
          "antiCheatStr" : "开启举报平台",
          "signUpFieldTitles" : "投递编号,姓名,手机号码,邮箱,职位,学校,学历",
          "creatorHrId" : 30,
          "creatorHrName" : null,
          "needJudge" : 0,
          "notStartedCount" : 0,
          "inProgressCount" : 0,
          "expiredCount" : 0,
          "cheatTaskStatus" : 0,
          "faceDetectedRation" : 0.0,
          "codeDetectedRation" : 0.0,
          "screenDetectedRation" : 0.0,
          "hasCodeQuestion" : false,
          "hasCtsPic" : false,
          "hasScreen" : false,
          "questionDesc" : "问答 1 道",
          "interviewPaper" : null,
          "forever" : false
        } ],
        "ext" : null,
        "allTotalCount" : 1,
        "notStartedPaperCount" : 1,
        "testingPaperCount" : 0,
        "finishedPaperCount" : 0,
        "archivePaperCount" : 0
    

    获取一个账户下的试卷列表。支持分页。这个接口可以用于遍历牛客系统中已经创建好的试卷。

    GET /papers/oid-{ownerId}

    ownerId HR系统的用户ID,需填充在url中 第几页,从1开始。 pageCount 每页20多少数据。无数量限制,可以传较大的值,但试卷数量多之后响应时长可能很长,不推荐这么做 orderBy 试卷排序的依据项。0根据create_time排序,1根据做题人数排序,2根据平均分排序,3开考时间 order 试卷的排列顺序。1代表升序,2代表降序 filter 是否过滤。可不传,默认0。0不过滤, 1过滤掉不需要人工判卷的试卷 query String 试卷名称搜索,实现方式为SQLLIKE关键字的模糊搜索 paperType 试卷类型:0.全部,1.普通笔试,2.ai面试。当paperType未传值或该参数不存在时,默认值为0,会返回笔试试卷+AI面试试卷(AI试卷名称自动添加#AI面试#前缀,以便于与笔试试卷区分);如果需要只返回笔试试卷,可以找客户经理进行配置 progressType 试卷的状态:0.代表不限,1.表示未开始,2.表示进行中,3.表示结束 progressTypeList List<Integer> progressType的多值查询参数,多个参数之间用OR关系取并集;当启用该参数时,建议progressType参数默认取值0(progressType和progressTypeList两参数间,是And关系取交集的逻辑) projectIdList List<Long> 限定试卷所属项目id,可传多个 otherJobIdList List<Long> 限定职位id,一般情况下不用传,可传多个,用于筛选出“试卷配置中指定了职位id“的试卷列表。关于职位id更多信息见系统对接模式2 totalCount 数据(试卷)总数 totalPage 总共多少页 currentPage 当前是第几页,从第一页开始 datas 试卷信息数组,试卷关键信息见试卷关键返回字段

    批量获取试卷

    public class Main {
      @Test
      public void testGetPaperListByMultiPaperIds() {
        String path = "/papers/multi";
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        mvMap.put("paperIds", 17071483);
        mvMap.put("paperIds", 17071578);
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "GET");
        System.out.println(responseString);
    
    curl --location --request GET 'https://dapi.nowcoder.com/v1/papers/[email protected]&paperIds=17071483&paperIds=17071578' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  
      "code" : 0,
      "msg" : "OK",
      "data" : [ {
        "id" : 17071483,
        "paperName" : "121",
        "createTime" : 1611214578000,
        "duration" : 120,
        "score" : 112,
        "personTotal" : 0,
        "avgTotal" : 0.0,
        "summary" : "1、考前请关闭其他浏览器窗口,关闭QQ、微信等即时通信软件,关闭屏保、Outlook等弹窗提示软件,考试中不要切换到考试窗口之外的区域。<br/>\n2、请在规定时间内完成题目,答题过程中系统自动即时,到时自动交卷,请掌握好答题进度;<br/>\n3、请诚信答题,考试全程不要跳出考试页面(在线编程题除外),后台将记录你的跳出次数。编程题交卷后,我们将进行代码相似度判断,标示作弊嫌疑代码。<br/>\n4、笔试过程中遇到任务问题,请通过在线咨询小窗发消息给我们,我们会有相应人员解答。<br/>",
        "logo" : null,
        "questionCount" : 4,
        "diffcult" : 0,
        "beginTime" : 1611214578000,
        "endTime" : 4568544000000,
        "previewUrl" : "https://examd.nowcoder.com/cts/preview/papers/17071483?p_token=L9mTCQXQaLsBUEfFzKlJMrKLgROj5Xk4",
        "testUrl" : "https://examd.nowcoder.com/cts/17071483/summary",
        "mobileTestUrl" : null,
        "assigned" : true,
        "testCount" : 0,
        "assignedCount" : 0,
        "paperSetting" : null,
        "presetUserCount" : 0,
        "paperExcelDownloadUrl" : null,
        "excelTaskStatus" : 0,
        "finished" : false,
        "started" : true,
        "setting" : {
          "logo" : "https://dev-private-public.oss-cn-hangzhou.aliyuncs.com/images/20201130/30_1606732062638/3669B06677BFB1053B71DAA1400C3083",
          "paperSummary" : "1. 请使用最新版Chrome浏览器作答(不低于82版),如考试需开启摄像头,请确保电脑带有摄像头。\n2. 一旦开始考试,请勿离开答题页面,除非当前目录明确提醒可以离开,前三次离开会有提醒,之后将不再提醒。各目录是否支持离开答题页面则取决于试卷具体设置,进入每个目录会有提示。\n3. 考试过程中允许使用草稿纸,请提前准备纸笔。允许上厕所等短暂离开,请控制离开时间。\n4. 考试期间如遇到断电、断网、死机等问题,关闭浏览器重新打开试卷链接即可继续做题。\n5. 遇到问题请即时反馈给考试主办方。",
          "examDisclaimer" : null,
          "antiJumpOut" : false,
          "antiDesignJumpOut" : true,
          "antiCodingJumpOut" : false,
          "codeSimilarRate" : 80,
          "setSourceCoderCheat" : false,
          "monitorPhone" : false,
          "allowMobileTest" : false,
          "noQueueUp" : false,
          "signUpFields" : [ {
            "title" : "姓名",
            "name" : "name",
            "format" : "",
            "need" : true,
            "edit" : 0,
            "valueType" : 0,
            "valueList" : null
          }, {
            "title" : "投递编号",
            "name" : "key",
            "format" : "",
            "need" : true,
            "edit" : 0,
            "valueType" : 0,
            "valueList" : null
          }, {
            "title" : "手机号码",
            "name" : "phone",
            "format" : "Phone",
            "need" : false,
            "edit" : 0,
            "valueType" : 0,
            "valueList" : null
          }, {
            "title" : "邮箱",
            "name" : "email",
            "format" : "Email",
            "need" : false,
            "edit" : 0,
            "valueType" : 0,
            "valueList" : null
          }, {
            "title" : "职位",
            "name" : "zhi2_wei4",
            "format" : "",
            "need" : false,
            "edit" : 0,
            "valueType" : 0,
            "valueList" : null
          }, {
            "title" : "学校",
            "name" : "xue2_xiao4",
            "format" : "",
            "need" : false,
            "edit" : 0,
            "valueType" : 0,
            "valueList" : null
          }, {
            "title" : "学历",
            "name" : "xue2_li4",
            "format" : "",
            "need" : false,
            "edit" : 0,
            "valueType" : 0,
            "valueList" : null
          } ],
          "relationType" : 0,
          "questionCategories" : {
            "100" : "1",
            "101" : "2",
            "102" : "3",
            "103" : "4"
          "questionIdsTypes" : { },
          "questionScores" : null,
          "questionNewCounts" : null,
          "relationJsonString" : null,
          "questionCategoryRule" : null,
          "questionCategoryOrder" : null,
          "randomQuestion" : false,
          "customCategory" : true,
          "randomFrequentType" : 0,
          "version" : "1.0",
          "questionTagNames" : { },
          "codingScoreRule" : 1,
          "chooseScoreRule" : 3,
          "checkCheat" : true,
          "allowCopy" : false,
          "allowCalculator" : false,
          "contestDomain" : null,
          "navLogoUrl" : null,
          "hideNowcoder" : false,
          "simulation" : false,
          "languageLimit" : false,
          "languageList" : [ ],
          "reportPlatform" : true,
          "forbidPreview" : true,
          "needMobileCamera" : false,
          "codePlayback" : false,
          "timeLimitType" : 0,
          "timeLimitDetail" : null,
          "tiankongScores" : "{\"803922\":[20,21,22,23]}",
          "otherJobIds" : null,
          "subPaperSetting" : [ {
            "id" : 1,
            "name" : "子卷1",
            "intro" : "子卷1说明子卷1说明子卷1说明子卷1说明子卷1说明子卷1说明子卷1说明子卷1说明子卷1说明子卷1说明子卷1说明子卷1说明子卷1说明子卷1说明子卷1说明子卷1说明子卷1说明",
            "categories" : "102,100,101"
          }, {
            "id" : 2,
            "name" : "子卷2",
            "intro" : "子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明子卷2说明",
            "categories" : "101,102,103"
          } ],
          "uploadFileTimeRange" : 0,
          "videoAnswerQuestionRule" : null,
          "lateNoticeSetting" : null,
          "paper_end_summary" : "本场考试已结束,请保持您的手机、邮箱畅通,方便接收后续通知。",
          "allow_new" : false,
          "allow_camera" : true,
          "allow_screen_record" : false,
          "allow_message" : false,
          "question_disorder" : true,
          "option_disorder" : true,
          "not_need_judge_type" : "3_4",
          "need_judge_type" : "5",
          "faq" : [ ],
          "hide_return_button" : true
        "beenTested" : false,
        "passScoreLine" : null,
        "projectId" : 1643,
        "projectName" : "liumeng测试",
        "departmentList" : null,
        "previewOverdueTime" : null,
        "paperType" : null,
        "hasNotAttendTestUser" : false,
        "antiCheatStr" : "开启摄像头,题目乱序,选择题选项乱序,开启举报平台",
        "signUpFieldTitles" : "投递编号,姓名,手机号码,邮箱,职位,学校,学历",
        "creatorHrId" : 30,
        "creatorHrName" : null,
        "needJudge" : 0,
        "notStartedCount" : 0,
        "inProgressCount" : 0,
        "expiredCount" : 0,
        "cheatTaskStatus" : 0,
        "faceDetectedRation" : 0.0,
        "codeDetectedRation" : 0.0,
        "screenDetectedRation" : 0.0,
        "hasCodeQuestion" : false,
        "hasCtsPic" : true,
        "hasScreen" : false,
        "questionDesc" : "子卷1: 1 1 道,2 1 道,3 1 道<br>子卷2: 2 1 道,3 1 道,4 1 道<br>",
        "interviewPaper" : null,
        "forever" : true
      }, {
        "id" : 17071578,
        "paperName" : "magictest",
        "createTime" : 1615197295000,
        "duration" : 60,
        "score" : 36,
        "personTotal" : 3,
        "avgTotal" : 0.0,
        "summary" : "1、考前请关闭其他浏览器窗口,关闭QQ、微信等即时通信软件,关闭屏保、Outlook等弹窗提示软件,考试中不要切换到考试窗口之外的区域。<br/>\n2、请在规定时间内完成题目,答题过程中系统自动即时,到时自动交卷,请掌握好答题进度;<br/>\n3、请诚信答题,考试全程不要跳出考试页面(在线编程题除外),后台将记录你的跳出次数。编程题交卷后,我们将进行代码相似度判断,标示作弊嫌疑代码。<br/>\n4、笔试过程中遇到任务问题,请通过在线咨询小窗发消息给我们,我们会有相应人员解答。<br/>",
        "logo" : null,
        "questionCount" : 12,
        "diffcult" : 0,
        "beginTime" : 1615197295000,
        "endTime" : 1616818200000,
        "previewUrl" : "https://examd.nowcoder.com/cts/preview/papers/17071578?p_token=L9mTCQXQaLsBUEfFzKlJMrKLgROj5Xk4",
        "testUrl" : "https://examd.nowcoder.com/cts/17071578/summary",
        "mobileTestUrl" : null,
        "assigned" : false,
        "testCount" : 4,
        "assignedCount" : 0,
        "paperSetting" : null,
        "presetUserCount" : 7,
        "paperExcelDownloadUrl" : null,
        "excelTaskStatus" : 0,
        "finished" : true,
        "started" : true,
        "setting" : {
          "logo" : "https://dev-private-public.oss-cn-hangzhou.aliyuncs.com/images/20201130/30_1606732062638/3669B06677BFB1053B71DAA1400C3083",
          "paperSummary" : "1. 请使用最新版Chrome浏览器作答(不低于82版),如考试需开启摄像头,请确保电脑带有摄像头。\n2. 一旦开始考试,请勿离开答题页面,除非当前目录明确提醒可以离开,前三次离开会有提醒,之后将不再提醒。各目录是否支持离开答题页面则取决于试卷具体设置,进入每个目录会有提示。\n3. 考试过程中允许使用草稿纸,请提前准备纸笔。允许上厕所等短暂离开,请控制离开时间。\n4. 考试期间如遇到断电、断网、死机等问题,关闭浏览器重新打开试卷链接即可继续做题。\n5. 遇到问题请即时反馈给考试主办方。",
          "examDisclaimer" : null,
          "antiJumpOut" : false,
          "antiDesignJumpOut" : false,
          "antiCodingJumpOut" : false,
          "codeSimilarRate" : 80,
          "setSourceCoderCheat" : false,
          "monitorPhone" : false,
          "allowMobileTest" : false,
          "noQueueUp" : false,
          "signUpFields" : [ {
            "title" : "姓名",
            "name" : "name",
            "format" : "",
            "need" : true,
            "edit" : 0,
            "valueType" : 0,
            "valueList" : null
          }, {
            "title" : "投递编号",
            "name" : "key",
            "format" : "",
            "need" : true,
            "edit" : 0,
            "valueType" : 0,
            "valueList" : null
          }, {
            "title" : "手机号码",
            "name" : "phone",
            "format" : "Phone",
            "need" : false,
            "edit" : 0,
            "valueType" : 0,
            "valueList" : null
          }, {
            "title" : "邮箱",
            "name" : "email",
            "format" : "Email",
            "need" : false,
            "edit" : 0,
            "valueType" : 0,
            "valueList" : null
          }, {
            "title" : "职位",
            "name" : "zhi2_wei4",
            "format" : "",
            "need" : false,
            "edit" : 0,
            "valueType" : 0,
            "valueList" : null
          }, {
            "title" : "学校",
            "name" : "xue2_xiao4",
            "format" : "",
            "need" : false,
            "edit" : 0,
            "valueType" : 0,
            "valueList" : null
          }, {
            "title" : "学历",
            "name" : "xue2_li4",
            "format" : "",
            "need" : false,
            "edit" : 0,
            "valueType" : 0,
            "valueList" : null
          } ],
          "relationType" : 0,
          "questionCategories" : {
            "1" : "单选"
          "questionIdsTypes" : { },
          "questionScores" : null,
          "questionNewCounts" : null,
          "relationJsonString" : null,
          "questionCategoryRule" : null,
          "questionCategoryOrder" : "1,2,3,4,5",
          "randomQuestion" : false,
          "customCategory" : false,
          "randomFrequentType" : 0,
          "version" : "1.0",
          "questionTagNames" : { },
          "codingScoreRule" : 1,
          "chooseScoreRule" : 3,
          "checkCheat" : true,
          "allowCopy" : false,
          "allowCalculator" : false,
          "contestDomain" : null,
          "navLogoUrl" : null,
          "hideNowcoder" : false,
          "simulation" : false,
          "languageLimit" : false,
          "languageList" : [ ],
          "reportPlatform" : true,
          "forbidPreview" : true,
          "needMobileCamera" : false,
          "codePlayback" : false,
          "timeLimitType" : 0,
          "timeLimitDetail" : null,
          "tiankongScores" : "{}",
          "otherJobIds" : null,
          "subPaperSetting" : null,
          "uploadFileTimeRange" : 0,
          "videoAnswerQuestionRule" : null,
          "lateNoticeSetting" : null,
          "paper_end_summary" : "本场考试已结束,请保持您的手机、邮箱畅通,方便接收后续通知。",
          "allow_new" : false,
          "allow_camera" : true,
          "allow_screen_record" : false,
          "allow_message" : false,
          "question_disorder" : true,
          "option_disorder" : true,
          "not_need_judge_type" : "3_4",
          "need_judge_type" : "5",
          "faq" : [ ],
          "hide_return_button" : true
        "beenTested" : false,
        "passScoreLine" : null,
        "projectId" : 1643,
        "projectName" : "liumeng测试",
        "departmentList" : null,
        "previewOverdueTime" : null,
        "paperType" : null,
        "hasNotAttendTestUser" : false,
        "antiCheatStr" : "开启摄像头,题目乱序,选择题选项乱序,开启举报平台",
        "signUpFieldTitles" : "投递编号,姓名,手机号码,邮箱,职位,学校,学历",
        "creatorHrId" : 30,
        "creatorHrName" : null,
        "needJudge" : 0,
        "notStartedCount" : 0,
        "inProgressCount" : 0,
        "expiredCount" : 0,
        "cheatTaskStatus" : 3,
        "faceDetectedRation" : 0.0,
        "codeDetectedRation" : 0.0,
        "screenDetectedRation" : 0.0,
        "hasCodeQuestion" : false,
        "hasCtsPic" : true,
        "hasScreen" : false,
        "questionDesc" : "单选 12 道",
        "interviewPaper" : null,
        "forever" : false
    

    根据试卷id批量获取试卷。开发者可以通过考生所属的试卷id来获取试卷的详细信息。如果试卷id不存在,会返回code=1的报错。

    GET /papers/multi

    paperIds List<Long>

    试卷信息数组,试卷关键信息见试卷关键返回字段

    删除试卷

    public class Main {
      @Test
      public void testDeletePaper() {
        long paperId = 17131854;
        String path = String.format("/papers/%d", paperId);
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "DELETE");
        System.out.println(responseString);
    
    curl --location --request DELETE 'https://dapi.nowcoder.com/v1/papers/17131854' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  \
     --data-raw 'api_key=huaxinjiayou%40126.com'
      "code" : 0,
      "msg" : "OK",
      "data" : "OK"
    

    根据试卷id删除试卷,删除之后,试卷的做题记录将同时清除。这个接口是幂等的,可以删除已经删除的试卷(无事发生)。

    DELETE /papers/{paperId}

    paperId 需填充在url中

    不需要关注返回数据。只需要检查接口请求是否成功(返回HTTP状态码为 200 且内容中的code=0

    根据试卷ID获取试卷信息

    public class Main {
      @Test
      public void testGetPaperPreview() {
        long paperId = 17071578;
        String path = String.format("/papers/%d", paperId);
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "POST");
        System.out.println(responseString);
    
    curl --location --request POST 'https://dapi.nowcoder.com/v1/papers/17071578/previews' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  \
     --data-raw 'api_key=huaxinjiayou%40126.com&shortUrl=true'
      "code" : 0,
      "msg" : "OK",
      "data" : "https://dwz.cn/HTQwVSEe"
    

    GET /papers/{paperId}

    paperId 不能小于1,需填充在url中

    试卷信息数组,试卷关键信息见试卷关键返回字段

    分享试卷预览

    public class Main { 
      @Test
      public void testGetPaperPreview() {
        long paperId = 17071578;
        String path = String.format("/papers/%d/previews", paperId);
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        mvMap.put("shortUrl", true);
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "POST");
        System.out.println(responseString);
    
    curl --location --request POST 'https://dapi.nowcoder.com/v1/papers/17071578/previews' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  \
     --data-raw 'api_key=huaxinjiayou%40126.com&shortUrl=true'
      "code" : 0,
      "msg" : "OK",
      "data" : "https://dwz.cn/U4QdDWK8"
    

    接口可以用于在开发者自己的系统中预览牛客的试卷。

    POST /papers/{paperId}/previews

    paperId 不能小于1,需填充在url中 shortUrl boolean 默认true,可以为false 是否需要转换成短链接

    字符串类型的链接地址。

    笔试-考生管理

    (考生实体)关键字段

    考生包含了考生的个人信息,每一位考生归属一张试卷,每一位考生有自己的专属笔试链接。

    考生实体的创建、删除和查询可调用考生管理接口获取,下面是考生实体的一些关键字段。

    testId String 考生id加密版,32位字符 (该字段建议入库保存,成绩报告回调时会回传testId字段,可用于进行考生成绩关联) userKey String 业务侧唯一用户标识,同张试卷下userKey唯一(通过paperId+userKey,也可以用于成绩报告回调时关联) String email String phone String testUrl String 考生的专属考试链接 shortTestUrl String 考生的专属考试链接(短链形式,打开自动跳转testUrl,目前仅对AI面试场景开放) testBeginTime 考试链接最早可以开始作答时间,如果试卷当前正在使用,该时间默认为考试链接生成时间;但如果试卷未开始,则该时间可能晚于当前时间 testExpireTime 考试链接过期时间(对长期有效链接,默认取值'9999-12-31';20240614之前创建的长期有效链接,该字段则为null) started boolean 考生的考试是否已开始,true已开始 testStatus 考生考试状态,1没有开始考试,2表示已经打开,3表示已经提交 String paperId paperName String paperStarted boolean 试卷是否已开始 signStatus 考生确认是否参加考试状态 noSignReason String 拒绝参加考试的原因 emailNotification 邮件发起通知次数 smsNotification 短信发起通知次数 emailSentStatus 邮件发送状态, 0未发送,1发送中,2发送失败,3接收成功,4接收失败,5定时发送,6取消发送 smsSentStatus 短信发送状态, 0未发送,1发送中,2发送失败,3接收成功,4接收失败,5定时发送,6取消发送 createTime

    (添加考生前)检测余额是否充足

    public class Main {
      @Test
      public void testAddTestUsersCheckBalance() {
        String path = "/papers/test_users/checkBalance";
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        long paperId = 17071600;
        int userCnt = 2;
        mvMap.put("paperId_userCounts", paperId + "_" + userCnt);
        long anotherPaperId = 17071600;
        int anotherUserCnt = 2;
        mvMap.put("paperId_userCounts", anotherPaperId + "_" + anotherUserCnt);
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "GET");
        System.out.println(responseString);
    
    curl --location --request GET 'https://dapi.nowcoder.com/v1/papers/test_users/[email protected]&paperId_userCounts=17071600_2&paperId_userCounts=17071600_2' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "hostId" : 30,
        "adminHrId" : 30,
        "moneyEnough" : true,
        "subAccountLimitEnough" : true
    

    在添加考生前,可以通过该接口预估添加考生时是否余额足够。

    GET /papers/test_users/checkBalance

    paperId_userCounts List<String> 格式为:试卷id_考生数量。可传多个 按试卷id聚合考生数量, hostId 当前账号id adminHrId 当前账号的公司主账号id moneyEnough 公司主账号的余额是否充足 subAccountLimitEnough 子账号分配的业务额度是否充足 public void testAddTestUsers() { long paperId = 17131890; String path = String.format("/papers/%d/test_users", paperId); MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>(); mvMap.put("name", "郭凯俊1"); mvMap.put("key", "gkj1"); mvMap.put("phone", "18812341234"); mvMap.put("email", "[email protected]"); mvMap.put("shen1_fen4_zheng4", "431123199911116666"); mvMap.put("zhi2_wei4", "Java开发工程师"); mvMap.put("xue2_xiao4", "清北大学"); mvMap.put("xue2_li4", "本科"); mvMap.put("note", "这个考生是通过API添加的"); mvMap.put("name", "郭凯俊2"); mvMap.put("key", "gkj2"); mvMap.put("phone", "18812341234"); mvMap.put("email", "[email protected]"); mvMap.put("shen1_fen4_zheng4", "431123199911116666"); mvMap.put("zhi2_wei4", "Java开发工程师"); mvMap.put("xue2_xiao4", "清北大学"); mvMap.put("xue2_li4", "本科"); mvMap.put("note", "这个考生是通过API添加的"); mvMap.put("failOnExist", false); mvMap.put("notice", false); mvMap.put("version", 0); String responseString = NowcoderApiRequestUtils.request(path, mvMap, "POST"); System.out.println(responseString);
    curl --location --request POST 'https://dapi.nowcoder.com/v1/papers/17131890/test_users' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  \
     --data-raw 'api_key=huaxinjiayou%40126.com&note=%E8%BF%99%E4%B8%AA%E8%80%83%E7%94%9F%E6%98%AF%E9%80%9A%E8%BF%87API%E6%B7%BB%E5%8A%A0%E7%9A%84&note=%E8%BF%99%E4%B8%AA%E8%80%83%E7%94%9F%E6%98%AF%E9%80%9A%E8%BF%87API%E6%B7%BB%E5%8A%A0%E7%9A%84&failOnExist=false&phone=18812341234&phone=18812341234&shen1_fen4_zheng4=431123199911116666&shen1_fen4_zheng4=431123199911116666&name=%E9%83%AD%E5%87%AF%E4%BF%8A1&name=%E9%83%AD%E5%87%AF%E4%BF%8A2&xue2_xiao4=%E6%B8%85%E5%8C%97%E5%A4%A7%E5%AD%A6&xue2_xiao4=%E6%B8%85%E5%8C%97%E5%A4%A7%E5%AD%A6&zhi2_wei4=Java%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88&zhi2_wei4=Java%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88&version=0&key=gkj1&key=gkj2&email=guokaijun%40nowcoder.com&email=guokaijun%40nowcoder.com&xue2_li4=%E6%9C%AC%E7%A7%91&xue2_li4=%E6%9C%AC%E7%A7%91&notice=false'
      "code" : 0,
      "msg" : "OK",
      "data" : [ {
        "id" : 2115087,
        "email" : null,
        "phone" : null,
        "testId" : "DCC8EDB8828E22D5",
        "paperId" : 17131890,
        "paperName" : null,
        "userKey" : "gkj1",
        "name" : null,
        "ext" : null,
        "testUrl" : "https://examd.nowcoder.com/cts/17131890/summary?id=DCC8EDB8828E22D5",
        "started" : false,
        "signStatus" : 0,
        "noSignReason" : null,
        "emailNotification" : 0,
        "smsNotification" : 0,
        "emailSentStatus" : 0,
        "smsSentStatus" : 0,
        "note" : null,
        "createTime" : null,
        "testStatus" : 0,
        "realTestId" : 0,
        "ctsDepartment" : null,
        "creatorHrUid" : 0,
        "creatorHrName" : null,
        "apiRole" : 0,
        "emailRecordCount" : 0,
        "smsRecordCount" : 0,
        "emailRecord" : null,
        "smsRecord" : null,
        "emailSuccessCount" : 0,
        "smsSuccessCount" : 0,
        "paperStarted" : false,
        "arrangeFeedbackId" : 0,
        "arrangeFeedbackTime" : null,
        "arrangeFeedbackContent" : null,
        "errMsg" : null,
        "paperStartTime" : 1735660800000,
        "paperEndTime" : 1738339200000
      }, {
        "id" : 2115088,
        "email" : null,
        "phone" : null,
        "testId" : "C72B030BD2287647",
        "paperId" : 17131890,
        "paperName" : null,
        "userKey" : "gkj2",
        "name" : null,
        "ext" : null,
        "testUrl" : "https://examd.nowcoder.com/cts/17131890/summary?id=C72B030BD2287647",
        "started" : false,
        "signStatus" : 0,
        "noSignReason" : null,
        "emailNotification" : 0,
        "smsNotification" : 0,
        "emailSentStatus" : 0,
        "smsSentStatus" : 0,
        "note" : null,
        "createTime" : null,
        "testStatus" : 0,
        "realTestId" : 0,
        "ctsDepartment" : null,
        "creatorHrUid" : 0,
        "creatorHrName" : null,
        "apiRole" : 0,
        "emailRecordCount" : 0,
        "smsRecordCount" : 0,
        "emailRecord" : null,
        "smsRecord" : null,
        "emailSuccessCount" : 0,
        "smsSuccessCount" : 0,
        "paperStarted" : false,
        "arrangeFeedbackId" : 0,
        "arrangeFeedbackTime" : null,
        "arrangeFeedbackContent" : null,
        "errMsg" : null,
        "paperStartTime" : 1735660800000,
        "paperEndTime" : 1738339200000
    

    接口用于向试卷中添加考生。如果试卷不允许用户自己报名参加,只有再这里添加的用户才能参加考试(直接打开接口返回的URL来考试)。 接口可以同时添加多个用户,即传多个keys和names参数,数量要保持一致。其他选填字段如手机、邮箱等,方式相同。 试卷配置中默认的手机字段为phone, 邮箱为email,其他为汉语拼音加声调加下划线。例如职位zhi2_wei4, 学历xue2_li4。

    POST /papers/{paperId}/test_users

    除列表中展示的字段外,还可以填入考生的其他选填字段。例如职位zhi2_wei4, 学历xue2_li4。详情见代码示例

    paperId 需填充在url中 List<String> 考试编号,在同一个试卷内唯一确定一个用户的字符串,不能包含emoji字符 List<String> 和key对应的用户的姓名,姓名不能包含如下字符: `~!@#$%^&*()+=|{}':;[]<>/?!¥…()—【】‘;:”“’。、? foreignKey List<String> 同1位候选人(自然人)在其它场景(比如AI面试)使用的考试编号,与key字段相对应。比如笔试场景下,key代表的是该候选人在本场考试下的考试编号,而foreignKey可代表该候选人在后续AI面试中的编号,通过这2个Key可以跨场景关联到同1个人。 userData List<String> 候选人信息,主要用于AI面试智能化出题、智能追问等场景,数据类型为json对象转string,json结构定义请参考文档候选人信息Json结构定义 callback String 回调地址,填写后将配置:完成考试、作弊检测、人工判题、考生被删除 四种类型的回调。更多关于回调类型的信息见:链接 failOnExist boolean 为true时,如果导入前这个考生的key已经存在,则直接返回失败 userType 考生类型: 0 普通考生 1 测试考生,可提前进入考试答题。每张试卷可免费添加10个测试考生,超过部分将扣费 confirm boolean 当添加测试考生且即将扣费时,需要confirm=true时才能继续操作。 List<String> 和key对应的用户的备注,可以不传 version 0:当所有考生格式正确才会添加,1:格式正确考生会录入成功 notice boolean true:使用牛客默认模版发送手机短信和邮件通知,false:不发送 emailTemplateId 仅在notice=true时有效,用于指定本次通知的邮件版本 smsTemplateId 仅在notice=true时有效,用于指定本次通知的短信版本 emailTemplateId和smsTemplateId的取值,目前不支持产品化,但技术同学可以在HR后台,通过截图中的示例方案自助获取。点击查看emailTemplateId/smsTemplateId获取示例

    已经添加过的考生信息数组。接口需要关心下面的字段

    errMsg 添加考生失败的时候,返回的考生id=0,此时这个字段会返回错误原因

    其他参数见考生关键信息见考生关键返回字段

    删除考生

    public class Main {
      @Test
      public void testDeleteTestUser() {
        long paperId = 17131890;
        long testUserId = 2115115;
        String path = String.format("/papers/%d/test_users/%d", paperId, testUserId);
        // 考试已经开始无法删除考生。
        // 已经删除的考生无法删除。
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "DELETE");
        System.out.println(responseString);
    
    curl --location --request DELETE 'http://localhost:8888/v1/papers/17131890/test_users/2115115' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  \
     --data-raw 'api_key=huaxinjiayou%40126.com'
    # 删除成功
      "code" : 0,
      "msg" : "OK",
      "data" : "该考生未参加考试,考试费用15.0元已退回您的账户。"
    # 考生曾经删除成功 或者 考生没有被添加过
      "code" : 1,
      "msg" : "考生不存在",
      "details" : null
    

    通过考生id删除牛客系统中的一个考生。

    DELETE /papers/{paperId}/test_users/{id}

    paperId 需填充在url中 需填充在url中

    无需关心返回数据,接口请求成功则视为删除成功

    如果考生成功删除,示例信息如下: "code" : 0, "msg" : "OK", "data" : "该考生未参加考试,考试费用15.0元已退回您的账户。" 如果考生曾经删除成功或者考生没有被添加过,会返回下面的错误信息。 "code" : 1, "msg" : "考生不存在", "details" : null 删除时机说明(包括批量删除接口):
    1. 在笔试场景下,只允许删除尚未开始考试的考生。
    2. 在AI面试场景下,对删除考生时机已放开限制;如果被删考生正在面试中,删除后会中断并结束面试;如果面试已结束,相关面试记录都也会被删除。请警慎操作!

    批量删除考生

    public class Main {
      @Test
      public void testDeleteMultiTestUsers() {
        String delUsersPath = String.format("/papers/%d/test_users", 0);
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        mvMap.put("ids", 2115077);
        mvMap.put("ids", 2115081);
        mvMap.put("paperIds", 17131890);
        mvMap.put("paperIds", 17131891);
        mvMap.put("isAll", 2);
        String responseString = NowcoderApiRequestUtils.request(delUsersPath, mvMap, "DELETE");
        System.out.println(responseString);
    
    curl --location --request DELETE 'https://dapi.nowcoder.com/v1/papers/0/test_users' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  \
     --data-raw 'api_key=huaxinjiayou%40126.com&ids=2115077&ids=2115081&isAll=2&paperIds=17131890&paperIds=17131891'
      "code" : 0,
      "msg" : "OK",
      "data" : "UBfCoqS08apsZ8QIEojbsmfpyxUCaYgh"
    

    通过多个考生id批量删除牛客系统中的考生。该接口会异步进行处理。无需关心返回数据,接口请求成功则视为删除成功

    如果确实需要获取异步任务信息,根据接口返回的异步任务id请求接口[获取异步任务进度](#system-async-job-process)

    DELETE /papers/{paperId}/test_users

    List<Long> 考生id。可以填多个 paperIds List<Long> 试卷id,需要包含所有考生所属的试卷ids。可以填多个,但列表中id不能重复 isAll 用于指定接口取paperIds paperId 用于填充参数中的url

    牛客异步任务id。

    查询单个考生信息

    public class Main {
      @Test
      public void testGetTestUser() {
        long paperId = 17131890;
        long testUserId = 2115086;
        String path = String.format("/papers/%d/test_users/%d", paperId, testUserId);
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "GET");
        System.out.println(responseString);
    
    curl --location --request GET 'https://dapi.nowcoder.com/v1/papers/17131890/test_users/[email protected]' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "id" : 2115086,
        "email" : "[email protected]",
        "phone" : "18812341234",
        "testId" : null,
        "paperId" : 17131890,
        "paperName" : null,
        "userKey" : "gkj",
        "name" : "郭凯俊",
        "ext" : "{\"phone\":\"18812341234\",\"name\":\"郭凯俊\",\"xue2_xiao4\":\"清北大学\",\"zhi2_wei4\":\"Java开发工程师\",\"key\":\"gkj\",\"email\":\"[email protected]\",\"xue2_li4\":\"本科\"}",
        "testUrl" : null,
        "started" : false,
        "signStatus" : 0,
        "noSignReason" : "",
        "emailNotification" : 0,
        "smsNotification" : 0,
        "emailSentStatus" : 0,
        "smsSentStatus" : 0,
        "note" : "这个考生是通过API添加的",
        "createTime" : 1628147456000,
        "testStatus" : 1,
        "realTestId" : 0,
        "ctsDepartment" : null,
        "creatorHrUid" : 30,
        "creatorHrName" : null,
        "apiRole" : 2,
        "emailRecordCount" : 0,
        "smsRecordCount" : 0,
        "emailRecord" : null,
        "smsRecord" : null,
        "emailSuccessCount" : 0,
        "smsSuccessCount" : 0,
        "paperStarted" : false,
        "arrangeFeedbackId" : 0,
        "arrangeFeedbackTime" : 1628147456000,
        "arrangeFeedbackContent" : null,
        "errMsg" : null,
        "paperStartTime" : null,
        "paperEndTime" : null
    

    接口用于查询单个考生的信息

    GET /papers/{paperId}/test_users/{id}

    paperId 需填充在url中 需填充在url中

    考生关键信息见考生关键返回字段

    更新单个考生信息

    public class Main {
      @Test
      public void testUpdateTestUser() {
        long paperId = 17131890;
        long testUserId = 2115086;
        String path = String.format("/papers/%d/test_users/%d", paperId, testUserId);
        // 考试已经开始无法删除考生。
        // 已经删除的考生无法删除。
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        mvMap.put("name", "郭凯俊");
        mvMap.put("key", "gkj");
        mvMap.put("phone", "18812341234");
        mvMap.put("email", "[email protected]");
        mvMap.put("shen1_fen4_zheng4", "431123199911116666");
        mvMap.put("zhi2_wei4", "Java开发工程师");
        mvMap.put("xue2_xiao4", "清北大学");
        mvMap.put("xue2_li4", "本科");
        mvMap.put("note", "这个考生是通过API添加的");
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "PUT");
        System.out.println(responseString);
    
    curl --location --request PUT 'https://dapi.nowcoder.com/v1/papers/17131890/test_users/2115086' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  \
     --data-raw 'api_key=huaxinjiayou%40126.com&note=%E8%BF%99%E4%B8%AA%E8%80%83%E7%94%9F%E6%98%AF%E9%80%9A%E8%BF%87API%E6%B7%BB%E5%8A%A0%E7%9A%84&phone=18812341234&shen1_fen4_zheng4=431123199911116666&name=%E9%83%AD%E5%87%AF%E4%BF%8A&xue2_xiao4=%E6%B8%85%E5%8C%97%E5%A4%A7%E5%AD%A6&zhi2_wei4=Java%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88&key=gkj&email=guokaijun%40nowcoder.com&xue2_li4=%E6%9C%AC%E7%A7%91'
      "code" : 0,
      "msg" : "OK",
      "data" : null
    

    接口用于更新单个考生的信息

    PUT /papers/{paperId}/test_users/{id}

    paperId 需填充在url中 需填充在url中 String String 考试编号,在同一个试卷内唯一确定一个用户的字符串,不能包含emoji字符 departmentId 所属部门,为0表示公开 userType String notice boolean 是否发送通知,true发送、false不发送 emailTemplateId 仅在notice=true时有效,用于指定本次通知的邮件版本 smsTemplateId 仅在notice=true时有效,用于指定本次通知的短信版本

    无需关心返回数据,接口请求成功则视为删除成功

    批量查询当前考生状态

    接口地址

    /v1/partners/paper/batch_user_status

    请求方法和类型

    post, application/json

    请求和回报参数见右边

    请求参数:
      "paperId": "必填,long,试卷id",
      "userKeyList": "必填,string array,考试编号,单次最多查询50个考生"
    
    回包参数:
      "code": "int:0表示成功,非0表示失败",
      "msg": "string:code非0时表示报错原因",
      "data": {
        "userList": [
            "id": "long, 考生id",
            "userKey": "string, 考试编号",
            "status": "int, 考生状态,ai面试场景:1.面试未开始,2.待面试,3.已过期,4.面试中,5.已完成,6.判题完成;笔试场景:210.未进入考试,220.已开考,230.作答完成"
    

    笔试-考生成绩管理

    查询单个考生考试结果

    public class Main {
      @Test
      public void testGetUserTestInfo() {
        String path = "/papers/usertestinfo";
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        mvMap.put("paperId", 17131674);
        mvMap.put("userkey", "qwe");
        mvMap.put("needCategoryScore", true);
        mvMap.put("needCheatInfo", true);
        mvMap.put("needJudgeInfo", true);
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "GET");
        System.out.println(responseString);
    
    curl --location --request GET 'https://dapi.nowcoder.com/v1/papers/[email protected]&needCategoryScore=true&needCheatInfo=true&needJudgeInfo=true&paperId=17131674&userkey=qwe' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  
      "code" : 0,
      "msg" : "OK",
      "data" : [ {
        "paperName" : "编程题测试2",
        "pdfUrl" : "https://dapi.nowcoder.com/v1/test-pdf/F23269B6DFB0F586?paperId=17131674&tokenValue=cbe1f318a47b50c7e7f096ff6cbf2ed8746df596943e48f971a2a191a36ab07d&download=false",
        "userScore" : 0.0,
        "paperScore" : 60,
        "status" : 2,
        "cheatStatus" : 3,
        "beginTime" : 1626785242000,
        "finishTime" : 1626797842000,
        "createTime" : 1626785226000,
        "apiCategoryScores" : [ {
          "score" : 0.0,
          "categoryType" : 5,
          "questionType" : 5,
          "categoryName" : "问答"
        } ],
        "rankPercent" : 0.25,
        "cheatReasonList" : null,
        "judgeAssignAccountAndJudgeStatuses" : null,
        "judgeRemarkInfos" : null,
        "cheatInfoDesc" : null,
        "finalScore" : true
    

    查询单个考生考试结果信息。如果考生没有参加考试无法查到信息。

    GET /papers/usertestinfo

    paperId 试卷id(不传的话会查询所有试卷中考试编号为userkey的考生,传了就查指定试卷中的) userkey String 考试编号,对应添加考生接口中key字段值 needCategoryScore boolean 是否需要不同题型得分 needCheatInfo boolean 是否需要作弊信息 needJudgeInfo boolean 是否需要人工判题信息,仅在paperId>0时有效 pdfFileType 0表示返回在线预览的pdf地址,1表示返回可下载的pdf地址

    接口的返回数据由考生信息与考生测评信息结合而成。

    paperName pdfUrl 报告pdf链接 webReportUrl 在线报告链接 userScore paperScore testResult 表示考试结果,取值passed表示“通过”,failed表示“不通过” rejectionReasons 表示筛选不通过的原因(仅在testResult="failed"时有效);原因存在多项时,采用";"进行拼接;没值时用null表示 specialNotes 表示报告中需要特别关注的事情;存在多个关注事项时,采用";"进行拼接;没值时用null表示 moduleScores 表示考生按能力项维度聚合的得分情况。这个参数会有多个,每一个的参数格式是moduleScore|moduleName 如 "70.5|英语能力",moduleScore为skillScore的上级维度 skillScores 表示考生按技能项维度聚合的得分情况。这个参数会有多个,每一个的参数格式是skillScore|skillName 如 "60.5|抗压能力",skillScore为moduleScore的下级维度 status 考生未参加考试(-1),系统判题未完成(1), 考试进行中(0), 已交卷(2), 人工判题完成(4) cheatStatus 作弊检测未完成(0), 作弊(1), 未作弊(2), 作弊疑似(3) beginTime 开始答卷时间 finishTime createTime 笔试的安排时间 elapseTime 测评消耗时间,单位是秒 rankPercent 浮点型排名百分比 rankScore 考生得分中位数 finalScore 是否是最终成绩:需要人工判题的,若人工判题完成则为最终成绩;无需人工判题的,只要交卷就是最终成绩 judgeRemarkInfos 判题备注,对象数组 cheatInfoDesc 作弊描述信息,单个字符串 apiCategoryScores 各个目录得分,对象数组 cheatReasonList 以文字表述的作弊原因字符串数组。具体信息见链接 judgeAssignAccountAndJudgeStatuses 判题备注 ,对象数组。分配的判题账户列表以及相应的完成状态 headUrl 考生自拍头像链接

    目录得分数据结构

    score categoryType questionType 题目类型:单选(1), 不定项选择(2), 填空(3), 编程(4), 问答(5) , categoryName

    目录得分数据结构

    userId 判题的账号id userName 判题的账号名称 judgeStatus 判题完成的状态,值枚举:已判题/未判题

    判题备注数据结构

    userName 判题的账号名称 summaryRemark questionRemarkInfos 各题目备注,对象数组
    题目备注数据结构
    questionName 例如:填空题第1题 remark

    获取某个用户拥有卷子的测评信息

    public class Main {
      @Test
      public void testGetPaperTestsInfo() {
        String path = String.format("/tests/poid-%d", ConfigUtils.getNowcoderHrId());
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        mvMap.put("projectIdList", 2227);
        mvMap.put("paperIds", 17131674);
        mvMap.put("page", 1);
        mvMap.put("pageSize", 1);
        mvMap.put("order", 2);
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "POST");
        System.out.println(responseString);
    
    curl --location --request POST 'https://dapi.nowcoder.com/v1/tests/poid-30' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  \
     --data-raw 'api_key=huaxinjiayou%40126.com&pageSize=1&page=1&projectIdList=2227&paperIds=17131674&order=2'
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "totalCount" : 4,
        "totalPage" : 4,
        "currentPage" : 1,
        "datas" : [ {
          "id" : 1838108,
          "encryptId" : null,
          "actorId" : 2114808,
          "paperId" : 17131674,
          "paperName" : "编程题测试2",
          "finishTime" : 1626797842000,
          "status" : 2,
          "score" : 0.0,
          "paperScore" : 60.0,
          "paperOpenCount" : 4,
          "createTime" : 1626785242000,
          "actorType" : 10,
          "elapseTime" : 40,
          "leaveCount" : 4,
          "headUrl" : "",
          "signatureUrl" : null,
          "ipAddress" : "北京市",
          "ip" : "123.118.109.227",
          "cheated" : 3,
          "ncUser" : {
            "id" : 2114808,
            "email" : null,
            "nickname" : "aweqwe",
            "phone" : null,
            "displayName" : "aweqwe"
          "user" : {
            "id" : 2114808,
            "email" : null,
            "nickname" : "aweqwe",
            "phone" : null,
            "displayName" : "aweqwe"
          "testUserKey" : "qwe",
          "questionCount" : 0,
          "rightCount" : 0,
          "numberRank" : 1,
          "percentRank" : 0,
          "difficulty" : 0,
          "key" : null,
          "keyTitle" : null,
          "name" : null,
          "nameTitle" : null,
          "creatorHrUid" : 0,
          "creatorHrName" : "管理员",
          "pdfUrl" : null,
          "testResultUrl" : "https://dapi.nowcoder.com/v1/test-pdf/F23269B6DFB0F586?paperId=17131674&tokenValue=cbe1f318a47b50c7e7f096ff6cbf2ed8746df596943e48f971a2a191a36ab07d&download=false",
          "notJudgedTypes" : [ 3 ],
          "needJudge" : true,
          "picCount" : 0,
          "review" : null,
          "questionTypeList" : null,
          "categoryTypeList" : null,
          "signUpFields" : null,
          "userExt" : {
            "phone" : "",
            "name" : "aweqwe",
            "xue2_xiao4" : "",
            "zhi2_wei4" : "",
            "email" : "",
            "xue2_li4" : "",
            "key" : "qwe"
          "remarkList" : null,
          "antiJumpOut" : false,
          "allowCamera" : false,
          "allowScreenRecord" : false,
          "monitorPhone" : false,
          "needMobileCamera" : false,
          "hasCodeProblem" : false,
          "hasHistoryData" : false,
          "judgingPermission" : null,
          "canSee" : true,
          "price" : 30.0,
          "cheatReasonList" : [ ],
          "testUserNote" : null,
          "paperSimulation" : false,
          "categoryScores" : null,
          "categoryTotalScores" : null,
          "timeCount" : null,
          "resumeId" : 0,
          "resumePermit" : 0,
          "recruitProjectId" : 0,
          "judged" : true,
          "notJudgedReason" : null,
          "judgingTip" : "需要人工阅卷的题目答案为空,系统自动判题",
          "resumeForJudge" : null,
          "deliverId" : 0,
          "testPeriod" : null,
          "clientSystem" : 1,
          "longValidTime" : true,
          "previewOverdueTime" : null,
          "tagNameList" : [ ],
          "bought" : true,
          "tagList" : null
        } ],
        "ext" : {
          "lackCount" : "0"
    

    根据查询条件,查询当前账户下的考生成绩。

    POST /tests/poid-{paperOwnerId}

    paperOwnerId 必传,需填充在url中 当前用户的HRId paperIds List<Long> 用于筛选试卷id,可不传 projectIdList List<Long> 用于筛选项目id,可不传 非必传,从1开始,默认为1 pageSize 非必传,默认为20 orderBy 非必传,默认0 根据什么排序,默认为0;0根据考生开始测评的时间排序,1根据考生完成测评的时间排序,2根据考生测评的分数排序 order 非必传,默认1 升序还是降序,默认为1升序。1代表升序,2代表降序。 totalCount 列表数据总数 totalPage 列表总页数 currentPage 当前是第几页,从1开始 datas 考生成绩数据数组

    考生成绩对象数据结构

    encryptId actorId 测评用户ID paperId 测评点的试卷 paperName finishTime 测评完成时间 status score 测评的分数 paperScore paperOpenCount 试卷到场人数 createTime 测评开始时间 actorType 测评用户的类型 elapseTime 测评消耗时间,单位是秒 leaveCount headUrl signatureUrl 签名url ipAddress 考生考试ip地址 cheated 是否作弊:0-作弊检测任务未完成,1-作弊,2-未作弊,3-疑似作弊 testUserKey 考试测评用户的主key questionCount rightCount 试题正确的数量 numberRank percentRank 百分比排名 唯一识别用户的Key keyTitle key的标题 测评用户名字 nameTitle 测评用户名字的标题 creatorHrUid 创建测评用户的hr的uid creatorHrName 创建测评用户的hr名字 pdfUrl 测评结果的PDF地址 testResultUrl 笔试报告地址,三方系统请使用此链接查看笔试报告 notJudgedTypes 不判题的题目类型 needJudge 试卷是否需要人工判题 picCount 截图的数量 review 牛客系统评语 questionTypeList signUpFields 需要录入的考生信息 judgingPermission 面试官查看权限 cheatReasonList 作弊原因,仅在cheated=1的时候有值,具体信息见链接 judged 是否已经判题 notJudgedReason 未判题的原因 clientSystem 答题设备1表示pc ,2表示ios 3表示android tagNameList 判题所打的标签名字列表

    笔试-回调服务

    笔试回调服务以考生为维度进行回调,回调的信息为考生信息、考生的考试信息等信息。 回调地址为业务方在调用添加考生接口(POST /papers/{paperId}/test_user)中传入的callback参数。

    回调类型、回调时机与回调配置

    下面这些回调类型需要在调用创建考生接口时,添加callback参数配置回调地址即可订阅一个考生下列回调类型的回调。

    考生手动交卷或考试时间截止自动交卷 作弊检测完成 牛客后台完成了对考生的作弊检测 如果存在作弊重判,可能触发多次回调 人工判题完成 牛客系统中有用户对考生进行了人工判题 仅对开启人工判题的试卷有效 考生被删除 在牛客系统或通过API删除了某个考生 只允许考前删除考生,不涉及成绩报告相关数据 附件上传结束 到了试卷设置附件上传截止时间或这期间的每天0点 仅对考后仍允许上传附件的试卷有效

    下面这些回调类型需要联系牛客开发人员。进行配置

    非长期有效试卷考试结束 成绩报告变化 考生成绩报告发生变化

    如果无特殊要求,建议回调接收方按“可重入”的思路进行方案设计,默认以最新1次的回调结果为准。

    回调参数

    通用回调参数

    完成考试作弊检测人工判题考试结束成绩报告变化这几种回调类型采用的时通用的回调参数。 考生删除链接过期等回调事件,不涉及成绩报告相关信息。

    callbackType 笔试场景下的回调类型:1.人工判题完成,3.完成考试,4.考试结束,5.成绩报告变化,6.作弊检测完成,8.考生被删除。 AI面试场景下的回调类型:201. 候选人被删除, 202. ai面试结束, 203. ai面试判题完成, 204. ai面试pdf报告生成完毕。使用建议:非特殊需要,不建议客户方对callbackType进行任何判断,牛客成绩报告默认均以最后1次回调为准,客户方客户保证回调操作可重入/覆盖式更新即可 testId String 测评id唯一标识(String类型),对应到添加考生接口返回的考生实体中的testId字段 numTestId 测评id唯一标识(long类型),对应到添加考生接口返回的考生实体中的id字段 String 业务侧用户唯一标识,对应到考生实体的userKey字段 status String 测评的状态 NOT_DO-未做题,DOING-正在做题,DONE-做完题,JUDGED-人工阅卷完成, CHEAT_DETECT_DONE-作弊检测完成,DELETE-删除 cheatStatus 作弊检测状态 作弊检测未完成(0), 作弊(1), 未作弊(2), 作弊疑似(3) cheatReasonList String 以文字表述的作弊原因字符串数组,具体格式为json中的string array转换出来的字符串。具体信息见链接,有值示例:["摄像头监控异常"],无值示例:[] testStartTime 考生开始考试时间(豪秒级) testFinishTime 考生交卷时间(豪秒级) headUrl String 考生自拍头像链接 score float 考生试卷总得分(%.1f),笔试场景默认为必传,AI面试场景可能为null scoreLeverType 取值:0表示百分制形式;1表示5星形式; scoreLever float 取值定义由scoreLeverType控制,当ScoreLeverType=0时,取值为score(%0.1f)字段值;当scoreLeverType=1时,取值为0.0,0.5,1.0,1.5,...,4.5,5.0,分别对应到5星档位; testResult String 表示考试结果,取值passed表示“通过”,failed表示“不通过” rejectionReasons String 表示筛选不通过的原因(仅在testResult="failed"时有效);原因存在多项时,采用";"进行拼接;没值时用null表示 specialNotes String 表示报告中需要特别关注的事情;存在多个关注事项时,采用";"进行拼接;没值时用null表示 isFinalScore boolean 是否是用户的最终成绩 moduleScores List[String] 表示考生按能力项维度聚合的得分情况。这个参数会有多个,每一个的参数格式是moduleScore|moduleName 如 "70.5|英语能力",moduleScore为skillScore的上级维度 moduleScoreLevers List[String] 表示考生按能力项维度聚合的得分等级情况。这个参数会有多个,每一个的参数格式是moduleScoreLever|moduleName 如 "3.5|英语能力",其中的moduleName与moduleScores中的moduleName一一对应 skillScores List[String] 表示考生按技能项维度聚合的得分情况。这个参数会有多个,每一个的参数格式是skillScore|skillName 如 "60.5|抗压能力",skillScore为moduleScore的下级维度 skillScoreLevers List[String] 表示考生按技能项维度聚合的得分等级情况。这个参数会有多个,每一个的参数格式是skillScoreLever|skillName 如 "4.0|抗压能力",其中的skillName与skillScores中的skillName一一对应 categoryScores List[String] 表示考生按试卷目录维度聚合的得分情况。这个参数会有多个,每一个的参数格式是score|categoryId|categoryName1.5|100|选择题。笔试场景默认为必传,AI面试场景为空 extDataItems List[String] 可扩展的信息维度。这个参数会有多个,每一个的参数格式是json string。结构:{"id": "xx", "name": "xxx", "value": "xxx"} 例子:{"name":"不通过原因","id":"rejectionReasons","value":"候选人放弃面试"} 考生排名,这个排名是在回调的时间点计算出来 isCheated boolean true、false 是否作弊,疑似作弊时为null(待废弃,以cheatStatus字段为准) resultPdfUrl String 测评成绩报告的PDF版本的URL,支持按需配置 onlineTestResultUrl String 测评成绩报告的网页版本的URL,支持按需配置 paperName String paperId paperScore 试卷满分,笔试和试卷中的题目总分有关,ai面试默认100分 needJudge boolean 试卷是否需要人工判题,true表示需要,false不表示不需要 isArchived boolean 代表当前考生是否可以归档,true表示可以归档,false表示还不能归档(该标识仅代表系统判定考生分数不再改变,但是可能存在手动修改考生成绩以及多次重新判题修改分数的情况) 基于数据安全等方面考虑,resultPdfUrl字段返回的pdf成绩报告地址,在2021年7月1日之后将启用基于tokenValue的校验、过期机制。 报告将会6个月之后过期(从回调时间点开始计算时间)。过期时间可登录牛客网企业版, 点击`设置->安全设置`来修改。更新设置将会对新生成的报告生效。
    public class Main {
      @Test
      public void escapeOnlineTestResultUrl() throws UnsupportedEncodingException {
        String onlineTestResultUrl = "https://dhr.nowcoder.com/console?theme=tinyLeft&access_token=1b60b47668a2459416985edfb4c4a2207cf318999c51715e00f722fd235b0b0b#paper/{\"tab\":\"index\",\"action\":\"candidate/result/index\",\"testId\":1837423}";
        int anchorIndex = onlineTestResultUrl.indexOf("#paper/");
        int encodeStrStartIndex = anchorIndex + "#paper/".length();
        String anchorStr  = StringUtils.substring(onlineTestResultUrl, encodeStrStartIndex);
        String encodedAnchorStr = URLEncoder.encode(anchorStr, "UTF-8");
        System.out.println(onlineTestResultUrl.substring(0, encodeStrStartIndex) + encodedAnchorStr);
        onlineTestResultUrl字段在url编码、解码过程中会出现部分字符转义失败的问题,在使用时需要按照Java示例代码中的形式处理。
        这个排名是在回调的时间点计算出来的,如果想实时获取最新排名,请调用查询单个考生考试结果接口
        或获取所有测评信息接口。
        isFinalScore在考生测评无需人工判题、需要人工判题的题目没有作答或者需要人工判题的题目已经判题完成时为true。
        但由于目前牛客系统中可以对已经判题的考生重新判题,因此该字段为true时不代表分数不会发生变化。
        isCheated字段在疑似作弊时为null。后续可能使用新的字段表示:作弊、疑似作弊、没有作弊的情况。
    

    考生被删除

    考试被删除时,只会回传考生的信息,具体参数如下:

    status 测评的状态,在考生删除时为:DELETE(删除) paperId paperName 唯一确定一个用户的字符串

    除了这些字段外,还会带上创建考生时填入的其他字段比如:phoneemail等字段。更多考生个人信息字段详见:添加考生接口

    笔试-免登录判题

    无需登录系统,开放给第三方的判题能力,该接口可获取判题链接,判题链接会失效过期,无需保存,需要时实时获取即可

    GET /judging-tests/quick-judge-url

    paperId userKey String 考试编号,对应添加考生接口中key字段值

    免登录判题短链
    注意:链接有效期默认是2个月,从第一次请求接口生成时算起;同一个考生判题链接只会生成一次重复请求接口返回的是同一个判题链接

    @Test public void testGetProjects() { String path = "/user/interview-projects/all"; MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>(); String responseString = NowcoderApiRequestUtils.request(path, mvMap, "GET"); System.out.println(responseString);
    curl --location --request GET 'https://dapi.nowcoder.com/v1/user/interview-projects/[email protected]' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  
      "code" : 0,
      "msg" : "OK",
      "data" : [ {
        "id" : 1638,
        "name" : "小程序测试",
        "remark" : "",
        "jobNums" : 2,
        "studentNums" : 32,
        "roundNums" : 5,
        "status" : 1,
        "type" : 0,
        "star" : 1,
      }, {
        "id" : 1746,
        "name" : "小程序",
        "remark" : "",
        "jobNums" : 10,
        "studentNums" : 88,
        "roundNums" : 4,
        "status" : 0,
        "type" : 0,
        "star" : 1,
      }, {
        "id" : 1291,
        "name" : "liumeng测试",
        "remark" : "liumeng 测试",
        "jobNums" : 30,
        "studentNums" : 357,
        "roundNums" : 14,
        "status" : 0,
        "type" : 0,
        "star" : 0,
      }, {
        "id" : 1293,
        "name" : "测试",
        "remark" : "呵呵呵",
        "jobNums" : 15,
        "studentNums" : 130,
        "roundNums" : 8,
        "status" : 0,
        "type" : 0,
        "star" : 0,
    

    GET /user/interview-projects/all

    array 面试项目数组,关键信息见面试项目关键返回字段

    面试-面试管理

    面试实体关键字段

    interviewProjectId 面试项目id intervieweeName String 面试者(候选人)姓名 intervieweeEmail String 面试者(候选人)的邮箱 intervieweePhone String 面试者(候选人)的手机 jobType 技术or非技术, 1技术面试、2非技术面试 String deliverId String resumeUrl String 用户简历地址 testResultUrl String round 当前处于第几轮 rounds array 轮次实体关键字段 interviewReportUrl String 面试报告地址 startTime 毫秒级时间戳、面试开始时间,即第一轮面试开始时间 expireTime 毫秒级时间戳、过期时间,到达过期时间且面试未使用过会标记为过期并且退费 elapsedTime 使用时长,单位毫秒 validTime 总的可用时长,单位是秒, 如果为0则默认为3小时。使用时长超过可用时长后面试房间会无法使用,除非延长面试 interviewerUrl String 面试官面试地址 interviewerOfflineUrl String 面试官线下面试地址, 只有开启了线下面试权限才能使用 intervieweeUrl String 候选人面试地址 status 状态,0表示正常,1表示删除,2表示过期。 请不要根据elapsedTimevalidTime判断面试是否超时,或者根据expireTime判断面试是否过期。牛客内部可能有优化策略, 如果需要判断请调用该接口获取面试房间状态

    轮次实体关键字段

    interviewId round 第几轮面试 bookTime 预约时间、毫秒级时间戳 multi 是否多对一面试,0一对一面试,1多对一面试 offline 是否线下面试, 0线上,1线下 interviewerName String 一对一面试字段,面试官姓名 interviewerPhone String 一对一面试字段,面试官电话 interviewerEmail String 一对一面试字段,面试官邮箱 userList array 多对一面试字段,面试官实体关键字段 score 面试评分,0未评分, 1-2未通过,3-5通过 evaluation String elapsedTime 该轮使用时长,单位毫秒 intervieweeImage String 候选人面试过程中的一张照片 status 轮次状态,0未开始、1进行中、3结束、4删除、5暂停、7面试淘汰被自动取消

    面试官实体关键字段

    interviewId roundId round 第几轮面试 String 面试官姓名 phone String 面试官电话 email String 面试官邮箱 是否主持人,0非主持人,1主持人 evaluation String elapsedTime 面试官面试时长, 单位毫秒, 非实时更新 status 状态, 0初始、1删除、2面试中、4结束 一对一面试轮次中,轮次实体字段userList会为空,多对一面试轮次中, 轮次实体字段interviewerName、interviewerPhone、interviewerEmail

    优先检查服务对应可用次数,当可用次数不够时使用账户余额进行检查

    public class Main {
      @Test
      public void testCheckBalance() {
        String path = "/interviews/checkBalance";
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        mvMap.put("techCount", 10);
        mvMap.put("unTechCount", 10);
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "GET");
        System.out.println(responseString);
    
    curl --location --request GET 'https://dapi.nowcoder.com/v1/interviews/[email protected]&unTechCount=10&techCount=10' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "hostId" : 30,
        "adminHrId" : 30,
        "moneyEnough" : true,
        "subAccountLimitEnough" : true
    

    GET /interviews/checkBalance

    techCount 技术类面试数量 unTechCount 非技术类面试数量 copilotFlag boolean 是否开启智能面试(同时对techCount和unTechCount生效),不传默认是false hostId 当前账号id adminHrId 当前账号的公司主账号id moneyEnough boolean 公司主账号的余额是否充足 subAccountLimitEnough boolean 子账号分配的业务额度是否充足 该接口协议由于协议复杂,扩展困难等问题,将不再添加新功能,且不支持最新的功能。请尽量使用新接口创建面试-新版
    public class Main {
      @Test
      public void testCreateInterview(){
        String path = "/interviews";
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        mvMap.put("projectId", 2071);
        mvMap.put("intervieweeName", "nowcoder");
        mvMap.put("intervieweeEmail", "[email protected]");
        mvMap.put("intervieweePhone", "10000000000");
        mvMap.put("copilotFlag", false);
        mvMap.put("job", "java");
        mvMap.put("jobType", 1);
        mvMap.put("jobDesc", "职业介绍");
        mvMap.put("deliverId", "TD6879239819");
        mvMap.put("resumeUrl", "https://www.nowcoder.com");
        mvMap.put("resumeText", "简历文本内容");
        mvMap.put("testResultUrl", "https://www.nowcoder.com");
        mvMap.put("rounds", "2021-08-26 11:00:00|coder|10000000000|[email protected]|0|0");
        mvMap.put("rounds", "2021-08-26 11:30:00|-|-|-|0|1");
        mvMap.put("multiUsers", "2|0|coder1|[email protected]|10000000001|1");
        mvMap.put("multiUsers", "2|0|coder2|[email protected]|10000000002|0");
        mvMap.put("callback", null);
        mvMap.put("callback2", null);
        mvMap.put("finishRedirectUrl", "https://www.nowcoder.com");
        mvMap.put("finishRedirectUrls", "https://www.nowcoder.com");
        mvMap.put("finishRedirectUrls", "https://www.nowcoder.com");
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "POST");
        System.out.println(responseString);
    
    curl --location --request POST 'https://dapi.nowcoder.com/v1/interviews' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  \
     --data-raw 'api_key=huaxinjiayou%40126.com&intervieweeName=nowcoder&multiUsers=2%7C0%7Ccoder1%7Cer1%40nowcoder.com%7C10000000001%7C1&multiUsers=2%7C0%7Ccoder2%7Cer2%40nowcoder.com%7C10000000002%7C0&finishRedirectUrl=https%3A%2F%2Fwww.nowcoder.com&intervieweePhone=10000000000&deliverId=TD6879239819&intervieweeEmail=ee%40nowcoder.com&resumeUrl=https%3A%2F%2Fwww.nowcoder.com&testResultUrl=https%3A%2F%2Fwww.nowcoder.com&job=java&jobType=1&projectId=2071&rounds=2021-08-26+11%3A00%3A00%7Ccoder%7C10000000000%7Cer%40nowcoder.com%7C0%7C0&rounds=2021-08-26+11%3A30%3A00%7C-%7C-%7C-%7C0%7C1&finishRedirectUrls=https%3A%2F%2Fwww.nowcoder.com&finishRedirectUrls=https%3A%2F%2Fwww.nowcoder.com'
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "id" : 36724903,
        "interviewProjectId" : 2071,
        "intervieweeName" : "nowcoder",
        "intervieweeEmail" : "[email protected]",
        "intervieweePhone" : "10000000000",
        "jobType" : 1,
        "job" : "java",
        "deliverId" : "TD6879239819",
        "resumeUrl" : "https://www.nowcoder.com",
        "testResultUrl" : "https://www.nowcoder.com",
        "round" : 0,
        "rounds" : [ {
          "id" : 289423,
          "interviewId" : 36724903,
          "round" : 1,
          "bookTime" : 1629946800000,
          "multi" : 0,
          "offline" : 0,
          "interviewerName" : "coder",
          "interviewerPhone" : "10000000000",
          "interviewerEmail" : "[email protected]",
          "userList" : null,
          "score" : 0,
          "evaluation" : null,
          "elapsedTime" : 0,
          "status" : 0,
        }, {
          "id" : 289424,
          "interviewId" : 36724903,
          "round" : 2,
          "bookTime" : 1629948600000,
          "multi" : 1,
          "offline" : 0,
          "interviewerName" : null,
          "interviewerPhone" : null,
          "interviewerEmail" : null,
          "userList" : [{
            "id" : 186503,
            "interviewId" : 36724903,
            "roundId" : 289424,
            "round" : 2,
            "name" : "coder1",
            "email" : "[email protected]",
            "phone" : "10000000001",
            "host" : 1,
            "evaluation" : null,
            "elapsedTime" : 0,
            "status" : 0
          }, {
            "id" : 186504,
            "interviewId" : 36724903,
            "roundId" : 289424,
            "round" : 2,
            "name" : "coder2",
            "email" : "[email protected]",
            "phone" : "10000000002",
            "host" : 0,
            "evaluation" : null,
            "elapsedTime" : 0,
            "status" : 0
          "score" : 0,
          "evaluation" : null,
          "elapsedTime" : 0,
          "status" : 0
        "interviewReportUrl" : "https://dapi.nowcoder.com/v1/interview-report/712E34F318A80DEC5D2B1AAD67C4DCC3/report_pdf?code=NstxvwnE",
        "startTime" : null,
        "expireTime" : 1635072309584,
        "elapsedTime" : 0,
        "validTime" : 0,
        "interviewerUrl" : "https://examd.nowcoder.com/interview/36724903/interviewer?code=NstxvwnE",
        "interviewerOfflineUrl" : "https://examd.nowcoder.com/interview/36724903/offline?code=NstxvwnE",
        "intervieweeUrl" : "https://examd.nowcoder.com/interview/36724903/interviewee?code=WNDyBdkI",
        "status" : 0
    

    POST /interviews

    projectId 所属项目id intervieweeName String 面试者的姓名 intervieweeEmail String 面试者email intervieweePhone String 面试者手机号码 copilotFlag boolean 非必填(默认false) 是否开启智能面试 String 面试职位名称 jobType 职位类型1-技术,2-非技术 jobDesc String 非必填(长度上限4K) deliverId String resumeUrl String 简历URL resumeText String 非必填(长度上限12K) 简历文本内容 testResultUrl String 笔试结果URL rounds array 轮次信息字符串 multiUsers array 多对一面试必填(一对一面试非必填) 多对一面试字段,面试官信息字符串 callback String 非必填(想使用对应回调功能必填) 面试轮次评价回调, 录音完成回调 callback2 String 非必填(想使用对应回调功能必填) 面试状态回调 finishRedirectUrl String 非必填(想使用对应回调功能必填) 面试结束后跳转链接,一般用于三方对接填写面试评价使用, 搭配评分接口使用 finishRedirectUrls array 非必填(想使用对应回调功能必填) 面试结束后跳转链接,一般用于三方对接填写面试评价使用, 搭配评分接口使用,这里适用于每一轮都需要不同的跳转链接,大小必须和rounds参数一样 public void testUpdateInterview(){ long interviewId = 36724903; String path = String.format("/interviews/%d/interview", interviewId); MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>(); mvMap.put("intervieweeName", "javaCoder"); mvMap.put("intervieweeEmail", "[email protected]"); mvMap.put("intervieweePhone", "10000000000"); mvMap.put("job", "java"); mvMap.put("jobType", 1); mvMap.put("deliverId", "TD6879239819"); mvMap.put("resumeUrl", "https://www.nowcoder.com"); mvMap.put("testResultUrl", "https://www.nowcoder.com"); mvMap.put("rounds", "289423|2021-08-26 11:00:00|coder|10000000000|[email protected]|0|0"); mvMap.put("rounds", "289424|2021-08-26 11:30:00|-|-|-|0|1"); mvMap.put("multiUsers", "186503|2|0|coder1|[email protected]|10000000001|1"); mvMap.put("multiUsers", "186504|2|0|coder2|[email protected]|10000000002|0"); mvMap.put("callback", null); mvMap.put("callback2", null); mvMap.put("finishRedirectUrl", "https://www.nowcoder.com"); mvMap.put("finishRedirectUrls", "https://www.nowcoder.com"); mvMap.put("finishRedirectUrls", "https://www.nowcoder.com"); String responseString = NowcoderApiRequestUtils.request(path, mvMap, "PUT"); System.out.println(responseString);
    curl --location --request PUT 'https://dapi.nowcoder.com/v1/interviews/36724903/interview' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  \
     --data-raw 'api_key=huaxinjiayou%40126.com&intervieweeName=javaCoder&multiUsers=186503%7C2%7C0%7Ccoder1%7Cer1%40nowcoder.com%7C10000000001%7C1&multiUsers=186504%7C2%7C0%7Ccoder2%7Cer2%40nowcoder.com%7C10000000002%7C0&finishRedirectUrl=https%3A%2F%2Fwww.nowcoder.com&intervieweePhone=10000000000&deliverId=TD6879239819&intervieweeEmail=java%40nowcoder.com&resumeUrl=https%3A%2F%2Fwww.nowcoder.com&testResultUrl=https%3A%2F%2Fwww.nowcoder.com&job=java&jobType=1&rounds=289423%7C2021-08-26+11%3A00%3A00%7Ccoder%7C10000000000%7Cer%40nowcoder.com%7C0%7C0&rounds=289424%7C2021-08-26+11%3A30%3A00%7C-%7C-%7C-%7C0%7C1&finishRedirectUrls=https%3A%2F%2Fwww.nowcoder.com&finishRedirectUrls=https%3A%2F%2Fwww.nowcoder.com'
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "id" : 36724903,
        "interviewProjectId" : 2071,
        "intervieweeName" : "javaCoder",
        "intervieweeEmail" : "[email protected]",
        "intervieweePhone" : "10000000000",
        "jobType" : 1,
        "job" : "java",
        "deliverId" : "TD6879239819",
        "resumeUrl" : "https://www.nowcoder.com",
        "testResultUrl" : "https://www.nowcoder.com",
        "round" : 0,
        "rounds" : [ {
          "id" : 289423,
          "interviewId" : 36724903,
          "round" : 1,
          "bookTime" : 1629946800000,
          "multi" : 0,
          "offline" : 0,
          "interviewerName" : "coder",
          "interviewerPhone" : "10000000000",
          "interviewerEmail" : "[email protected]",
          "userList" : null,
          "score" : 0,
          "evaluation" : null,
          "elapsedTime" : 0,
          "status" : 0
        }, {
          "id" : 289424,
          "interviewId" : 36724903,
          "round" : 2,
          "bookTime" : 1629948600000,
          "multi" : 1,
          "offline" : 0,
          "interviewerName" : null,
          "interviewerPhone" : null,
          "interviewerEmail" : null,
          "userList" : [{
            "id" : 186503,
            "interviewId" : 36724903,
            "roundId" : 289424,
            "round" : 2,
            "name" : "coder1",
            "email" : "[email protected]",
            "phone" : "10000000001",
            "host" : 1,
            "evaluation" : null,
            "elapsedTime" : 0,
            "status" : 0
          }, {
            "id" : 186504,
            "interviewId" : 36724903,
            "roundId" : 289424,
            "round" : 2,
            "name" : "coder2",
            "email" : "[email protected]",
            "phone" : "10000000002",
            "host" : 0,
            "evaluation" : null,
            "elapsedTime" : 0,
            "status" : 0
          "score" : 0,
          "evaluation" : null,
          "elapsedTime" : 0,
          "status" : 0
        "interviewReportUrl" : "https://dapi.nowcoder.com/v1/interview-report/712E34F318A80DEC5D2B1AAD67C4DCC3/report_pdf?code=NstxvwnE",
        "startTime" : null,
        "expireTime" : 1635072309584,
        "elapsedTime" : 0,
        "validTime" : 0,
        "interviewerUrl" : "https://examd.nowcoder.com/interview/36724903/interviewer?code=NstxvwnE",
        "interviewerOfflineUrl" : "https://examd.nowcoder.com/interview/36724903/offline?code=NstxvwnE",
        "intervieweeUrl" : "https://examd.nowcoder.com/interview/36724903/interviewee?code=WNDyBdkI",
        "status" : 0
    

    PUT /interviews/{id:[0-9]+}/interview

    intervieweeName String 面试者的姓名 intervieweeEmail String 面试者email intervieweePhone String 面试者手机号码 String 面试职位名称 jobType 职位类型1-技术,2-非技术 deliverId String resumeUrl String 简历URL testResultUrl String 笔试结果URL rounds array 轮次信息字符串 multiUsers array 多对一面试必填 多对一面试字段,面试官信息字符串 finishRedirectUrl String 面试结束后跳转链接,用于三方对接填写面试评价使用

    轮次参数字段

    bookTime String/long 预约时间, yyyy-MM-dd HH:mm:ss 或者 毫秒级时间戳 interviewerName String 一对一面试字段,面试官姓名 interviewerPhone String 一对一面试字段,面试官号码 interviewerEmail String 一对一面试字段,面试官邮箱 offline 0线上、1线下 multi 0一对一面试、1多对一面试

    使用时按照列表顺序以'|'为分割符拼接起来,为空的参数可以用'-'替代

    面试官参数字段

    面试官id round 第几轮的面试官 String 面试官姓名 email String 面试官邮箱 phone String 面试官号码 0非主持人、1主持人

    使用时按照列表顺序以'|'为分割符拼接起来,为空的参数可以用'-'替代

    id大于0则代表是修改操作,等于0则代表是新增操作。 轮次采用增量更新,只能进行修改和新增。但在多对一面试的面试官信息更新中采用全量更新,即没有传递的面试官会被删除。

    面试实体关键字段

    取消一轮面试

    public class Main {
      @Test
      public void testCancelInterviewRound(){
        long interviewId = 36724903;
        long roundId = 289424;
        String path = String.format("/interviews/%d/%d", interviewId, roundId);
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        mvMap.put("cancelCurrentRoundOnly", true);
        mvMap.put("needSendCancelNotice", false);
        mvMap.put("cancelReason", "test");
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "DELETE");
        System.out.println(responseString);
    
    curl --location --request DELETE 'https://dapi.nowcoder.com/v1/interviews/36724903/289424' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  \
     --data-raw 'api_key=huaxinjiayou%40126.com&needSendCancelNotice=false&cancelCurrentRoundOnly=true&cancelReason=test'
      "code" : 0,
      "msg" : "OK",
      "data" : null
    

    DELETE /interviews/{id:[0-9]+}/{roundId:[0-9]+}

    roundId 面试轮次id cancelCurrentRoundOnly boolean 必填(默认为false) 是否只取消当前轮次而保留后面轮次 needSendCancelNotice boolean 必填(默认为false) 是否发送取消通知 cancelReason String public void testGetById() { long interviewId = 36724903; String path = String.format("/interviews/%d", interviewId); MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>(); String responseString = NowcoderApiRequestUtils.request(path, mvMap, "GET"); System.out.println(responseString);
    curl --location --request GET 'https://dapi.nowcoder.com/v1/interviews/[email protected]' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "id" : 36724903,
        "interviewProjectId" : 2071,
        "intervieweeName" : "javaCoder",
        "intervieweeEmail" : "[email protected]",
        "intervieweePhone" : "10000000000",
        "jobType" : 1,
        "job" : "java",
        "deliverId" : "TD6879239819",
        "resumeUrl" : "https://www.nowcoder.com",
        "testResultUrl" : "https://www.nowcoder.com",
        "round" : 0,
        "rounds" : [{
          "id" : 289423,
          "interviewId" : 36724903,
          "round" : 1,
          "bookTime" : 1629946800000,
          "multi" : 0,
          "offline" : 0,
          "interviewerName" : "coder",
          "interviewerPhone" : "10000000000",
          "interviewerEmail" : "[email protected]",
          "userList" : null,
          "score" : 0,
          "evaluation" : null,
          "elapsedTime" : 0,
          "status" : 0,
        "interviewReportUrl" : "https://dapi.nowcoder.com/v1/interview-report/712E34F318A80DEC5D2B1AAD67C4DCC3/report_pdf?code=NstxvwnE",
        "startTime" : null,
        "expireTime" : 1635072309584,
        "elapsedTime" : 0,
        "validTime" : 0,
        "interviewerUrl" : "https://examd.nowcoder.com/interview/36724903/interviewer?code=NstxvwnE",
        "interviewerOfflineUrl" : "https://examd.nowcoder.com/interview/36724903/offline?code=NstxvwnE",
        "intervieweeUrl" : "https://examd.nowcoder.com/interview/36724903/interviewee?code=WNDyBdkI",
        "status" : 0
    

    GET /interviews/{id:[0-9]+}

    面试房间id

    面试实体关键字段

    获取面试房间状态

    public class Main {
      @Test
      public void testGetRoomStatus() {
        String path = "/interviews/room-status";
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        mvMap.put("roomId", 36724903);
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "GET");
        System.out.println(responseString);
    
    curl --location --request GET 'https://dapi.nowcoder.com/v1/interviews/[email protected]&roomId=36724903' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "roomId" : 36724903,
        "timeRunOut" : false,
        "roomStatus" : 0,
        "remainMinitus" : 180
    

    GET /interviews/room-status

    roomId roomId timeRunOut boolean 面试是否已经超时 roomStatus 房间状态:0-正常,1-取消,2-过期 remainMinitus 剩余可用时长,单位:分钟. validTime - elapsedTime

    批量获取面试官、候选人在线状态

    public class Main {
      @Test
      public void testGetPersonStatus() {
        String path = "/interviews/rooms-status";
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        mvMap.put("roomIdList", 36724903);
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "GET");
        System.out.println(responseString);
    
    curl --location --request GET 'https://dapi.nowcoder.com/v1/interviews/[email protected]&roomIdList=36724903' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  
      "code" : 0,
      "msg" : "OK",
      "data" : [ {
        "roomId" : 36724903,
        "intervieweeStatus" : 0,
        "interviewerStatus" : 0
    

    GET /interviews/rooms-status

    roomIdList array 面试id数组 roomId intervieweeStatus 候选人在线状态:0-离线, 1-在线 interviewerStatus 面试官在线状态:0-离线, 1-在线

    当面试的超时导致面试无法使用时,可以通过该接口延长可用时长,每次调用会延长一次初始时长,但会收取一次费用。

    public class Main {
      @Test
      public void testExtendInterview() {
        long interviewId = 36724903;
        String path = String.format("/interviews/%d/extend", interviewId);
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "PUT");
        System.out.println(responseString);
    
    curl --location --request PUT 'https://dapi.nowcoder.com/v1/interviews/36724903/extend' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  \
     --data-raw 'api_key=huaxinjiayou%40126.com'
      "code" : 0,
      "msg" : "OK",
      "data" : null
    

    PUT /interviews/{id:[0-9]+}/extend

    如果面试未结束时调用该接口会缓存结果,等结束面试时进行覆盖
    public class Main {
      @Test
      public void testInterviewEvaluation() {
        String path = "/user/interviews-other/round/evaluations";
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        mvMap.put("version", 1);
        mvMap.put("roundId", 289423);
        mvMap.put("interviewId", 36724903);
        mvMap.put("roundIdx", 1);
        mvMap.put("isPass", true);
        String responseString = NowcoderApiRequestUtils.request(path, mvMap, "PUT");
        System.out.println(responseString);
    
    curl --location --request PUT 'https://dapi.nowcoder.com/v1/user/interviews-other/round/evaluations' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  \
     --data-raw 'api_key=huaxinjiayou%40126.com&interviewId=36724903&roundIdx=1&isPass=true&version=1&roundId=289423'
      "code" : 0,
      "msg" : "OK",
      "data" : { }
    

    PUT /user/interviews-other/round/evaluations

    version 固定值 1 roundId interviewId roundIdx isPass

    空json串

    ai智能报告点赞点踩

    /v1/partners/interview/report/prefer

    请求方法和类型

    post, application/json

  • url后面添加api_key的query参数,如:/v1/partners/interview/report/prefer?api_key=xxx
  • 请求添加一个Authorization头,值为:Bearer token,这个token可以从hr系统获得
  • 请求和回报参数见右边

    请求参数:
      "roundId": "面试轮次id,long",
      "sceneType": "场景类型,int:1.报告点赞,2.报告点踩,3.评价维度点赞,4.评价维度点踩,5.答题分析点赞,6.答题分析点踩",
      "sceneId": "场景id,string:sceneType=1,2时不传;sceneType=3,4时,代表dimensionId;sceneType=5,6时,代表analysisId"
    
    回包参数:
        "code": "int:0表示成功,非0表示失败",
        "msg": "string:code非0时表示报错原因"
    

    面试-新版面试管理

    旧版接口使用form格式参数,组装复杂,扩展困难。因此对创建面试、修改面试两个接口进行了重写,采用json格式参数。请尽量切换到新版接口,旧版接口将不再增加新特性。
  • Content-Type统一使用application/json
  • 如果参数的非空校验、格式校验等基础校验失败,Response Status会返回400。其他情况Response Status统一使用200,返回值中code为0代表成功,其他代表失败
  • 面试实体字段

    interviewId expireTime 秒级时间戳,过期失效时间 validDuration interviewReportUrl String 面试报告地址 interviewRounds array @Test public void testNewCreateInterview(){ String path = "/partners/interview/create_interview"; PartnerInterviewDTO partnerInterviewDTO = new PartnerInterviewDTO(); PartnerInterviewDTO.OrgInfo orgInfo = new PartnerInterviewDTO.OrgInfo(); orgInfo.projectId = 2071L; orgInfo.deptId = null; PartnerInterviewDTO.Interviewee interviewee = new PartnerInterviewDTO.Interviewee(); interviewee.name = "coder"; interviewee.email = "[email protected]"; interviewee.phone = "10000000000"; interviewee.resumeUrl = "https://www.nowcoder.com"; PartnerInterviewDTO.JobInfo jobInfo = new PartnerInterviewDTO.JobInfo(); jobInfo.jobName = "java"; jobInfo.deliverId = "TD12983710892"; List<PartnerInterviewDTO.InterviewRound> interviewRounds = new ArrayList<>(); PartnerInterviewDTO.InterviewRound interviewRound = new PartnerInterviewDTO.InterviewRound(); interviewRound.offline = 0; interviewRound.interviewType = 1; interviewRound.panelFlag = 0; interviewRound.bookTime = 1629982394L; interviewRounds.add(interviewRound); List<PartnerInterviewDTO.Interviewer> interviewers = new ArrayList<>(); PartnerInterviewDTO.Interviewer interviewer = new PartnerInterviewDTO.Interviewer(); interviewer.name = "er"; interviewer.email = "[email protected]"; interviewer.phone = "10000000000"; interviewer.host = 1; interviewers.add(interviewer); interviewRound.interviewers = interviewers; partnerInterviewDTO.interviewee = interviewee; partnerInterviewDTO.jobInfo = jobInfo; partnerInterviewDTO.interviewRounds = interviewRounds; partnerInterviewDTO.orgInfo = orgInfo; String response = NowcoderApiRequestUtils.jsonRequest(path, partnerInterviewDTO, "POST"); System.out.println(response);
    curl --location --request POST 'https://dapi.nowcoder.com/v1/partners/interview/[email protected]' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c' \
     --header 'Content-Type: application/json'  \
     --data-raw '{"interviewRounds":[{"bookTime":1629982394,"interviewType":1,"interviewers":[{"email":"[email protected]","host":1,"name":"er","phone":"10000000000"}],"offline":0,"panelFlag":0}],"interviewee":{"email":"[email protected]","name":"coder","phone":"10000000000","resumeUrl":"https://www.nowcoder.com"},"jobInfo":{"deliverId":"TD12983710892","jobName":"java"},"orgInfo":{"projectId":2071}}'
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "interviewId" : 37000637,
        "expireTime" : 1635080281,
        "validDuration" : 10800,
        "interviewReportUrl" : "https://dapi.nowcoder.com/v1/interview-report/844C0F4B8BD9E8685D2B1AAD67C4DCC3/report_pdf?code=QQGnFJCH",
        "interviewRounds" : [ {
          "roundId" : 289426,
          "roundIdx" : 1,
          "offline" : 0,
          "panelFlag" : 0,
          "bookTime" : 1629982394,
          "interviewer" : [ {
            "interviewerId" : null,
            "name" : "er",
            "email" : "[email protected]",
            "phone" : "10000000000",
            "host" : 1,
            "interviewUrl" : "https://examd.nowcoder.com/interview/37000637/interviewer?code=QQGnFJCH"
          } ],
          "interviewee" : {
            "name" : "coder",
            "email" : "[email protected]",
            "phone" : "10000000000",
            "interviewUrl" : "https://examd.nowcoder.com/interview/37000637/interviewee?code=SSEb3BCn"
          "interviewType" : 1
    

    POST /partners/interview/create_interview

    Content-type

    application/json

    orgInfo interviewee 候选人信息 jobInfo interviewRounds array callback projectId 面试所属项目id deptId 面试所属部门id copilotFlag boolean 非必填(默认false) 是否开启智能面试 resumeText String 非必填(长度上限12K) 简历文本内容

    候选人信息

    String 候选人姓名 email String 候选人邮箱 phone String 候选人电话 resumeUrl String 候选人简历地址 deliverId String 投递编号, 同一个面试项目下唯一 jobName String 应聘岗位名称 offline 线上视频 或 线下面试, 0表示线上视频,1表示线下面试 interviewType 技术面试 或 非技术面试, 1表示技术面试,2表示非技术面试 panelFlag 1对1面试 或 多对1面试, 0表示1对1面试,1表示多对1面试 bookTime 面试预约时间, 秒级时间戳 redirectUrl 非必填, 一对一面试用到 重定向链接 interviewers array 面试官信息

    面试官信息

    String 面试官姓名 email String 面试官邮箱 phone String 面试官电话 是否主持人 0代表非主持人, 1代表主持人 feedbackCb String 非必填, 多对一面试用到 自定义面评表地址, https格式。 redirectUrl 非必填, 多对一面试用到 重定向链接

    重定向链接

    finishRedirectUrl String 结束时的重定向链接 @Test public void testNewUpdateInterview(){ String path = "/partners/interview/part-update-interview"; PartnerInterviewDTO partnerInterviewDTO = new PartnerInterviewDTO(); PartnerInterviewDTO.OrgInfo orgInfo = new PartnerInterviewDTO.OrgInfo(); orgInfo.deptId = null; PartnerInterviewDTO.Interviewee interviewee = new PartnerInterviewDTO.Interviewee(); interviewee.name = "coder5"; partnerInterviewDTO.interviewId = 37000637L; partnerInterviewDTO.interviewee = interviewee; String response = NowcoderApiRequestUtils.jsonRequest(path, partnerInterviewDTO, "POST"); System.out.println(response);
    curl --location --request POST 'https://dapi.nowcoder.com/v1/partners/interview/[email protected]' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c' \
     --header 'Content-Type: application/json'  \
     --data-raw '{"interviewId":37000637,"interviewee":{"name":"coder5"}}'
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "interviewId" : 37000637,
        "expireTime" : 1856005081,
        "validDuration" : 10800,
        "interviewReportUrl" : "https://dapi.nowcoder.com/v1/interview-report/844C0F4B8BD9E8685D2B1AAD67C4DCC3/report_pdf?code=QQGnFJCH",
        "interviewRounds" : [ {
          "roundId" : 289426,
          "roundIdx" : 1,
          "offline" : 0,
          "panelFlag" : 0,
          "bookTime" : 1629982394,
          "interviewer" : [ {
            "interviewerId" : null,
            "name" : "er",
            "email" : "[email protected]",
            "phone" : "10000000000",
            "host" : 1,
            "interviewUrl" : "https://examd.nowcoder.com/interview/37000637/interviewer?code=QQGnFJCH"
          } ],
          "interviewee" : {
            "name" : "coder5",
            "email" : "[email protected]",
            "phone" : "10000000000",
            "interviewUrl" : "https://examd.nowcoder.com/interview/37000637/interviewee?code=SSEb3BCn"
          "interviewType" : 1
        }, {
          "roundId" : 289428,
          "roundIdx" : 2,
          "offline" : 0,
          "panelFlag" : 0,
          "bookTime" : 1656322593,
          "interviewer" : [ {
            "interviewerId" : null,
            "name" : null,
            "email" : null,
            "phone" : "14700000000",
            "host" : 1,
            "interviewUrl" : "https://examd.nowcoder.com/interview/37000637/interviewer?code=QQGnFJCH"
          } ],
          "interviewee" : {
            "name" : "coder5",
            "email" : "[email protected]",
            "phone" : "10000000000",
            "interviewUrl" : "https://examd.nowcoder.com/interview/37000637/interviewee?code=SSEb3BCn"
          "interviewType" : 1
    

    POST /partners/interview/part-update-interview

    Content-type

    application/json

    interviewId orgInfo interviewee 候选人信息 jobInfo interviewRounds array deptId 面试所属部门id

    候选人信息

    String 候选人姓名 email String 候选人邮箱 phone String 候选人电话 resumeUrl String 候选人简历地址 deliverId String 投递编号,同一个面试项目下唯一 jobName String 应聘岗位名称 roundId 需要修改轮次时填写 需要修改的轮次id,新增时不填 offline 线上视频 或 线下面试, 0表示线上视频,1表示线下面试, 必填 interviewType 技术面试 或 非技术面试, 1表示技术面试,2表示非技术面试, 必填 panelFlag 1对1面试 或 多对1面试, 0表示1对1面试,1表示多对1面试, 必填 bookTime 面试预约时间, 秒级时间戳, 必填 redirectUrl 非必填, 一对一面试用到 重定向链接 interviewers array 面试官信息

    面试官信息

    interviewerId 多对一面试修改面试官填写 面试官id,多对一面试修改时传入 String 面试官姓名, 必填 email String 面试官邮箱 phone String 面试官电话 是否主持人 0代表非主持人, 1代表主持人 必填 delete boolean 非必填,默认false 是否删除面试官,多对一时用到 feedbackCb String 非必填,多对一面试用到 自定义面评表地址, https格式 redirectUrl 非必填,多对一面试用到 重定向链接

    重定向链接

    finishRedirectUrl String 结束时的重定向链接 @Test public void testNewUpdateInterview(){ String path = "/partners/interview/update_interview"; PartnerInterviewDTO partnerInterviewDTO = new PartnerInterviewDTO(); PartnerInterviewDTO.OrgInfo orgInfo = new PartnerInterviewDTO.OrgInfo(); orgInfo.deptId = null; PartnerInterviewDTO.Interviewee interviewee = new PartnerInterviewDTO.Interviewee(); interviewee.name = "coder2"; interviewee.email = "[email protected]"; interviewee.phone = "10000000000"; interviewee.resumeUrl = "https://www.nowcoder.com"; PartnerInterviewDTO.JobInfo jobInfo = new PartnerInterviewDTO.JobInfo(); jobInfo.jobName = "java"; jobInfo.deliverId = "TD12983710892"; List<PartnerInterviewDTO.InterviewRound> interviewRounds = new ArrayList<>(); PartnerInterviewDTO.InterviewRound interviewRound = new PartnerInterviewDTO.InterviewRound(); interviewRound.roundId = 289426L; interviewRound.offline = 0; interviewRound.interviewType = 1; interviewRound.panelFlag = 0; interviewRound.bookTime = 1629982394L; interviewRounds.add(interviewRound); List<PartnerInterviewDTO.Interviewer> interviewers = new ArrayList<>(); PartnerInterviewDTO.Interviewer interviewer = new PartnerInterviewDTO.Interviewer(); interviewer.name = "er"; interviewer.email = "[email protected]"; interviewer.phone = "10000000000"; interviewer.host = 1; interviewers.add(interviewer); interviewRound.interviewers = interviewers; partnerInterviewDTO.interviewId = 37000637L; partnerInterviewDTO.interviewee = interviewee; partnerInterviewDTO.jobInfo = jobInfo; partnerInterviewDTO.interviewRounds = interviewRounds; partnerInterviewDTO.orgInfo = orgInfo; String response = NowcoderApiRequestUtils.jsonRequest(path, partnerInterviewDTO, "POST"); System.out.println(response);
    curl --location --request POST 'https://dapi.nowcoder.com/v1/partners/interview/[email protected]' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c' \
     --header 'Content-Type: application/json'  \
     --data-raw '{"interviewId":37000637,"interviewRounds":[{"bookTime":1629982394,"interviewType":1,"interviewers":[{"email":"[email protected]","host":1,"name":"er","phone":"10000000000"}],"offline":0,"panelFlag":0,"roundId":289426}],"interviewee":{"email":"[email protected]","name":"coder2","phone":"10000000000","resumeUrl":"https://www.nowcoder.com"},"jobInfo":{"deliverId":"TD12983710892","jobName":"java"},"orgInfo":{}}'
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "interviewId" : 37000637,
        "expireTime" : 1635080281,
        "validDuration" : 10800,
        "interviewReportUrl" : "https://dapi.nowcoder.com/v1/interview-report/844C0F4B8BD9E8685D2B1AAD67C4DCC3/report_pdf?code=QQGnFJCH",
        "interviewRounds" : [ {
          "roundId" : 289426,
          "roundIdx" : 1,
          "offline" : 0,
          "panelFlag" : 0,
          "bookTime" : 1629982394,
          "interviewer" : [ {
            "interviewerId" : null,
            "name" : "er",
            "email" : "[email protected]",
            "phone" : "10000000000",
            "host" : 1,
            "interviewUrl" : "https://examd.nowcoder.com/interview/37000637/interviewer?code=QQGnFJCH"
          } ],
          "interviewee" : {
            "name" : "coder2",
            "email" : "[email protected]",
            "phone" : "10000000000",
            "interviewUrl" : "https://examd.nowcoder.com/interview/37000637/interviewee?code=SSEb3BCn"
          "interviewType" : 1
    

    POST /partners/interview/update_interview

    Content-type

    application/json

    interviewId orgInfo interviewee 候选人信息 jobInfo interviewRounds array deptId 面试所属部门id

    候选人信息

    String 候选人姓名 email String 候选人邮箱 phone String 候选人电话 resumeUrl String 候选人简历地址 deliverId String 投递编号,同一个面试项目下唯一 jobName String 应聘岗位名称 roundId 修改轮次信息时必填,增加轮次时不填 需要修改的轮次id offline 线上视频 或 线下面试, 0表示线上视频,1表示线下面试, 必填 interviewType 技术面试 或 非技术面试, 1表示技术面试,2表示非技术面试, 必填 panelFlag 1对1面试 或 多对1面试, 0表示1对1面试,1表示多对1面试, 必填 bookTime 面试预约时间, 秒级时间戳, 必填 redirectUrl 非必填, 一对一面试用到 重定向链接 interviewers array 面试官信息

    面试官信息

    interviewerId 多对一面试修改必填 面试官id,多对一面试修改时传入 String 面试官姓名, 必填 email String 面试官邮箱 phone String 面试官电话 是否主持人 0代表非主持人, 1代表主持人 必填 feedbackCb String 非必填, 多对一面试用到 自定义面评表地址, https格式 redirectUrl 非必填,多对一面试用到 重定向链接

    重定向链接

    finishRedirectUrl String 结束时的重定向链接 String interviewId = "31310396"; String path = String.format("/partners/interview/get-record-url/%s", interviewId); MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>(); String responseString = CommonUtils.request(path, mvMap, "GET"); System.out.println(responseString);
    curl --location --request GET 'https://dapi.nowcoder.com/v1/partners/interview/get-record-url?interviewId=31310396&[email protected]' \
    --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c1273a4e338f650a5c'
        "code": 0,
        "msg": "OK",
        "data": {
            "interviewId": 31310396,
            "roundRecordDatas": [
                    "roundId": 430801,
                    "round": 1,
                    "roundStatus": 3,
                    "recordUrl": null,
                    "recordExpireTime": null
                    "roundId": 430802,
                    "round": 2,
                    "roundStatus": 3,
                    "recordUrl": null,
                    "recordExpireTime": null
    

    GET /partners/interview/get-record-url

    Content-type

    application/json

    interviewId 面试房间id interviewId 面试房间id roundRecordDatas array 录音数组,关键信息见录音信息实体

    录音实体字段

    rounId round roundStatus 轮次状态,0未开始、1进行中、3结束、4删除、5暂停、7面试淘汰被自动取消 recordUrl String 录音下载链接 (不存在返回null) recordExpireTime 下载链接过期时间(注意是秒级时间戳,不存在返回null)

    面试-回调服务

    面试轮次评价回调

  • 每一轮面试结束时进行回调
  • 轮次评分修改分数后进行回调
  • interviewId roundId 面试轮次id round score 0未评分、1-2淘汰、3-5通过 evaluation String reportUrl Stirng deliverId String interviewerName String 面试官姓名,以最后评价填写的为准 roundStatus 固定值3,代表面试结束 roundStartTime 该轮面试开始时间 roundEndTime 该轮面试结束时间 roundElapsedTime String 该轮使用时长,单位毫秒 autoCancelRounds array 自动取消轮次信息,如果开启了淘汰取消后续轮次这里会携带被自动取消的轮次信息 interviewerEvaluations array 多对一面试非主持人评价信息

    自动取消轮次信息

    round 第几轮, 被折叠的轮次也会记录

    多对一面试非主持人评价信息

    interviewerName String 面试官姓名 interviewerEvaluations String 面试官评价

    面试状态回调

  • 面试开始使用
  • 面试删除、过期
  • 候选人或面试官上线
  • interviewId status 状态, 1取消、2过期、3开始使用、4面试官或候选人上线

    收到该回调表示面试轮次ai智能报告已经生成,相关答题分析和面试记录可以通过下面两个接口来拉取

    请求方法和类型

    post, application/x-www-form-urlencoded

    string string 加密后的内容 string 回调的数据,是个json字符串,结构见右边
    回调参数中data对应的json结构:
        "interviewId": "面试id,long",
        "roundId": "面试轮次id,long",
        "round": "表示第几轮,int",
    
    回包参数:
      "code": "int:200表示成功,非200表示失败",
      "message": "string:表示失败时的报错原因"
    

    答题分析获取接口

    接口地址

    /v1/partners/interview/report/answer-analysis

    请求方法和类型

  • url后面添加api_key的query参数,如:/v1/partners/interview/answer-analysis?api_key=xxx
  • 请求添加一个Authorization头,值为:"Bearer token",其中的token可以从hr系统获得
  • 请求query参数

    roundId 必填,轮次id

    回包参数见右边

    {
      "code": "int:0表示成功,非0表示失败",
      "msg": "string:code非0时表示报错原因",
      "data": {
        "assessmentDimensionList": [
            "name": "维度名称,string:学习能力",
            "assessment": "维度评价内容,string:候选人应对挫折和卡点,容易陷入自我怀疑与否定...",
            "dimensionId": "维度评价id,string:249483jsfjoe"
        "answerAnalysisList": [
            "chatList": [
                "roleType": "角色类型,int: 0.面试官,1.候选人",
                "roleName": "角色名称,string:面试官",
                "content": "对话的内容,string:请你做个自我介绍"
            "skills": [
              "考察技能名称,string:Java"
            "advice": "答题分析建议,string:候选人回答基本正确,但掌握比较基础,建议深入考核",
            "analysisId": "答题分析建议id,string:2898598543jfosdjfoi"
    

    面试记录获取接口

    接口地址

    /v1/partners/interview/report/chat-list

    请求方法和类型

  • url后面添加api_key的query参数,如:/v1/partners/interview/chat-list?api_key=xxx
  • 请求添加一个Authorization头,值为:"Bearer token",其中的token可以从hr系统获得
  • 请求query参数

    roundId 必填,轮次id curPage 选填,请求页,默认值1 pageSize 选填,每页大小,默认值20

    回包参数见右边

    {
      "code": "int:0表示成功,非0表示失败",
      "msg": "string:code非0时表示报错原因",
      "data": {
        "totalCount": "int: 总条数",
        "totalPage": "int:总页数",
        "curPage": "int:当前页",
        "pageSize": "int:当前每页大小",
        "originChatList": [
            "roleType": "角色类型,int: 0.面试官,1.候选人",
            "roleName": "角色名称,string:比如面试官",
            "content": "对话的内容,string:请你做个自我介绍",
            "actionTime": "对话时间戳,long:毫秒时间戳"
    

    系统接口

    获取用户当前账户信息

    public class Main {
        @Test
        public void testGetUserTestInfo() {
            String path = "/users/self";
            MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
            String responseString = CommonUtils.request(path, mvMap, "GET");
            System.out.println(responseString);
    
    curl --location --request GET 'http://localhost:8888/v1/users/[email protected]' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "id" : 30,
        "email" : "[email protected]",
        "phone" : null,
        "companyName" : "华鑫加油",
        "headUrl" : null,
        "accountConfig" : null,
        "validBeginTime" : null,
        "validEndTime" : null,
        "encryptPassword" : null
    

    查询当前用户的账户信息

    GET /users/self

    email 账号登录邮箱 phone companyName 公司名称,不同于账号名称 headUrl validBeginTime 有效期开始时间 validEndTime 有效期开始时间 encryptPassword

    获取hr系统每种服务的最大可用额度

    public class Main {
        @Test
        public void testGetPaperTestsInfo() {
            String path = "/user/checkBalance/count";
            MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
            mvMap.put("serviceTypes", 1);
            mvMap.put("serviceTypes", 3);
            mvMap.put("serviceTypes", 7);
            mvMap.put("serviceTypes", 8);
            mvMap.put("serviceTypes", 9);
            String responseString = CommonUtils.request(path, mvMap, "GET");
            System.out.println(responseString);
    
    curl --location --request GET 'http://localhost:8888/v1/user/checkBalance/[email protected]&serviceTypes=1&serviceTypes=3&serviceTypes=7&serviceTypes=8&serviceTypes=9' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "hostId" : 30,
        "adminHrId" : 30,
        "techContestCount" : 2176,
        "untechContestCount" : 4352,
        "techInterviewCount" : 932,
        "untechInterviewCount" : 1865,
        "extendPackageCount" : 3264
    

    查询每个服务类型最大可以使用的额度(包括额度和账户余额),包括技术笔试、非技术笔试、技术面试、非技术面试、面试扩展包。

    最大可以使用额度计算方式:
    技术笔试额度=合同剩余技术笔试额度+取整(账户余额/30)
    非技术笔试额度=合同剩余非技术笔试额度+取整(账户余额/15)
    技术面试额度=合同剩余技术面试额度+取整(账户余额/70)
    非技术面试额度=合同剩余非技术笔试额度+取整(账户余额/35)
    面试扩展包=合同剩余扩展包额度+取整(账户余额/20)

    注:子账号查询,返回总账号/子账号的额度限制,取最小值

    支持指定类型查询最大额度,例如 只查询笔试的;也可以支持不指定类型,查询全部最大额度;

    GET /user/checkBalance/count

    serviceTypes 需要查询的服务类型,可以传多个值。1:技术面试,3:技术笔试,7:非技术面试,8:非技术笔试,9:面试扩展包 hostId 当前用户ID adminHrId 用户主账号ID,如果当前用户为主账号与用户ID相同 techContestCount 技术笔试可用额度,-1为无限制 untechContestCount 非技术笔试可用额度,-1为无限制 techInterviewCount 技术面试可用额度,-1为无限制 untechInterviewCount 非技术面试可用额度,-1为无限制 extendPackageCount 面试扩展包可用额度,-1为无限制,子账户此项默认返回父账可用最大额度

    获取异步任务进度

    public class Main {
      @Test
      public void testGetJobProcess() {
        String processId = "LntWBG4tD1YRyJ4z7woVSqaU5sxulx36";
        String path = String.format("/job-progress/%s", processId);
        MultiValuedMap<String, Object> mvMap = new ArrayListValuedHashMap<>();
        String responseString = CommonUtils.request(path, mvMap, "GET");
        System.out.println(responseString);
    
    curl --location --request GET 'http://localhost:8888/v1/job-progress/[email protected]' \
     --header 'Authorization: Bearer 9e906c093a59bc80e312d2821d5daff81aa9c7a8512638f4c73a4e338f650a5c'  
      "code" : 0,
      "msg" : "OK",
      "data" : {
        "ownerId" : 0,
        "content" : "",
        "end" : true,
        "error" : false,
        "type" : 2,
        "progress" : 100,
        "jobId" : "LntWBG4tD1YRyJ4z7woVSqaU5sxulx36",
        "jobInfo" : null
    

    获取异步任务进度

    GET /job-progress/{id}

    异步任务id ownerId jobId 异步任务id progress 异步任务进度,0~100之间的整数 异步任务是否结束。true结束、false未结束 error 异步任务是否发生异常。true发生了异常、false未发生异常 content 异步任务返回信息 content字段的类型,1-下载链接 2-文字结果 3-JSON字符串