Performs a biometric enrollment (or training) of a single class with one or more images containing the face of the person to enroll. With this method a new biometric face template is created and stored. It can be used to create a completely new biometric template, to update an existing template or even to upgrade an existing template to a newer encoder version.
The created template is persisted to a storage, addressed by its Biometric Class ID (BCID). Beside of a compact version of the biometric template (used for face matching purposes), an enhanced version of the template is stored. The enhanced version contains at least all calculated face features (standard template) and optionally also the thumbnails of the enrolled faces (full version), which are needed for upgrades to newer encoder versions. The enhanced template versions are always encrypted, the compact version is encrypted if required by the configuration of the client (slows down search requests).
                The Enroll API is defined as a unary RPC:
            
rpc Enroll (FaceEnrollmentRequest) returns (FaceEnrollmentResponse);
message FaceEnrollmentRequest {
    int64 classId = 1;
    repeated ImageData images = 2;
}
message FaceEnrollmentResponse {
    JobStatus status = 1;
    repeated JobError errors = 2;
    repeated ImageProperties image_properties = 3;
    EnrollmentAction performed_action = 4;
    int32 enrolled_images = 5;
    FaceTemplateStatus template_status = 6;
    enum EnrollmentAction {
        NONE = 0;
        NEW_TEMPLATE_CREATED = 1;
        TEMPLATE_UPDATED = 2;
        TEMPLATE_UPGRADED = 3;
        ENROLLMENT_FAILED = -1;
    }
}
            
                The FaceEnrollmentRequest message has the fields as follows:
            
classIdThe unique class ID of the enrolled person. The class ID is a 64-bit positive number, managed by the client.
This ID, together with a storage name and a partition ID will make up the Biometric Class ID (BCID), which is used to address the created biometric template.
images
                The maximum API request size is 50 MB.
            
This API requires a valid JWT in the Authorization request header and accepts an optional reference number.
| Authorization | Required Bearer authentication. Please refer to BWS API Authentication for a description of how to provide a valid JWT here. | 
| Reference-Number | Optional, client specific reference number, which will be added to the BWS bookkeeping as well as to the response header. You typically use this reference to link the resulting BWS bookkeeping entries with your logs. | 
                On success the API returns a FaceEnrollmentResponse message:
            
statuserrors may have occurred, even if the job was completed successfully.
                errorsperformed_action field will typically be set to ENROLLMENT_FAILED.
                image_propertiesperformed_actionThe actual action performed. This is a value out of the EnrollmentAction enumeration:
NONENEW_TEMPLATE_CREATEDTEMPLATE_UPDATEDTEMPLATE_UPGRADEDENROLLMENT_FAILEDerrors field) and no action was performed.
                        enrolled_imagestemplate_status
                Please note, that even if a biometric face template has been enrolled successfully,
                not all images and found faces may have considered, as no face or multiple faces may have been
                found on an image, or feature extraction failed. 
                Refer to the image_properties (especially the quality_assessments field) to find out more.
            
                In case that the performed_action field is set to ENROLLMENT_FAILED, at least one of the following errors is reported in the errors field:
            
Beside of the success return status code OK (0), this call might also return one of the following gRPC error status codes to indicate an error:
All successful BWS gRPC calls return a response header and a response trailer containing additional information about the request:
| Response Header | |
| jobid | The Job-ID (a GUID) that has been assigned to this BWS call. | 
| bws-version | The version of the BWS gRPC service. | 
| reference-number | An optional reference number as provided in the request header. | 
| date | The timestamp when the request has been received at the server. | 
| ... | Other headers that might have been added by the server (NGINX, Kestrel, ...) that was handling the request. | 
| Response Trailer | |
| response-time-ms | The timespan in milliseconds the request spent at the BWS service. | 
| ... | Other trailers, like exception trailers, which are added by the gRPC framework in case an RPC exception occurred. | 
Here is a short example of how to call into the Enroll gRPC API using a classId and a list of images.
Please refer to BWS API Authentication for a description of the methods related to authentication.
                            The tooling package Grpc.Tools can be used to generate C# assets, such as classes and methods, from the facerecognition.proto and bwsmessages.proto files.
                            Refer to overview for gRPC on .NET to learn more about how to call into a gRPC service with a .NET client.
                        
