Carte Vitale - FRANCE OCR

Automatically extract data from french “Carte Vitale”.

Mindee’s Carte Vitale - FRANCE API uses deep learning to automatically, accurately, and instantaneously parse your card details. In under a second, the API extracts a set of data from your PDFs or photos of Carte Vitale, including:

  • Given Name(s)
  • Surname
  • Social Security Number
  • Issuance Date

The Carte Vitale - France API supports the new and old format for all people in France. The cards of other nationalities and states are not supported with this model.

Set up the API

📘

Before making any API calls, you need to have created your API key.

  1. You'll need a french carte vitale. You can use one of the sample documents provided below.

  1. Access your API by clicking on the Carte Vitale - FRANCE card in the Document Catalog

  1. From the left navigation, go to documentation > API Reference, you'll find sample code in popular languages and command line.
from mindee import Client, AsyncPredictResponse, product

# Init a new client
mindee_client = Client(api_key="my-api-key-here")

# Add the corresponding endpoint (document). Set the account_name to "mindee" if you are using OTS.
my_endpoint = mindee_client.create_endpoint(
    account_name="mindee",
    endpoint_name="french_healthcard",
    version="1"
)

# Load a file from disk
input_doc = mindee_client.source_from_path("/path/to/the/file.ext")

# Parse the file.
# The endpoint must be specified since it cannot be determined from the class.
result: AsyncPredictResponse = mindee_client.enqueue_and_parse(
    product.GeneratedV1,
    input_doc,
    endpoint=my_endpoint
)

# Print a brief summary of the parsed data
print(result.document)

# # Iterate over all the fields in the document
# for field_name, field_values in result.document.inference.prediction.fields.items():
#     print(field_name, "=", field_values)
const mindee = require("mindee");
// for TS or modules:
// import * as mindee from "mindee";

// Init a new client
const mindeeClient = new mindee.Client({ apiKey: "my-api-key-here" });

// Load a file from disk
const inputSource = mindeeClient.docFromPath("/path/to/the/file.ext");

// Create a custom endpoint for your product
const customEndpoint = mindeeClient.createEndpoint(
  "french_healthcard",
  "mindee",
  "1" // Defaults to "1"
);

// Parse the file asynchronously.
const asyncApiResponse = mindeeClient.enqueueAndParse(
  mindee.product.GeneratedV1,
  inputSource,
  { endpoint: customEndpoint }
);

// Handle the response Promise
asyncApiResponse.then((resp) => {
  // print a string summary
  console.log(resp.document.toString());
});
using Mindee;
using Mindee.Input;
using Mindee.Http;
using Mindee.Product.Generated;

string apiKey = "my-api-key-here";
string filePath = "/path/to/the/file.ext";

// Construct a new client
MindeeClient mindeeClient = new MindeeClient(apiKey);

// Load an input source as a path string
// Other input types can be used, as mentioned in the docs
var inputSource = new LocalInputSource(filePath);

// Set the endpoint configuration
CustomEndpoint endpoint = new CustomEndpoint(
    endpointName: "french_healthcard",
    accountName: "mindee",
    version: "1"
);

// Call the product asynchronously with auto-polling
var response = await mindeeClient
    .EnqueueAndParseAsync<GeneratedV1>(inputSource, endpoint);

// Print a summary of all the predictions
System.Console.WriteLine(response.Document.ToString());

// Print only the document-level predictions
// System.Console.WriteLine(response.Document.Inference.Prediction.ToString());
require 'mindee'

# Init a new client
mindee_client = Mindee::Client.new(api_key: 'my-api-key-here')

# Load a file from disk
input_source = mindee_client.source_from_path('/path/to/the/file.ext')

# Initialize a custom endpoint for this product
custom_endpoint = mindee_client.create_endpoint(
  account_name: 'mindee',
  endpoint_name: 'french_healthcard',
  version: '1'
)

# Parse the file
result = mindee_client.enqueue_and_parse(
  input_source,
  Mindee::Product::Generated::GeneratedV1,
  endpoint: custom_endpoint
)

