[[:guide_de_migration_shootid_vers_id360|FranΓ§ais]] | [[:en:guide_de_migration_shootid_vers_id360|English]]
----
====== Migration Guide : ShootID to ID360 ======
===== π STEP 1 β AUTHENTICATION =====
==== πΉ ShootID ====
* **Method**: Authentication via **HTTP Basic Auth**
* **Header used in all requests**:
Authorization: Basic base64(applicationToken:applicationSecret)
* **Validity duration**: Permanent (or until manually revoked)
----
==== πΈ ID360 ====
* **Method**: POST /api/1.0.0/user/login/
* **URL**:
* Preprod: https://preprod.id360docaposte.com/api/1.0.0/user/login/
* Prod: https://id360docaposte.com/api/1.0.0/user/login/
* **JSON Payload**:
{
"username": "string",
"password": "string"
}
* **Response**:
{
"token": "0123456789abcdef01234567"
}
* **Header to include in each subsequent API call**:
Authorization: Token 0123456789abcdef01234567
----
==== π Token lifespan & renewal (ID360) ====
* **Validity**: 15 minutes
* **Auto-renewal**: with each API call using this token
* **Exception**: `/user/login/` does **not** refresh the token duration
* **Error on expiration**: HTTP 401 Unauthorized
**π To extend token validity (without generating a new one):**
GET /api/1.0.0/user/whoami
Authorization: Token 0123456789abcdef01234567
* **Recommended frequency**: every 13 minutes
* **Expected response**: HTTP 200 if token is still valid
----
==== β
Authentication Summary Table ====
^ Function ^ ShootID ^ ID360 ^
| Method | HTTP Basic Auth | Login with username/password β Token |
| Endpoint | N/A (included in each request) | POST /user/login/ |
| Authentication format | Authorization: Basic ... | Authorization: Token |
| Token validity | Long term (no expiration) | Expires after 15 min of inactivity |
| Token refresh | N/A | GET /user/whoami recommended every 13 minutes |
----
===== π§© STEP 2 β INITIALIZE A TRANSACTION / START A PROCESS =====
==== πΉ ShootID ====
* **Method**: `GET`
* **URL**: `https://www.contralia.fr/shootid/api/v2/init`
* **Response**:
{
"transactionId": "2c95841e45404f7e0145405da33f0009",
"qrCode": "https://www.contralia.fr/shootid/api/v2/picture?pictureId=2c95841e45404f7e0145405"
}
----
==== πΈ ID360 ====
* **Method**: `POST`
* **URL PROD**: `https://id360docaposte.com/api/1.0.0/process/{UUID}/enrollment`
* **URL PREPROD**: `https://preprod.id360docaposte.com/api/1.0.0/process/{UUID}/enrollment`
* **Request (cURL)**:
curl -X POST \
"https://id360docaposte.com/api/1.0.0/process/{UUID}/enrollment" \
-H "accept: application/json" \
-H "Authorization: Token 0123456789abcdef01234567" \
-d '{
"callback_url": "https://www.example.com/callback_url",
"browser_callback_url": "https://www.example.com/browser_callback_url",
"client_reference": "any_string",
"callback_headers": {
"header_name_1": "header_value_1",
"header_name_2": "header_value_2"
},
"last_name": "Users last name",
"first_name": "Users first name",
"email": "Users email",
"address_line_1": "Users address line 1",
"address_line_2": "Users address line 2",
"address_line_3": "Users address line 3",
"zip_code": "Users zip code",
"city": "Users city",
"country": "Users country",
"phone_number": "Users phone number"
}'
=== π§Ύ Parameter details ===
* In the URL, the UUID corresponds to the process ID
* `callback_url` (**required**): backend URL that will receive the **full result** of the ID360 process via POST
* `browser_callback_url` (**required**): URL to which the user will be **redirected via the browser**
* `callback_headers`: custom headers for the backend callback (auth, ID, etc.)
* `client_reference`: internal reference ID in your IS (for linking with your data)
* User fields (`last_name`, `email`, etc.): **informational only**, not used for checks
* `email`: required only for PVID processes
----
==== β
Summary table β Process initialization ====
^ Function ^ **ShootID** ^ **ID360** ^
| Request type | `GET /api/v2/init` | `POST /api/1.0.0/process/{id}/enrollment` |
| Response | `transactionId`, `qrCode` | `id` (dossier), `url`, `api_key`, `status` |
| Process configuration | Implicit | Explicit via `{id}` of the process configured in the admin console |
| Technical callbacks | N/A | `callback_url` (backend) + `browser_callback_url` (frontend) |
| Custom tracking | No | `client_reference` available |
| Authentication | Basic Auth in each request | Token-based (`Authorization: Token ...`) |
===== π STEP 2B β SELECTING THE ROUTE (ID360) =====
=== π§ Why this step is required ===
In some ID360 processes, **multiple identification methods** can be proposed to the user, such as:
* Identification via **La Poste Digital Identity**
* Identification via a **Custom Online Process from Docaposte**
π **In this process**, **only the Custom Online Process is used**,
which means that the ID360 platform **requires the integrator to explicitly select this route** among the available options.
π This selection ensures that the user will follow **the correct identification scenario**,
according to the business configuration set in the admin console.
=== π― Goal ===
Associate a **specific route** with a **user dossier (enrollment)** using its `api_key`,
in order to **lock the identification method** to follow.
----
=== 1. π₯ Retrieve the list of available routes ===
* **Endpoint**: `GET /api/1.0.0/enrollment/flow/enrollment_info/`
**Preprod:**
curl -X 'GET' \
'https://preprod.id360docaposte.com/api/1.0.0/enrollment/flow/enrollment_info/' \
-H 'accept: application/json' \
-H 'x-api-key: {DOSSIER_API_KEY}'
**Prod:**
curl -X 'GET' \
'https://id360docaposte.com/api/1.0.0/enrollment/flow/enrollment_info/' \
-H 'accept: application/json' \
-H 'x-api-key: {DOSSIER_API_KEY}'
**Sample response**:
{
"routes": [
{
"id": 275128
}
]
}
> The field `routes[0].id` contains the ID of the route to use.
----
=== 2. β
Select the route ===
* **Endpoint**: `POST /api/1.0.0/enrollment/flow/route/{route_id}/select/`
**Preprod:**
curl -X 'POST' \
'https://preprod.id360docaposte.com/api/1.0.0/enrollment/flow/route/{route_id}/select/' \
-H 'accept: application/json' \
-H 'x-api-key: {DOSSIER_API_KEY}' \
-H 'Content-Type: text/plain'
**Prod:**
curl -X 'POST' \
'https://id360docaposte.com/api/1.0.0/enrollment/flow/route/{route_id}/select/' \
-H 'accept: application/json' \
-H 'x-api-key: {DOSSIER_API_KEY}' \
-H 'Content-Type: text/plain'
**Expected response**:
HTTP 204 No Content
----
=== π Key notes ===
* The **dossierβs API key (`api_key`)** is obtained through the `POST /process/{id}/enrollment` call
* Route selection is **mandatory** for multi-channel processes
* Once selected, the route is **permanently associated** with the dossier
* This action must be performed **before sending any documents or user data**
----
===== πͺͺ STEP 3 β ADD AN IDENTITY DOCUMENT =====
==== πΉ ShootID ====
* **Method**: `POST`
* **URL**: `https://www.contralia.fr/shootid/api/v2/add`
* **Type**: `multipart/form-data`
* **Main fields**:
* `transactionId` (string) β transaction ID (**required**)
* `file` (file) β image to upload (**required**)
* `type` (enum string) β document type: `Enum: IDENTITY` (**required**)
* `documentId` (integer) β document ID (**required**)
* **Advanced options**: page, geolocation, scanProvider, OCR/MRZ, image processing
* **Sample response**:
{
"transactionId": "2c95841e45404f7e0145405da33f0009",
"qrCode": "https://www.contralia.fr/shootid/api/v2/picture?pictureId=2c95841e45404f7e0145405da35c000a",
"documents": [{
"status": "READY_TO_BE_SCANNED",
"declaredType": "IDENTITY",
"documentId": 0
}]
}
----
==== πΈ ID360 ====
* **Method**: `POST`
* **URL**:
https://preprod.id360docaposte.com/api/1.0.0/enrollment/flow/document/id_document_image/?total_pages=2&uploaded_page=0
* **Type**: `application/octet-stream`
* **Authentication**: `x-api-key` (retrieved during enrollment)
* **Payload**: raw binary (not form-data)
=== β€ cURL (preprod) ===
curl -X 'POST' \
'https://preprod.id360docaposte.com/api/1.0.0/enrollment/flow/document/id_document_image/?total_pages=2&uploaded_page=0' \
-H 'accept: */*' \
-H 'x-api-key: {DOSSIER_API_KEY}' \
-H 'Content-Type: application/octet-stream' \
--data-binary '@CNIRecto.PNG'
=== β€ URL Parameters ===
^ Parameter ^ Description ^
| `total_pages` | Total number of pages to upload for the document (e.g., `2` for front/back of ID) |
| `uploaded_page` | Index of the uploaded page (starts at `0`) |
----
==== β
Comparison Table β Upload Document ====
^ Element ^ **ShootID** ^ **ID360** ^
| Endpoint | `POST /api/v2/add` | `POST /enrollment/flow/document/id_document_image/` |
| Authentication | `Authorization: Basic` + `transactionId` | `x-api-key` |
| Upload format | `multipart/form-data` | `application/octet-stream` (pure binary) |
| Document parameters | `type`, `documentId`, `page`, etc. | `total_pages`, `uploaded_page` in the URL |
| File field | `file` | raw content via `--data-binary` |
| Response | JSON with `status`, `documentId`, etc. | No detailed response (silent success) or `204` expected |
| Optional processing | Yes (binarization, OCR, cropping, etc.) | Managed upstream in the process configuration |
| Supported document types | Enum: `IDENTITY`, `RIB`, `CHECK`, `CAR_REGISTRATION`, etc. | Fixed: `id_document_image` (for this specific step) |
----
===== π STEP 4 β ADD OTHER DOCUMENTS (RIB, Proof of Address, etc.) =====
In some ID360 processes, especially those requiring an **address block** or **bank identity**,
it is necessary to upload additional documents **in addition to the ID document**:
* π **Proof of address** (utility bill, rent receipt, etc.)
* π¦ **Bank details (RIB)**
----
==== πΉ ShootID ====
* **Endpoint**: `POST /shootid/api/v2/add`
* **Required fields**:
* `transactionId`
* `file`
* `type` β `ADDRESS_BLOCK` (proof of address) or `RIB`
* **Optional fields**: `documentId`, `page`, `scanProvider`, `processCropping`, etc.
* **Response**: confirmation + status `READY_TO_BE_SCANNED`
----
==== πΈ ID360 ====
=== π¦ 1. Upload RIB ===
* **Endpoint**:
POST /api/1.0.0/enrollment/flow/document/bank_details_image/
* **Sample cURL**:
curl -X 'POST' \
'https://preprod.id360docaposte.com/api/1.0.0/enrollment/flow/document/bank_details_image/' \
-H 'accept: */*' \
-H 'x-api-key: {DOSSIER_API_KEY}' \
-H 'Content-Type: application/octet-stream' \
--data-binary '@rib.jpg'
β This document feeds the **bank block** (IBAN, account holder).
----
=== π 2. Upload Proof of Address ===
* **Endpoint**:
POST /api/1.0.0/enrollment/flow/document/proof_of_address_image/
* **Sample cURL**:
curl -X 'POST' \
'https://preprod.id360docaposte.com/api/1.0.0/enrollment/flow/document/proof_of_address_image/' \
-H 'accept: */*' \
-H 'x-api-key: {DOSSIER_API_KEY}' \
-H 'Content-Type: application/octet-stream' \
--data-binary '@electricity_bill.pdf'
β This document feeds the **address block**, which can be cross-verified with the ID document.
----
==== β
Summary of ID360 Document Upload Endpoints ====
^ Document Type ^ ID360 Endpoint URL Path ^
| Identity document | `/enrollment/flow/document/id_document_image/` |
| Proof of address | `/enrollment/flow/document/proof_of_address_image/` |
| Bank details (RIB) | `/enrollment/flow/document/bank_details_image/` |
----
===== π₯ STEP 5 β RETRIEVING THE FINAL RESULT =====
==== πΉ ShootID ====
* **Method**: `GET`
* **URL**: `https://www.contralia.fr/shootid/api/v2/result`
* **Parameters**:
* `transactionId` (**required**)
* `documentId` (optional)
* `scanTimeout` (optional)
=== Sample response ===
* Scan status: `OK`, `KO`, `PROVIDER_COULD_NOT_PROCESS_ERROR`
* Validation results: MRZ, integrity checks...
* OCR data: name, first name, birth date, gender, number...
* Generated images: `imagePhoto`, `image1Cut`, `image2Cut`, `imageSignature`
* Fraud criteria: `fraudScanTimesCriteria`, `fraudPeriodCriteria`
----
==== πΈ ID360 ====
=== Report Retrieval Request ===
* **Method**: `GET`
* **PROD URL**: `https://id360docaposte.com/api/1.0.0/enrollment/{id}/report`
* **PREPROD URL**: `https://preprod.id360docaposte.com/api/1.0.0/enrollment/{id}/report`
* **Authentication**: `Authorization: Token {your_token}`
=== Example cURL request ===
curl -X GET \
"https://preprod.id360docaposte.com/api/1.0.0/enrollment/{id}/report" \
-H "accept: application/json" \
-H "Authorization: Token 0123456789abcdef01234567"
* **In the URL `{id}`**: refers to the enrollment ID
* **Parameters**: none
* **Result**: HTTP 200 + JSON response
* **Call should only be made from your backend server**
=== Sample response ===
{
"status": "OK",
"id": 215416,
"identity": {
"name": "SPECIMEN ABB",
"first_name": "NATACHA",
"birth_date": "1973-07-12",
"gender": "F",
"birth_place": "TOULON",
"nationality": "FRA",
"extra": {
"id_number": "90RF02331",
"expiration_date": "2029-03-03",
"issuer": "PrΓ©fecture du Sud",
"address": "102 RUE PRINCIPALE 34700 LODΓVE FRANCE"
}
},
"extracted_data": {
"proof_of_address": [
{
"full_name": "MME SPECIMEN NATACHA",
"address_1": "205 route des lylas",
"address_2": "BT LES OLIVIERS",
"zip_code": "06000",
"city": "Nice",
"date": "2022-04-06"
}
],
"bank_details": [
{
"iban": "FR7630006000011234567890189",
"bic": "CEPAFRPP831",
"full_name": "MLE NATACHA SPECIMEN"
}
]
}
}
----
==== β οΈ Warning: do not call the report endpoint too early ====
**β Always wait for the *final callback* on your `callback_url` before calling the report endpoint.**
* This callback confirms the end of the processing.
* Once received, you can safely call `/enrollment/{id}/report`.
* See the callback guide [[en:guide_callbacks|here]]
----
==== ShootID / ID360 Comparison Table ====
^ Function ^ ShootID ^ ID360 ^
| Endpoint | `GET /result` | `GET /enrollment/{id}/report` |
| Authentication | Basic Auth | `Authorization: Token ...` |
| When to call | After document upload | **After final callback is received** |
| Response structure | Per document (`documents[]`) | Per block (`blocks.identity`, `blocks.address`, etc.) |
| Technical results | MRZ / OCR details | Aggregated based on process configuration |
----