****************************** Assessment workflows ****************************** ---- Xobin provides Workflow customizations for customers in the **Standard Plan**. Follow the steps below to customize workflows in Xobin. Workflow types ---------------- 1. **Assessment Start**: Automatically receive notifications when a candidate begins an assessment. 2. **Assessment Submission**: Get assessment results as soon as a candidate submits their assessment and the evaluation is complete. 3. **Assessment updates**: Get notified when a recruiter creates an assessment, or when an assessment is updated, archived, or deleted. With the events ``assessments.create`` or ``assessments.updates``. 4. **Redirection**: Redirect Xobin data to a specified URL for seamless integration with your workflows. Customize Workflows ---------------------------- Navigate to the **Assessments** dashboard. Click on the test settings (three dots) for the desired assessment. .. image:: _static/images/webhooks/all-assessments.png :alt: Test settings for an assessment In test settings, click on **Workflows** tab at the top to customize workflow rules for your assessment. Enable the desired webhook types (including **updates** for assessment create and change events), paste each webhook URL, and use **Send Sample Response** to verify delivery. .. image:: _static/images/webhooks/workflows.png :alt: Workflow customization in Xobin Sample response ----------------------------- .. tab:: Assessment Start .. code-block:: JSON { "id": 2196821, "assessment_id": 53280, "started_at": 1737521866717, "name": "Garrett Bolton", "email": "wuxiwehi@mailinator.com" } .. tab:: Assessment create / update Create and update events share the same envelope. Only ``event`` differs: ``assessments.create`` when a new assessment is created, and ``assessments.updates`` for edits, archive, or delete. ``data`` includes the assessment summary and ``updated_by`` (the user who performed the action). ``x-company-id`` is the ID of the company that the assessment belongs to. .. code-block:: JSON { "event": "assessments.updates", "timestamp": "2026-01-15T10:00:00", "data": { "assessment_id": 12345, "assessment_name": "Sample Assessment", "status": "live", "created_by": { "name": "Jane Recruiter", "id": 1, "email": "jane.recruiter@example.com" }, "creation_date": "2026-01-10T00:00:00", "last_updated": "2026-01-15T10:00:00", "assessment_duration": 60, "number_of_questions": 20, "number_of_sections": 2, "proctoring_status": null, "skills_included": ["Python", "SQL"], "question_types": ["objective", "code"], "updated_by": { "name": "Jane Recruiter", "id": 1, "email": "jane.recruiter@example.com" } } } .. tab:: Assessment Submission .. code-block:: JSON { "assessment_id": "integer", "candidate_id": "integer", "completed_date": "string", "cut_off": "integer", "email": "string", "invite_status": "string", "name": "string", "offtab_count": "integer", "overall_percentage": "double", "registration_fields": [ { "label": "string", "value": "string" } ], "report_id": "integer", "report_link": "string", "sections": [ { "percentage": "double", "section": "string", "skill_wise_score": [ { "skill": "string", "percentage": "float" }, ] }, ] } Authenticate webhook payload ----------------------------- When you receive ``POST`` requests from Xobin, it's essential to verify their authenticity and integrity to prevent malicious activities or data tampering. Each incoming ``POST`` request from Xobin includes an ``x-xobin-signature`` key in the header. This signature is generated by encoding a combination of your ``API_KEY`` and the payload of the request. For JSON webhooks such as **Assessment create / update**, use the exact raw request body (the same byte sequence as in the ``POST``) when computing the hash. To validate the request, you need to follow these steps: - Take the payload of the request and use your ``API_KEY`` to compute the ``HMAC-SHA256`` hash. - Encode the resulting hash using ``Base64 URL`` Safe encoding, without including any padding characters. - Compare this generated signature with the ``x-xobin-signature`` provided in the request headers. - If the two signatures match, it confirms that the request is authentic and hasn't been tampered with during transit. .. tab:: Python .. code-block:: python :linenos: import hmac import hashlib import base64 # Function to verify webhook def verify_webhook(data, hmacHeader, apikey): # Compute the HMAC digest of the data using the provided API key digest = hmac.new( apikey.encode('utf-8'), data.encode('utf-8'), digestmod=hashlib.sha256 ).digest() # Encode the digest into base64 format and remove padding characters computed_hmac = base64.urlsafe_b64encode(digest).rstrip(b"=") # Compare the computed HMAC with the HMAC included in the request return hmac.compare_digest(computed_hmac, hmac_header.encode('utf-8')) .. tab:: Java .. code-block:: java :linenos: import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; // Function to verify webhook public boolean verifyWebhook(String data, String hmacHeader, String apiKey) { try { // Create a new Mac instance with SHA-256 Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(apiKey.getBytes(), "HmacSHA256")); // Compute the HMAC digest String computedHmac = Base64.getUrlEncoder().withoutPadding().encodeToString(mac.doFinal(data.getBytes())); // Compare the computed HMAC with the provided HMAC header return computedHmac.equals(hmacHeader); } catch (Exception e) { e.printStackTrace(); return false; } } .. tab:: Javascript .. code-block:: javascript :linenos: const crypto = require('crypto'); // Function to verify webhook const verifyWebhook = (data, hmacHeader, apiKey) => { // Compute the HMAC digest using SHA-256 const hmac = crypto.createHmac('sha256', apiKey); hmac.update(data); const computedHmac = hmac.digest('base64url'); // 'base64url' gives URL-safe Base64 without padding // Compare the computed HMAC with the provided HMAC header return computedHmac === hmacHeader; }; .. tab:: PHP .. code-block:: php :linenos: - ``data``: The payload received from the webhook. - ``hmacHeader``: The HMAC signature included in the request. - ``apikey``: The API key used for HMAC generation. If you have any questions, reach out to your account manager for assistance.