# Print a full summary of the parsed data in RST format
puts result.document
import com.mindee.MindeeClient;
import com.mindee.input.LocalInputSource;
import com.mindee.parsing.common.AsyncPredictResponse;
import com.mindee.product.generated.GeneratedV1;
import com.mindee.http.Endpoint;
import java.io.File;
import java.io.IOException;

public class SimpleMindeeClient {

  public static void main(String[] args) throws IOException, InterruptedException {
    String apiKey = "my-api-key-here";
    String filePath = "/path/to/the/file.ext";

    // Init a new client
    MindeeClient mindeeClient = new MindeeClient(apiKey);

    // Load a file from disk
    LocalInputSource inputSource = new LocalInputSource(new File(filePath));

    // Configure the endpoint
    Endpoint endpoint = new Endpoint(
        "french_healthcard",
        "mindee",
        "1"
    );

    // Parse the file asynchronously
    AsyncPredictResponse<GeneratedV1> response = mindeeClient.enqueueAndParse(
        GeneratedV1.class,
        endpoint,
        inputSource
    );

    // Print a summary of the response
    System.out.println(response.toString());

    // Print a summary of the predictions
//  System.out.println(response.getDocumentObj().toString());

    // Print the document-level predictions
//    System.out.println(response.getDocumentObj().getInference().getPrediction().toString());

    // Print the page-level predictions
//    response.getDocumentObj().getInference().getPages().forEach(
//        page -> System.out.println(page.toString())
//    );
  }

}
API_KEY='my-api-key-here'
ACCOUNT='mindee'
ENDPOINT='french_healthcard'
VERSION='1'
FILE_PATH='/path/to/your/file.png'

# Maximum amount of retries to get the result of a queue
MAX_RETRIES=10

# Delay between requests
DELAY=6

# Enqueue the document for async parsing
QUEUE_RESULT=$(curl -sS --request POST \
  -H "Authorization: Token $API_KEY" \
  -H "Content-Type: multipart/form-data" \
  -F "document=@$FILE_PATH" \
  "https://api.mindee.net/v1/products/$ACCOUNT/$ENDPOINT/v$VERSION/predict_async")

# Status code sent back from the server
STATUS_CODE=$(echo "$QUEUE_RESULT" | grep -oP "[\"|']status_code[\"|']:[\s][\"|']*[a-zA-Z0-9-]*" | rev | cut --complement -f2- -d" " | rev)

# Check that the document was properly queued
if [ -z "$STATUS_CODE" ] || [ "$STATUS_CODE" -gt 399 ] || [ "$STATUS_CODE" -lt 200 ]
then
  if [ -z "$STATUS_CODE" ]
  then
    echo "Request couldn't be processed."
    exit 1
  fi
  echo "Error $STATUS_CODE was returned by API during enqueuing. "

  # Print the additional details, if there are any:
  ERROR=$(echo "$QUEUE_RESULT" | grep -oP "[\"|']error[\"|']:[\s]\{[^\}]*" | rev | cut --complement -f2- -d"{" | rev)
  if [ -z "$ERROR" ]
  then
    exit 1
  fi

  # Details on the potential error:
  ERROR_CODE=$(echo "$ERROR" | grep -oP "[\"|']code[\"|']:[\s]\"[^(\"|\')]*" | rev | cut --complement -f2- -d"\"" | rev)
  MESSAGE=$(echo "$QUEUE_RESULT" | grep -oP "[\"|']message[\"|']:[\s]\"[^(\"|\')]*" | rev | cut --complement -f2- -d"\"" | rev)
  DETAILS=$(echo "$QUEUE_RESULT" | grep -oP "[\"|']details[\"|']:[\s]\"[^(\"|\')]*" | rev | cut --complement -f2- -d"\"" | rev)
  echo "This was the given explanation:"
  echo "-------------------------"
  echo "Error Code: $ERROR_CODE"
  echo "Message: $MESSAGE"
  echo "Details: $DETAILS"
  echo "-------------------------"
  exit 1