try
{
    using GrpcChannel channel = CreateAuthenticatedChannel(new Uri(options.Host), GenerateToken(options.ClientId, options.Key));
    var client = new BioIDWebService.BioIDWebServiceClient(channel);
    var request = new  new FaceEnrollmentRequest { ClassId = options.ClassId };
    foreach (string file in options.Files)
    {
        request.LiveImages.Add(new ImageData { Image = ByteString.CopyFrom(File.ReadAllBytes(file)) });
    }
    using var call = client.EnrollAsync(request);
    FaceEnrollmentResponse response = await call.ResponseAsync.ConfigureAwait(false);
    // ...
    Console.WriteLine($"Performed action   : {response.PerformedAction}");
    Console.WriteLine($"Template Class-ID  : {response.TemplateStatus.ClassId}");
    Console.WriteLine($"Template available : {response.TemplateStatus.Available}");
    Console.WriteLine($"Template enrolled  : {response.TemplateStatus.Enrolled}");
}
catch (RpcException ex)
{
    Console.Error.WriteLine($"gRPC error from calling service: {ex.Status.StatusCode} - '{ex.Status.Detail}'");
}
                    
                            Assuming that the Protoc compiler and the Protoc gRPC Java plugin are already installed on your system.
                            To generate Protobuf Java classes and gRPC client stubs from the facerecognition.proto and bwsmessages.proto files.
                            Use the Protobuf compiler (protoc) with the following command in the cmd or terminal:
                            
                            protoc -I=PATH_TO_PROTOS_DIR --java_out=OUTPUT_DIR --grpc-java_out=OUTPUT_DIR --plugin=protoc-gen-grpc-java=PATH_TO_PLUGIN facerecognition.proto bwsmessages.proto
                            
                            For a detailed step by step guide on protobuf usage with Java, please refer to Java detailed guide
                        
import java.util.concurrent.CompletableFuture;
import com.bioid.services.BioIDWebServiceGrpc;
import com.bioid.services.BioIDWebServiceGrpc.BioIDWebServiceStub;
import com.bioid.services.Bws.ImageData;
import com.google.protobuf.ByteString;
import io.grpc.ManagedChannel;
import io.grpc.StatusRuntimeException;
import io.grpc.stub.StreamObserver;
import com.bioid.services.Facerecognition.FaceEnrollmentRequest;
import com.bioid.services.Facerecognition.FaceEnrollmentResponse;
public void faceEnrollAsync(byte[] image1, byte[] image2, long classId){
    ManagedChannel grpcChannel = null;
    try {
        String jwtToken = generateToken(options.clientId, option.secretKey, options.expireMinutes);
        grpcChannel = createAuthenticatedChannel(option.host, jwtToken);
     
        var bwsClient = FaceRecognitionGrpc.newStub(grpcChannel);
        var enrollRequest = FaceEnrollmentRequest.newBuilder()
                 // The unique class ID of the enrolled person
                 // You should set your ClassID
                .setClassId(classId)
                .addImages(ImageData.newBuilder().setImage(ByteString.copyFrom(image1)).build())
                .addImages(ImageData.newBuilder().setImage(ByteString.copyFrom(image2)).build())
                .build();
                
        CompletableFuture <FaceEnrollmentResponse> enrollResult = new CompletableFuture <>();
        bwsClient.enroll(enrollRequest, new StreamObserver <FaceEnrollmentResponse>() {
            @Override
            public void onNext(FaceEnrollmentResponse value) {
                enrollResult.complete(value);
            }
            @Override
            public void onError(Throwable t) {
                enrollResult.completeExceptionally(t);
            }
            @Override
            public void onCompleted() {
            }
        });
        var enrollResponse = enrollResult.get();
        System.out.println("Performed action   : " + enrollResponse.getPerformedAction().toString());
        System.out.println("Template Class-ID  : " + enrollResponse.getTemplateStatus().getClassId());
        System.out.println("Template available : " + enrollResponse.getTemplateStatus().getAvailable());
    } catch (Exception ex) {
        System.err.printf("Error processing images: " + ex.getMessage());
    } finally {
        if(grpcChannel != null) {
            grpcChannel.shutdown();
        }
    }
}
                    
                            You can generate the necessary Python client code from the facerecognition.proto and bwsmessages.proto files
                            using the protocol buffer compiler protoc (install: python -m pip install grpcio-tools)
                            from the  Phython gRPC tools.
                            These files can be taken from .proto service definitions.
                            Use the following commands to generate the necessary Python files:
                            python -m grpc_tools.protoc --proto_path=. --python_out=. --grpc_python_out=. facerecognition.proto bwsmessages.proto
                        
import grpc
import facerecognition_pb2
import facerecognition_pb2_grpc
token = generate_token(args.clientid, args.key, arg.expireMinutes)
with create_authenticated_channel(args.host, token) as channel:
    stub = facerecognition_pb2_grpc.FaceRecognitionStub(channel)
    request = facerecognition_pb2.FaceEnrollmentRequest()
    for img_file in args.images:
        with open(img_file, 'rb') as f:
            request.images.add(image=f.read())
    try:
        # The unique class ID of the enrolled person
        # You should set your ClassID
        request.classId = args.class_id
        response = stub.Enroll(request)
        print(response)
    except grpc.RpcError as rpc_error:
        print("Received error: ", rpc_error)