Deleting a candidate profile
This page provides instructions on deleting a candidate profile, detailing both the user interface (UI) and programmatically methods, along with scenarios to consider during deletion.
Deleting a candidate profile
Note:
- This requires the permission perm_delete_profile
- This is only possible in the candidate's full profile. This is not possible in the Candidate Sidebar on the Position pipeline
To delete a candidate profile, navigate to that profile and take the following steps:
- Click the
three-dot menu. - Click Delete Profile.

Note:
- This action of deleting a candidate profile affects only the Eightfold Profile and will not be reflected on ATS side. To prevent reappearing of the candidate profile, the profile should be deleted from the ATS side prior to the deletion in Eightfold.
- Eightfold automatically restores the candidate profile in the next candidate sync for this profile. To have the profile deleted from your ATS system, contact your Eightfold Admin or your ATS team.
- Go to Eightfold API
- Fill in the profileId and Authorization key as shown below in screenshot.

For Profile ID follow below steps:
- Go to the candidate profile you want to delete
- Click on the three dot menu -> select debug raw profile
- Copy the Eightfold ID which is the profile ID as shown in the screenshot

For Authorization Key follow below steps :
- Go to Admin console -> Integration -> Eightfold API -> Copy the key as shown in the screenshot

- Click on the try it button and you will get the response as shown below if the profile is deleted.
- Go to admin console -> Data Ingestion -> File Ingestion
- Upload the XML file for the candidate profiles which needs to be deleted. To create the XML file for candidate follow these steps :
- Confirm that Python version 3.8.x or higher and pip are installed on the system.
- Verify that the modules listed in the requirement.txt file are installed by running the command pip install -r requirements.txt.
Requirements.txt : lxml==4.9.2 - Execute the script given below using the command python3 purge _ candidate _ transform.py --input_file ./input.json.
from lxml import etree from json import loads from argparse import ArgumentParser from csv import DictReader from csv import field_size_limit from sys import exit import xml.etree.ElementTree as ET ONE_TAG_LENGTH = 1 ZERO_TAG_LENGTH = 0 EXIT_CODE = 1 PRINT_CONSTANTS = { 'FILE_ERROR': '--input_file argument is required', 'VALUE_ERROR': 'value error occurred when calling {} function ', 'PARSE_ERROR': 'XML Parse error occurred when calling {} function ', 'UNICODE_ERROR': 'Unicode error occurred when calling {} function ', 'VALID_ARGS': 'Input argument valiation passe successfully', 'NO_DATA': 'No file data in json, quitting the process.....', 'READING_DATA': 'Reading the data from input file {}', 'WRITING_DATA': 'writing the data to output_file {}', 'BUILD_XML_START': "################ building xml is started ################", 'BUILD_XML_COMPLETED': "################ building xml is completed ################", 'OUTPUT_XML_START': "################ writing to output file is started ################", 'OUTPUT_XML_COMPLETED': "################ writing to output file is completed ################", } FILE_CONSTANTS = { 'FIELD_LIMIT': 100000, 'OUTPUT_ENCODING': 'utf-8', 'INPUT_FILE_FORMAT': 'json', 'OUTPUT_FILE_FORMAT': 'xml', 'PARENT_TAG': 'EF_Candidate_List', 'CHILD_TAG': 'EF_Candidate', 'XML_TAG': 'candidate_id' } def read_file(file_object, delimiter, encoding): if not file_object: return None field_size_limit(FILE_CONSTANTS['FIELD_LIMIT']) print(PRINT_CONSTANTS['READING_DATA'].format(file_object)) with open(file_object, 'r+', encoding=encoding) as csvfile: csv_reader = list(DictReader(csvfile, delimiter=delimiter)) return csv_reader def write_output(data, output_file): print(PRINT_CONSTANTS['WRITING_DATA'].format(output_file)) with open(output_file, 'w+', encoding=FILE_CONSTANTS['OUTPUT_ENCODING']) as out: out.write(data) def get_tag(element, value=''): try: if value: ef_tag = etree.Element(element) ef_tag.text = value else: ef_tag = etree.Element(element) return ef_tag except UnicodeDecodeError as error: print(PRINT_CONSTANTS['UNICODE_ERROR'].format(get_tag.__name__), error) exit(1) except ValueError as error: print(PRINT_CONSTANTS['VALUE_ERROR'].format(get_tag.__name__), error) exit(1) except ET.ParseError as error: print(PRINT_CONSTANTS['PARSE_ERROR'].format(get_tag.__name__), error) exit(1) def build_purge_record(csv_data, column_field): """ Description of build_user_record Args: csv_data : unique record from the input csv file return: Etree object """ child_tag = get_tag(FILE_CONSTANTS['CHILD_TAG']) if csv_data.get(column_field): ef_id_tag = get_tag(FILE_CONSTANTS['XML_TAG'], csv_data[column_field]) child_tag.append(ef_id_tag) return child_tag def get_xml_str(data): try: output_str = etree.tostring(data, encoding=FILE_CONSTANTS['OUTPUT_ENCODING'], pretty_print=True).decode() return output_str except UnicodeDecodeError as error: print(PRINT_CONSTANTS['UNICODE_ERROR'].format(get_xml_str.__name__), error) exit(1) except ValueError as error: print(PRINT_CONSTANTS['VALUE_ERROR'].format(get_xml_str.__name__), error) exit(1) except ET.ParseError as error: print(PRINT_CONSTANTS['PARSE_ERROR'].format(get_xml_str.__name__), error) exit(1) def build_xml(purge_data, column_field): """ Description of build_and_write_xml transform into Args: purge_file (undefined): input file location delimiter (undefined): str """ length = len(purge_data) root = get_tag(FILE_CONSTANTS['PARENT_TAG']) for index, value in enumerate(purge_data): print('processing ', index, 'out of ', length) record = build_purge_record(value, column_field) print(record) if record is not None: root.append(record) output_data = get_xml_str(root) return output_data def main(data_json): """ "FILE_ENCODING": "utf-8", "INPUT_FILE_PATH": "", "DELIMITER": ",", "ENCODING": "utf-8", "CSV_COLUMN_FIELD": "candidate_id", "INPUT_CANDIDATE_PURGE_FILE_PATH": "" "OUTPUT_XML_FILE": "" """ input_file = data_json['INPUT_CANDIDATE_PURGE_FILE_PATH'] delimiter = data_json['DELIMITER'] encoding = data_json['ENCODING'] output_file = data_json['OUTPUT_XML_FILE'] csv_data_column_field = data_json['CSV_COLUMN_FIELD'] print(PRINT_CONSTANTS['BUILD_XML_START']) csv_data = read_file(input_file, delimiter, encoding) data = build_xml(csv_data, csv_data_column_field) print(PRINT_CONSTANTS['BUILD_XML_COMPLETED']) print(PRINT_CONSTANTS['OUTPUT_XML_START']) write_output(data, output_file) print('output file is generated at ', output_file) print(PRINT_CONSTANTS['OUTPUT_XML_COMPLETED']) def get_args(): parser = ArgumentParser() parser.add_argument('--input_file') args = parser.parse_args() if not args.input_file: print(PRINT_CONSTANTS['FILE_ERROR']) exit(EXIT_CODE) else: print(PRINT_CONSTANTS['VALID_ARGS']) return args def process_args(args): with open(args.input_file, 'r') as f: file_data = f.read() config_file_dict = loads(file_data) if not config_file_dict: print(PRINT_CONSTANTS['NO_DATA']) exit(EXIT_CODE) return config_file_dict if __name__ == '__main__': args = get_args() data_json = process_args(args) main(data_json) - Customize the parameters within the input.json file with the appropriate details.
- Upload the .xml file and chose the Delete option from the Operation Field and click on start button
When to reach out to your admin
Not all user accounts are provisioned with the Delete Profile option. If you do not find this option, contact your company’s Eightfold Admins and request that they delete the profile.
Right after deletion, the candidate's profile might still show up in the Global Search for up to 24 hours, as the system needs time to update its search results. If you click on the returned profile during this time, you will see an error message -
"This Profile was deleted at {timestamp when the delete action was initiated}."
Other programmatic ways to delete the profile(s)
Deleting profile using Eightfold API
Customers who prefer to manage candidate profiles from an external application can leverage the Eightfold APIs. The integration to Eightfold APIs will be built and owned by the customer.
Deleting profile using File based ingestion
Eightfold file ingestion framework supports managing User as well as role assignments and re-assignments. Customers should provide a file in the Eightfold specified format which can be ingested as a one-time activity or on a recurring basis depending on the customer use-case.
The following script is designed to purge candidates based on their candidate ID. To execute the script, ensure that the following prerequisites are fulfilled:
Below is a sample input.json file for purging the candidate:
{
"DELIMITER": ",",
"ENCODING": "utf-8-sig",
"CSV_COLUMN_FIELD": "CANDIDATE_ID",
"INPUT_CANDIDATE_PURGE_FILE_PATH": "/Users/dsunderg/Documents/customers/customer_test/candidate/cpg_data/CR - TMP - Candidate File 2023-11-14 01_37 EST.csv",
"OUTPUT_XML_FILE": "/Users/dsunderg/Documents/customers/file_ingest/cand_purge_customer/cand.xml"
}
Below is Sample csv data :
CANDIDATE_ID
111
222