else

  echo "File sent, starting to retrieve from server..."

  # Get the document's queue ID
  QUEUE_ID=$(echo "$QUEUE_RESULT" | grep -oP "[\"|']id[\"|']:[\s][\"|'][a-zA-Z0-9-]*" | rev | cut --complement -f2- -d"\"" | rev)

  # Amount of attempts to retrieve the parsed document were made
  TIMES_TRIED=1

  # Try to fetch the file until we get it, or until we hit the maximum amount of retries
  while [ "$TIMES_TRIED" -lt "$MAX_RETRIES" ]
  do
    # Wait for a bit at each step
    sleep $DELAY

    # Note: we use -L here because the location of the file might be behind a redirection
    PARSED_RESULT=$(curl -sS -L \
      -H "Authorization: Token $API_KEY" \
      "https://api.mindee.net/v1/products/$ACCOUNT/$ENDPOINT/v$VERSION/documents/queue/$QUEUE_ID")

    # Isolating the job (queue) & the status to monitor the document
    JOB=$(echo "$PARSED_RESULT" | grep -ioP "[\"|']job[\"|']:[\s]\{[^\}]*" | rev | cut --complement -f2- -d"{" | rev)
    QUEUE_STATUS=$(echo "$JOB" | grep -ioP "[\"|']status[\"|']:[\s][\"|'][a-zA-Z0-9-]*" | rev | cut --complement -f2- -d"\"" | rev)
    if [ "$QUEUE_STATUS" = "completed" ]
    then
      # Print the result
      echo "$PARSED_RESULT"

      # Optional: isolate the document:
      # DOCUMENT=$(echo "$PARSED_RESULT" | grep -ioP "[\"|']document[\"|']:[\s].*([\"|']job[\"|'])" | rev | cut -f2- -d"," | rev)
      # echo "{$DOCUMENT}"

      # Remark: on compatible shells, fields can also be extracted through the use of tools like jq:
      # DOCUMENT=$(echo "$PARSED_RESULT" | jq '.["document"]')
      exit 0
    fi
    TIMES_TRIED=$((TIMES_TRIED+1))
  done
fi

echo "Operation aborted, document not retrieved after $TIMES_TRIED tries"
exit 1
<?php

use Mindee\Client;
use Mindee\Product\Generated\GeneratedV1;
use Mindee\Input\PredictMethodOptions;

// Init a new client
$mindeeClient = new Client("my-api-key-here");

// Load a file from disk
$inputSource = $mindeeClient->sourceFromPath("/path/to/the/file.ext");

// Create a custom endpoint
$customEndpoint = $mindeeClient->createEndpoint(
    "french_healthcard",
    "mindee",
    "1"
);

// Add the custom endpoint to the prediction options.
$predictOptions = new PredictMethodOptions();
$predictOptions->setEndpoint($customEndpoint);

// Parse the file
$apiResponse = $mindeeClient->enqueueAndParse(GeneratedV1::class, $inputSource, $predictOptions);

echo strval($apiResponse->document);

  • Replace my-api-key-here with your new API key, or use the "select an API key" feature and it will be filled automatically.
  • Copy and paste the sample code of your desired choice in your application, code environment or terminal.
  • Replace /path/to/my/file with the path to your document.

❗️

Always remember to replace your API key!

  1. Run your code. You will receive a JSON response with the document details.

API Response

Here is the full JSON response you get when you call the API:

