diff --git a/modules/crm_case_external_id/config/optional/field.storage.crm_case.external_id.yml b/modules/crm_case_external_id/config/optional/field.storage.crm_case.external_id.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a11a19a87df74927f22498a4e8177ab52395f449
--- /dev/null
+++ b/modules/crm_case_external_id/config/optional/field.storage.crm_case.external_id.yml
@@ -0,0 +1,24 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - crm_case
+  enforced:
+    module:
+      - crm_case_external_id
+id: crm_case.external_id
+field_name: external_id
+entity_type: crm_case
+type: integer
+settings:
+  unsigned: true
+  size: normal
+module: core
+locked: false
+cardinality: 1
+translatable: true
+indexes:
+  value:
+    - value
+persist_with_no_fields: true
+custom_storage: false
diff --git a/modules/crm_case_external_id/crm_case_external_id.info.yml b/modules/crm_case_external_id/crm_case_external_id.info.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c8bbd06f65d79d0220356eae0975bbb5a0557b54
--- /dev/null
+++ b/modules/crm_case_external_id/crm_case_external_id.info.yml
@@ -0,0 +1,5 @@
+name: 'External Case Id'
+type: module
+description: 'An external Id for CRM Case entity.'
+package: CRM
+core_version_requirement: ^10 || ^11
diff --git a/modules/crm_case_external_id/crm_case_external_id.module b/modules/crm_case_external_id/crm_case_external_id.module
new file mode 100644
index 0000000000000000000000000000000000000000..282ad42e602694980efae82658bd75742accc313
--- /dev/null
+++ b/modules/crm_case_external_id/crm_case_external_id.module
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * @file
+ * Contains crm_case_external_id.module.
+ */
+
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Implements hook_entity_bundle_field_info_alter().
+ */
+function crm_case_external_id_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) {
+
+  if ($entity_type->id() === 'crm_case') {
+    if (isset($fields['external_id'])) {
+      // Use the ID as defined in the annotation of the constraint definition.
+      $fields['external_id']->addConstraint('CrmCaseExternalId', []);
+    }
+  }
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter() for 'field_config_edit_form'.
+ */
+function crm_case_external_id_form_field_config_form_alter(&$form, FormStateInterface $form_state, $form_id) {
+  $field = $form_state->getFormObject()->getEntity();
+  if ($field->getName() !== 'external_id' || $field->getTargetEntityTypeId() !== 'crm_case') {
+    return;
+
+  }
+  $crm_case_bundles = \Drupal::entityTypeManager()->getStorage('crm_case_type')->loadMultiple();
+  $options = [];
+  foreach ($crm_case_bundles as $crm_case_bundle) {
+    $options[$crm_case_bundle->id()] = $crm_case_bundle->label();
+  }
+
+  $form['third_party_settings']['external_id'] = [
+    '#type' => 'details',
+    '#title' => t('External Id settings'),
+    '#open' => TRUE,
+    '#group' => 'advanced',
+    '#weight' => 100,
+  ];
+
+  $form['third_party_settings']['external_id']['bundles'] = [
+    '#type' => 'checkboxes',
+    '#title' => t('Bundles'),
+    '#options' => $options,
+    '#default_value' => $field->getThirdPartySetting('external_id', 'bundles', []),
+  ];
+  $form['third_party_settings']['external_id']['negate'] = [
+    '#type' => 'radios',
+    '#title' => t('Negate'),
+    '#options' => [
+      0 => t('Include'),
+      1 => t('Exclude'),
+    ],
+    '#default_value' => $field->getThirdPartySetting('external_id', 'negate', 0),
+  ];
+
+  $form['#validate'][] = 'crm_case_external_id_form_field_config_form_validate';
+}
+
+/**
+ * Validation for 'field_config_edit_form'.
+ */
+function crm_case_external_id_form_field_config_form_validate(&$form, FormStateInterface $form_state) {
+
+  $third_party_settings = $form_state->getValue('third_party_settings');
+  $bundles = $third_party_settings['external_id']['bundles'];
+  $bundles = array_filter($bundles);
+  if (empty($bundles)) {
+    return;
+  }
+
+  $field = $form_state->getFormObject()->getEntity();
+  $bundle = $field->getTargetBundle();
+  $in_array = in_array($bundle, $bundles);
+  $negate = $third_party_settings['external_id']['negate'];
+
+  if ($negate && $in_array) {
+    $form_state->setErrorByName('third_party_settings][external_id][bundles', t('The bundle %bundle is selected and negate is enabled.', ['%bundle' => $bundle]));
+  }
+  elseif (!$negate && !$in_array) {
+    $form_state->setErrorByName('third_party_settings][external_id][bundles', t('The bundle %bundle is not selected and negate is disabled.', ['%bundle' => $bundle]));
+  }
+
+}
diff --git a/modules/crm_case_external_id/src/Plugin/Validation/Constraint/ExternalIdConstraint.php b/modules/crm_case_external_id/src/Plugin/Validation/Constraint/ExternalIdConstraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..2140a0f4d4ca784e61375758636426b640a541fc
--- /dev/null
+++ b/modules/crm_case_external_id/src/Plugin/Validation/Constraint/ExternalIdConstraint.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Drupal\crm_case_external_id\Plugin\Validation\Constraint;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * Checks that the submitted value is a unique integer.
+ *
+ * @Constraint(
+ *   id = "CrmCaseExternalId",
+ *   label = @Translation("External Crm Case Id", context = "Validation"),
+ *   type = "integer"
+ * )
+ */
+class ExternalIdConstraint extends Constraint {
+
+  /**
+   * The message that will be shown if the value is not an integer.
+   *
+   * @var string
+   */
+  public $notInteger = '%value is not an integer';
+
+  /**
+   * The message that will be shown if the value is not unique.
+   *
+   * @var string
+   */
+  public $notUnique = '%value is not unique';
+
+}
diff --git a/modules/crm_case_external_id/src/Plugin/Validation/Constraint/ExternalIdConstraintValidator.php b/modules/crm_case_external_id/src/Plugin/Validation/Constraint/ExternalIdConstraintValidator.php
new file mode 100644
index 0000000000000000000000000000000000000000..8b4b29ae3666602329e488449fb106fe05afee79
--- /dev/null
+++ b/modules/crm_case_external_id/src/Plugin/Validation/Constraint/ExternalIdConstraintValidator.php
@@ -0,0 +1,103 @@
+<?php
+
+namespace Drupal\crm_case_external_id\Plugin\Validation\Constraint;
+
+use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+
+/**
+ * Validates the UniqueInteger constraint.
+ */
+class ExternalIdConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  private $entityTypeManager;
+
+  /**
+   * Creates a new TaxonomyTermHierarchyConstraintValidator instance.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   */
+  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('entity_type.manager')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validate($value, Constraint $constraint) {
+    $entity = $value->getEntity();
+    $field_definition = $value->getFieldDefinition();
+
+    // dpm($field_definition->get('entity_type'));
+    // dpm($field_definition->get('field_name'));
+    // dpm($field_definition->get('bundle'));.
+    foreach ($value as $item) {
+      // First check if the value is an integer.
+      if (!is_int((int) $item->value)) {
+        // The value is not an integer, so a violation, aka error, is applied.
+        // The type of violation applied comes from the constraint description
+        // in step 1.
+        $this->context->addViolation($constraint->notInteger, ['%value' => $item->value]);
+      }
+
+      // Next check if the value is unique.
+      if (!$this->isUnique($item->value, $entity, $field_definition)) {
+        $this->context->addViolation($constraint->notUnique, ['%value' => $item->value]);
+      }
+    }
+  }
+
+  /**
+   * Is unique?
+   *
+   * @param string $value
+   *   The value to check.
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity.
+   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+   *   The field definition.
+   */
+  private function isUnique($value, $entity, $field_definition) {
+
+    $entity_type = $field_definition->get('entity_type');
+    $field_name = $field_definition->get('field_name');
+    $bundle = $field_definition->get('bundle');
+    $bundles = $field_definition->getThirdPartySetting('external_id', 'bundles', []);
+    $bundles = array_filter($bundles);
+    $negate = $field_definition->getThirdPartySetting('external_id', 'negate', FALSE);
+    // Here is where the check for a unique value would happen.
+    $query = $this->entityTypeManager->getStorage($entity_type)->getQuery();
+    $query->condition($field_name, $value);
+    if (!$entity->isNew()) {
+      $entity_id = $entity->id();
+      $query->condition('id', $entity_id, '<>');
+    }
+    if (!empty($bundles)) {
+      $operator = $negate ? 'NOT IN' : 'IN';
+      $query->condition('bundle', $bundles, $operator);
+    }
+
+    $results = $query->accessCheck(FALSE)->count()->execute();
+
+    return $results === 0;
+  }
+
+}