Database tables to clean when hard deleting a candidate profile
To clean up all entries where the profile ID is referenced, these are all the database tables:
- candidates
- candidate_profiles
- profile_data
- profile_notes
- profile_tags
- profile_applications
- profile_contact_info
- profile_feedback
- user_messages
- user_calendar_events
- event_candidate_activity
- offers
Scenarios while deleting a profile
This section describes frequently asked questions about deleting a candidate profile.
Profile still appears in Career Hub and Talent Acquisition
A profile is visible in Career Hub and Talent Acquisition as it still exists in the Eightfold database. When a user account is disabled, the user can no longer log in to Eightfold account or perform any actions. User accounts can be deleted or disabled from Manage Users and this will not delete the profile associated with the user account, if there is any profile associated with.
For the profile to be removed completely, an Eightfold Admin or your ATS team must delete the profile from the Eightfold database and ATS end.
Impact on the AI recommendations
If users are removed from the Eightfold database and ATS end, there won't be any impact on the AI recommendations. The profiles are kept for the talent network of company (in case you want to reach out to the users in future for other opportunities). If the user want to apply again, their profile history is retained.
Deleting a profile created by mistake
Follow the steps in a previous section for deleting a profile.
If the profile was also created in the ATS due to an application, then the profile must deleted in the ATS. You must delete the profile from your ATS by an Eightfold Admin or your ATS team.
Note: If the profile is created through a candidate uploading their resume to apply for a position or through the Eightfold Chrome Extension, Eightfold doesn't create it in the ATS.
Profile is searchable with email ID
A profile may still be searchable by email ID, even after deletion from SuccessFactors and Eightfold. There are a few reasons why this might be the case:
- There could be an intermittent network glitch during the time you tried to delete or it could be a cache or cookies issue.
- There may be delay in deleting the profile in ATS and due to the same, it might have been re-synced.
- If the profile is still visible or can be viewed then the profile is not deleted in Eightfold or in ATS and it needs to be deleted from ATS and Eightfold.
- There could be a dupe profile with the same email ID. Even if ATS profile is deleted, it may start showing the dupe profile that could have been sourced in Eightfold stage.
If you have faced any of these issues when you are trying to delete the candidate profile and it is not deleting, try in a different browser. If it's still not deleting, please reach out to us and we will investigate the issue.