{
  "api_request": {
    "error": {},
    "resources": [
      "document",
      "job"
    ],
    "status": "success",
    "status_code": 200,
    "url": "https://api.mindee.net/v1/products/mindee/french_healthcard/v1/documents/1ec5aff1-ef20-4744-bf7e-fe03464192f3"
  },
  "document": {
    "id": "1ec5aff1-ef20-4744-bf7e-fe03464192f3",
    "inference": {
      "extras": {},
      "finished_at": "2024-10-28T10:07:18.627000",
      "is_rotation_applied": true,
      "pages": [
        {
          "extras": {},
          "id": 0,
          "orientation": {
            "value": 0
          },
          "prediction": {}
        }
      ],
      "prediction": { ... },
      "processing_time": 2.084,
      "product": {
        "features": [
          "given_names",
          "surname",
          "social_security",
          "issuance_date"
        ],
        "name": "mindee/french_healthcard",
        "type": "standard",
        "version": "1.0"
      },
      "started_at": "2024-10-28T10:07:16.391000"
    },
    "n_pages": 1,
    "name": "CarteVitale2 (1).jpg"
  },
  "job": {
    "available_at": "2024-10-28T10:07:18.636000",
    "error": {},
    "id": "097af697-b4dc-4a4a-9374-9e64fb009b01",
    "issued_at": "2024-10-28T10:07:16.391000",
    "status": "completed"
  }
}

You can find the prediction within the prediction key found in  document > inference > prediction for document-level predictions: it contains the different fields extracted at the document level, meaning that for multi-pages PDFs, we reconstruct a single object using all the pages.

Each predicted field may contain one or several values:

  • polygon highlighting the information location
  • page_id where the information was found (document level only)
{
  "api_request": { ... },
  "document": {
       ...
      "prediction": {
        "given_names": [
          {
            "page_id": 0,
            "polygon": [
              [
                0.282,
                0.671
              ],
              [
                0.441,
                0.671
              ],
              [
                0.441,
                0.709
              ],
              [
                0.282,
                0.709
              ]
            ],
            "value": "NATHALIE"
          }
        ],
        "issuance_date": {
          "page_id": 0,
          "polygon": [
            [
              0.443,
              0.438
            ],
            [
              0.605,
              0.438
            ],
            [
              0.605,
              0.475
            ],
            [
              0.443,
              0.475
            ]
          ],
          "value": "2007-01-01"
        },
        "social_security": {
          "page_id": 0,
          "polygon": [
            [
              0.282,
              0.838
            ],
            [
              0.616,
              0.838
            ],
            [
              0.616,
              0.873
            ],
            [
              0.282,
              0.873
            ]
          ],
          "value": "2 69 05 49 588 157 80"
        },
        "surname": {
          "page_id": 0,
          "polygon": [
            [
              0.284,
              0.727
            ],
            [
              0.422,
              0.727
            ],
            [
              0.422,
              0.766
            ],
            [
              0.284,
              0.766
            ]
          ],
          "value": "DURAND"
        }
      },
...

  }
}

Extracted data

Depending on the field type specified, additional attributes can be extracted from the Carte Vitale -FRANCE card object. Using the above example the following are the basic fields that can be extracted.

Given Name(s)

  • given_names: The given names of the card holder.
{
  "given_names": [
    {
      "page_id": 0,
      "polygon": [[0.282,0.671],[0.441,0.671],[0.441,0.709],[0.282,0.709]],
      "value": "NATHALIE"
    }
  ]
}

Surname

  • surname: The surname of the card holder.
{
  "surname": {
    "page_id": 0,
    "polygon": [[0.284,0.727],[0.422,0.727],[0.422,0.766],[0.284,0.766]],
    "value": "DURAND"
  }
}

Social Security Number

  • social_security: The social security number of the card holder.
{
  "social_security": {
    "page_id": 0,
    "polygon": [[0.282,0.838],[0.616,0.838],[0.616,0.873],[0.282,0.873]],
    "value": "2 69 05 49 588 157 80"
  }
}

Issuance Date

  • issuance_date: The date when the carte vitale was issued.
{
  "issuance_date": {
    "page_id": 0,
    "polygon": [[0.443,0.438],[0.605,0.438],[0.605,
        0.475
      ],
      [
        0.443,
        0.475
      ]
    ],
    "value": "2007-01-01"
  }
}

Questions?

Slack Logo Icon  Join our Slack