[[: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 | ----