# -*- coding: utf-8 -*-
"""
:Module: salespyforce.knowledge
:Synopsis: Defines the Knowledge-related functions associated with the Salesforce API
:Created By: Jeff Shurtliff
:Last Modified: Jeff Shurtliff
:Modified Date: 03 Feb 2026
"""
from __future__ import annotations
from typing import Optional
from . import errors
from .utils import log_utils
# Define constants
KNOWLEDGE_SOBJECT = 'Knowledge__kav'
# Initialize logging
logger = log_utils.initialize_logging(__name__)
[docs]
def check_for_existing_article(
sfdc_object, title: str,
sobject: Optional[str] = None,
return_id: bool = False,
return_id_and_number: bool = False,
include_archived: bool = False,
):
"""This method checks to see if an article already exists with a given title and returns its article number.
(`Reference 1 <https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_query.htm>`_,
`Reference 2 <https://developer.salesforce.com/docs/atlas.en-us.knowledge_dev.meta/knowledge_dev/knowledge_development_soql_sosl_intro.htm>`_)
.. versionchanged:: 1.2.2
You can now specify whether archived articles are included in the query results.
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param title: The title of the knowledge article for which to check
:type title: str
:param sobject: The Salesforce object to query (``Knowledge__kav`` by default)
:type sobject: str, None
:param return_id: Determines if the Article ID should be returned (``False`` by default)
:type return_id: bool
:param return_id_and_number: Determines if Article ID and Article Number should be returned (``False`` by default)
:type return_id_and_number: bool
:param include_archived: Determines if archived articles should be included (``False`` by default)
:type include_archived: bool
:returns: The Article Number, Article ID, or both, if found, or a blank string if not found
"""
sobject = 'Knowledge__kav' if sobject is None else sobject
query = f"SELECT Id,ArticleNumber FROM {sobject} WHERE Title = '{title}'"
query += " AND PublishStatus != 'Archived'" if not include_archived else query
response = sfdc_object.soql_query(query, replace_quotes=False)
return_value = ''
if response.get('totalSize') > 0:
if return_id:
return_value = response['records'][0]['Id']
elif return_id_and_number:
return_value = (response['records'][0]['Id'], response['records'][0]['ArticleNumber'])
else:
return_value = response['records'][0]['ArticleNumber']
elif return_id_and_number:
return_value = ('', '')
return return_value
[docs]
def get_article_id_from_number(
sfdc_object,
article_number,
sobject: Optional[str] = None,
return_uri: bool = False,
) -> str:
"""This method returns the Article ID when an article number is provided.
(`Reference 1 <https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_query.htm>`_,
`Reference 2 <https://developer.salesforce.com/docs/atlas.en-us.knowledge_dev.meta/knowledge_dev/knowledge_development_soql_sosl_intro.htm>`_)
.. warning::
The ability to retrieve the article URI/URL rather than the ID will be moved to a separate function in
a future release.
.. versionchanged:: 1.4.0
A logic issue has been fixed and improved to make this function more robust and stable.
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param article_number: The Article Number to query
:type article_number: str, int
:param sobject: The Salesforce object to query (``Knowledge__kav`` by default)
:type sobject: str, None
:param return_uri: Determines if the URI of the article should be returned rather than the ID (``False`` by default)
:type return_uri: bool
:returns: The Article ID or Article URI, or a blank string if no article is found
:raises: :py:exc:`TypeError`,
:py:exc:`RuntimeError`
"""
# Ensure the sobject is defined appropriately
if sobject and not isinstance(sobject, str):
exc_msg = f'The sobject must be a string (provided: {type(sobject)})'
logger.error(exc_msg)
raise TypeError(exc_msg)
if not sobject:
sobject = KNOWLEDGE_SOBJECT
logger.debug(f'The {KNOWLEDGE_SOBJECT} sObject will be used as one was not provided')
# Construct the SOQL query to perform
article_number = str(article_number) if not isinstance(article_number, str) else article_number
if len(article_number) < 9:
query = f"SELECT Id FROM {sobject} WHERE ArticleNumber LIKE '%0{article_number}'"
else:
query = f"SELECT Id FROM {sobject} WHERE ArticleNumber = '{article_number}'"
# Perform the SOQL query and return the article number if found
response = sfdc_object.soql_query(query)
if response.get('totalSize') > 0:
if return_uri:
# TODO: Split out the return_uri functionality into a separate function and method
warn_msg = ("The ability to retrieve the article URI/URL rather than the ID (return_uri parameter) will "
"be moved to a separate function/method in a future release")
logger.warning(warn_msg)
errors.handlers.display_warning(warn_msg)
return_value = response['records'][0]['attributes']['url']
else:
return_value = response['records'][0]['Id']
else:
return_value = ''
warn_msg = f'No results were returned when querying for the article number {article_number}'
logger.warning(warn_msg)
return return_value
[docs]
def get_articles_list(
sfdc_object,
query: Optional[str] = None,
sort: Optional[str] = None,
order: Optional[str] = None,
page_size: int = 20,
page_num: int = 1,
):
"""This function retrieves a list of knowledge articles.
(`Reference <https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_knowledge_support_artlist.htm>`_)
.. versionchanged:: 1.4.0
The errors now log as errors via the logger rather than to the stderr console.
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param query: A SOQL query with which to filter the results (optional)
:type query: str, None
:param sort: One of the following optional values: ``LastPublishedDate``, ``CreatedDate``, ``Title``, or ``ViewScore``
:type sort: str, None
:param order: Optionally define the ORDER BY as ``ASC`` or ``DESC``
:type order: str, None
:param page_size: The number of results per page (``20`` by default)
:type page_size: int
:param page_num: The starting page number (``1`` by default)
:type page_num: int
:returns: The list of retrieved knowledge articles
"""
# Define the headers
headers = sfdc_object._get_headers('articles')
# Validate the sort field
# TODO: Convert list below into constant
valid_sort_options = ['LastPublishedDate', 'CreatedDate', 'Title', 'ViewScore']
if sort and sort not in valid_sort_options:
logger.error(f"The sort value '{sort}' is not valid and will be ignored")
sort = None
# Validate the order field
if order and order.upper() not in ['ASC', 'DESC']:
logger.error(f"The order value '{order}' is not valid and will be ignored")
order = None
# Validate the page size field
if page_size > 100:
logger.error('The pageSize value exceeds the maximum and will default to 100')
page_size = 100
# Validate the pageNumber field
if page_num < 1:
logger.error('The pageNumber value is not valid and will default to 1')
page_num = 1
# Add values to the parameters dictionary if they have been defined
params = {}
if query:
params['q'] = query
if sort:
params['sort'] = sort
if order:
params['order'] = order
params['pageSize'] = page_size
params['pageNumber'] = page_num
# Perform the query
# TODO: Determine what is returned by this API call and see if data should be pruned to just the list of articles
return sfdc_object.get(f'/services/data/{sfdc_object.version}/support/knowledgeArticles',
params=params, headers=headers)
[docs]
def get_article_details(
sfdc_object,
article_id: str,
sobject: Optional[str] = None,
use_knowledge_articles_endpoint: Optional[bool] = None,
):
"""This function retrieves details for a single knowledge article.
(`Reference <https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_knowledge_support_artdetails.htm>`_)
.. versionchanged:: 1.4.0
A logic issue was resolved and the new optional ``use_knowledge_articles_endpoint`` parameter can now be set to
force the ``knowledgeArticles`` endpoint to be used for the GET request rather than the ``sobjects`` endpoint.
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param article_id: The Article ID for which to retrieve details
:type article_id: str
:param sobject: The Salesforce object to query (``Knowledge__kav`` by default)
:type sobject: str, None
:param use_knowledge_articles_endpoint: Optionally use the ``knowledgeArticles`` endpoint rather than ``sobjects``
to retrieve the article details (``False`` by default)
:type use_knowledge_articles_endpoint: bool, None
:returns: The details for the knowledge article
:raises: :py:exc:`RuntimeError`,
:py:exc:`salespyforce.errors.exceptions.DataMismatchError`
"""
# Define the headers based on the endpoint that will be utilized
headers = sfdc_object._get_headers('articles') if use_knowledge_articles_endpoint else None
# Ensure there are no conflicting parameters
if sobject and use_knowledge_articles_endpoint:
if sobject == KNOWLEDGE_SOBJECT:
info_msg = (f'It is not necessary to define the sObject as {KNOWLEDGE_SOBJECT} when leveraging '
f'the knowledgeArticles endpoint')
logger.info(info_msg)
else:
error_msg = 'You cannot use the knowledgeArticles endpoint with an explicitly defined sObject'
logger.error(error_msg)
raise errors.exceptions.DataMismatchError(error_msg)
# Define the endpoint to use in the GET request
if use_knowledge_articles_endpoint:
endpoint = f'/services/data/{sfdc_object.version}/support/knowledgeArticles/{article_id}'
else:
sobject = KNOWLEDGE_SOBJECT if not sobject else sobject
endpoint = f'/services/data/{sfdc_object.version}/sobjects/{sobject}/{article_id}'
# Perform the query and return the data
data = sfdc_object.get(endpoint, headers=headers)
# TODO: Determine what is returned by this API call and see if data should be pruned to just the article details (for both endpoints)
return data
[docs]
def get_validation_status(
sfdc_object,
article_id: Optional[str] = None,
article_details: Optional[dict] = None,
sobject: Optional[str] = None,
) -> str:
"""This function retrieves the Validation Status for a given Article ID.
(`Reference <https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_knowledge_support_artdetails.htm>`_)
.. versionchanged:: 1.4.0
The function now returns an empty string rather than a ``None`` value if the ``ValidationStatus`` field
is not found in the article details data, and a more specific exception class is used when input
data is missing instead of the generic :py:exc:`RuntimeError` exception class.
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param article_id: The Article ID for which to retrieve details
:type article_id: str, None
:param article_details: The dictionary of article details for the given article
:type article_details: dict, None
:param sobject: The Salesforce object to query (``Knowledge__kav`` by default)
:type sobject: str, None
:returns: The validation status as a text string
:raises: :py:exc:`RuntimeError`,
:py:exc:`salespyforce.errors.exceptions.MissingRequiredDataError`
"""
if not any((article_id, article_details)):
raise errors.exceptions.MissingRequiredDataError('The article ID or article details must be provided.')
# Retrieve the article details if not already supplied
if not article_details:
article_details = get_article_details(sfdc_object, article_id, sobject)
# Identify the validation status
return article_details.get('ValidationStatus', '')
[docs]
def get_article_metadata(sfdc_object, article_id: str):
"""This function retrieves metadata for a specific knowledge article.
(`Reference <https://developer.salesforce.com/docs/atlas.en-us.knowledge_dev.meta/knowledge_dev/knowledge_REST_retrieve_article_metadata.htm>`_)
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param article_id: The Article ID for which to retrieve details
:type article_id: str
:returns: The article metadata as a dictionary
:raises: :py:exc:`RuntimeError`
"""
return sfdc_object.get(f'/services/data/{sfdc_object.version}/knowledgeManagement/articles/{article_id}')
[docs]
def get_article_version(sfdc_object, article_id: str):
"""This function retrieves the version ID for a given master article ID.
(`Reference <https://developer.salesforce.com/docs/atlas.en-us.knowledge_dev.meta/knowledge_dev/knowledge_REST_retrieve_article_version.htm>`_)
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param article_id: The Article ID for which to retrieve details
:type article_id: str
:returns: The version ID for the given master article ID
:raises: :py:exc:`RuntimeError`
"""
endpoint = f'/services/data/{sfdc_object.version}/knowledgeManagement/articleversions/masterVersions/{article_id}'
# TODO: Determine what is returned by this API call and see if data should be pruned to just the Version ID
return sfdc_object.get(endpoint)
[docs]
def get_article_url(
sfdc_object,
article_id: Optional[str] = None,
article_number=None,
sobject: Optional[str] = None,
) -> str:
"""This function constructs the URL to view a knowledge article in Lightning or Classic.
.. versionchanged:: 1.2.0
Changed when lightning URLs are defined and fixed an issue with extraneous slashes.
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param article_id: The Article ID for which to retrieve details
:type article_id: str, None
:param article_number: The article number for which to retrieve details
:type article_number: str, int, None
:param sobject: The Salesforce object to query (``Knowledge__kav`` by default)
:type sobject: str, None
:returns: The article URL as a string
:raises: :py:exc:`ValueError`
"""
sobject = 'Knowledge__kav' if sobject is None else sobject
if not any((article_id, article_number)):
raise ValueError('An article ID or an article number must be provided to retrieve the article URL.')
if article_number and not article_id:
article_id = get_article_id_from_number(sfdc_object, article_number, sobject)
segment = '' if sfdc_object.base_url.endswith('/') else '/'
if 'lightning' in sfdc_object.base_url or sobject == 'Knowledge__kav':
article_url = f'{sfdc_object.base_url}{segment}lightning/r/Knowledge__kav/{article_id}/view'
else:
article_url = f'{sfdc_object.base_url}{segment}knowledge/publishing/articleDraftDetail.apexp?id={article_id}'
return article_url
[docs]
def create_article(
sfdc_object,
article_data: dict,
sobject: Optional[str] = None,
full_response: bool = False,
):
"""This function creates a new knowledge article draft.
(`Reference <https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_create.htm>`_)
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param article_data: The article data used to populate the article
:type article_data: dict
:param sobject: The Salesforce object to query (``Knowledge__kav`` by default)
:type sobject: str, None
:param full_response: Determines if the full API response should be returned instead of the article ID (``False`` by default)
:type full_response: bool
:returns: The API response or the ID of the article draft
:raises: :py:exc:`ValueError`, :py:exc:`TypeError`, :py:exc:`RuntimeError`
"""
# Get the appropriate sObject to call
sobject = 'Knowledge__kav' if sobject is None else sobject
# Ensure the payload is in the appropriate format
if not isinstance(article_data, dict):
raise TypeError('The article data must be provided as a dictionary.')
# Ensure that the required fields have been provided
required_fields = ['Title', 'UrlName']
for field in required_fields:
if field not in article_data:
raise ValueError(f'The following required field is missing from the article data: {field}')
# Perform the API call
response = sfdc_object.post(f'/services/data/{sfdc_object.version}/sobjects/{sobject}', payload=article_data)
# Return the full response or just the article ID
if not full_response:
response = response.get('id')
return response
[docs]
def update_article(
sfdc_object,
record_id: str,
article_data: dict,
sobject: Optional[str] = None,
include_status_code: bool = False,
):
"""This function updates an existing knowledge article draft.
(`Reference <https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_update_fields.htm>`_)
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param record_id: The ID of the article draft record to be updated
:type record_id: str
:param article_data: The article data used to update the article
:type article_data: dict
:param sobject: The Salesforce object to query (``Knowledge__kav`` by default)
:type sobject: str, None
:param include_status_code: Determines if the API response status code should be returned (``False`` by default)
:type include_status_code: bool
:returns: A Boolean indicating if the update operation was successful, and optionally the API response status code
:raises: :py:exc:`ValueError`,
:py:exc:`TypeError`,
:py:exc:`RuntimeError`
"""
# Get the appropriate sObject to call
sobject = 'Knowledge__kav' if sobject is None else sobject
# Ensure the payload is in the appropriate format
if not isinstance(article_data, dict):
raise TypeError('The article data must be provided as a dictionary.')
# Ensure that the required fields have been provided
required_fields = ['Title', 'UrlName']
for field in required_fields:
if field not in article_data:
raise ValueError(f'The following required field is missing from the article data: {field}')
# Perform the API call
response = sfdc_object.patch(f'/services/data/{sfdc_object.version}/sobjects/{sobject}/{record_id}',
payload=article_data)
# Determine whether the call was successful
successful = True if response.status_code == 204 else False
# Return the success determination and optionally the status code
if include_status_code:
return successful, response.status_code
return successful
[docs]
def create_draft_from_online_article(sfdc_object, article_id: str, unpublish: bool = False):
"""This function creates a draft knowledge article from an online article.
(`Reference <https://developer.salesforce.com/docs/atlas.en-us.knowledge_dev.meta/knowledge_dev/actions_obj_knowledge.htm#createDraftFromOnlineKnowledgeArticle>`_)
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param article_id: The ID of the online article from which to create the draft
:type article_id: str
:param unpublish: Determines if the online article should be unpublished when the draft is created (``False`` by default)
:type unpublish: bool
:returns: The API response from the POST request
:raises: :py:exc:`RuntimeError`
"""
# Define the payload for the API call
payload = {
"inputs": [
{
"action": "EDIT_AS_DRAFT_ARTICLE",
"unpublish": unpublish,
"articleId": f"{article_id}"
}
]
}
# Perform the API call
endpoint = f'/services/data/{sfdc_object.version}/actions/standard/createDraftFromOnlineKnowledgeArticle'
return sfdc_object.post(endpoint, payload)
[docs]
def create_draft_from_master_version(
sfdc_object,
article_id: Optional[str] = None,
knowledge_article_id: Optional[str] = None,
article_data: Optional[dict] = None,
sobject: Optional[str] = None,
full_response: bool = False,
):
"""This function creates an online version of a master article.
(`Reference <https://developer.salesforce.com/docs/atlas.en-us.198.0.knowledge_dev.meta/knowledge_dev/knowledge_REST_edit_online_master.htm>`_)
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param article_id: The Article ID from which to create the draft
:type article_id: str, None
:param knowledge_article_id: The Knowledge Article ID (``KnowledgeArticleId``) from which to create the draft
:type knowledge_article_id: str, None
:param article_data: The article data associated with the article from which to create the draft
:type article_data: dict, None
:param sobject: The Salesforce object to query (``Knowledge__kav`` by default)
:type sobject: str, None
:param full_response: Determines if the full API response should be returned instead of the article ID (``False`` by default)
:type full_response: bool
:returns: The API response or the ID of the article draft
:raises: :py:exc:`RuntimeError`
"""
if not any((article_id, knowledge_article_id, article_data)):
# TODO: Change to more specific exception class (errors.exceptions.MissingRequiredDataError)
raise RuntimeError('Need to provide article ID, knowledge article ID, or article data')
# Get the appropriate sObject to call
sobject = KNOWLEDGE_SOBJECT if sobject is None else sobject
# Get the knowledge article ID as needed
if not knowledge_article_id:
if not article_data:
article_data = sfdc_object.get_article_details(article_id, sobject=sobject)
knowledge_article_id = article_data.get('KnowledgeArticleId')
# Perform the API call to retrieve the new draft ID
endpoint = f'/services/data/{sfdc_object.version}/knowledgeManagement/articleVersions/masterVersions'
response = sfdc_object.post(endpoint, {'articleId': knowledge_article_id})
# Return the full response or the draft ID
if not full_response:
response = response.get('id')
return response
[docs]
def publish_article(
sfdc_object,
article_id: str,
major_version: bool = True,
full_response: bool = False,
):
"""This function publishes a draft knowledge article as a major or minor version.
(`Reference <https://developer.salesforce.com/docs/atlas.en-us.knowledge_dev.meta/knowledge_dev/knowledge_REST_publish_master_version.htm>`_)
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param article_id: The Article ID to publish
:type article_id: str
:param major_version: Determines if the published article should be a major version (``True`` by default)
:type major_version: bool
:param full_response: Determines if the full API response should be returned (``False`` by default)
:type full_response: bool
:returns: A Boolean value indicating the success of the action or the API response from the PATCH request
:raises: :py:exc:`RuntimeError`
"""
# Define the payload for the API call
payload = {
"publishStatus": "Online"
}
if major_version:
payload['versionNumber'] = 'NextVersion'
# Perform the API call
endpoint = f'/services/data/{sfdc_object.version}/knowledgeManagement/articleVersions/masterVersions/{article_id}'
result = sfdc_object.patch(endpoint, payload)
# Return the appropriate value depending on if a full response was requested
if not full_response:
result = True if result.status_code == 204 else False
return result
[docs]
def publish_multiple_articles(sfdc_object, article_id_list: list, major_version: bool = True):
"""This function publishes multiple knowledge article drafts at one time.
(`Reference <https://developer.salesforce.com/docs/atlas.en-us.knowledge_dev.meta/knowledge_dev/actions_obj_knowledge.htm#publishKnowledgeArticles>`_)
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param article_id_list: A list of Article IDs to be published
:type article_id_list: list
:param major_version: Determines if the published article should be a major version (``True`` by default)
:type major_version: bool
:returns: The API response from the POST request
:raises: :py:exc:`RuntimeError`, :py:exc:`TypeError`, :py:exc:`ValueError`
"""
# Define the endpoint URI
endpoint = f'/services/data/{sfdc_object.version}/actions/standard/publishKnowledgeArticles'
# Ensure there is at least one article ID to publish
if not isinstance(article_id_list, list) or not isinstance(article_id_list[0], str):
raise TypeError('A list of Article ID strings must be provided in order to publish multiple articles.')
elif len(article_id_list) == 0:
# TODO: Change to more specific exception class (errors.exceptions.MissingRequiredDataError)
raise ValueError('No article ID strings were found in the article ID list variable.')
# Define the action to perform
action = 'PUBLISH_ARTICLE_NEW_VERSION' if major_version else 'PUBLISH_ARTICLE'
# Construct the payload
payload = {
"inputs": [
{
"articleVersionIdList": article_id_list,
"pubAction": action
}
]
}
# Perform the API call
return sfdc_object.post(endpoint, payload)
[docs]
def assign_data_category(sfdc_object, article_id: str, category_group_name: str, category_name: str):
"""This function assigns a single data category for a knowledge article.
(`Reference <https://itsmemohit.medium.com/quick-win-15-salesforce-knowledge-rest-apis-bb0725b2040e>`_)
.. versionadded:: 1.2.0
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param article_id: The ID of the article to update
:type article_id: str
:param category_group_name: The unique Data Category Group Name
:type category_group_name: str
:param category_name: The unique Data Category Name
:type category_name: str
:returns: The API response from the POST request
:raises: :py:exc:`RuntimeError`
"""
# Define the payload for the API call
payload = {
"ParentId": article_id,
"DataCategoryGroupName": category_group_name,
"DataCategoryName": category_name
}
# Perform the API call
endpoint = f'/services/data/{sfdc_object.version}/sobjects/Knowledge__DataCategorySelection'
return sfdc_object.post(endpoint, payload)
[docs]
def archive_article(sfdc_object, article_id: str):
"""This function archives a published knowledge article.
(`Reference <https://developer.salesforce.com/docs/atlas.en-us.knowledge_dev.meta/knowledge_dev/knowledge_REST_archive_master_version.htm>`_)
.. versionadded:: 1.3.0
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param article_id: The ID of the article to archive
:type article_id: str
:returns: The API response from the POST request
:raises: :py:exc:`RuntimeError`
"""
# Define the payload for the API call
payload = {
"publishStatus": "Archived"
}
# Perform the API call
endpoint = f'/services/data/{sfdc_object.version}/knowledgeManagement/articleVersions/masterVersions/{article_id}'
return sfdc_object.patch(endpoint, payload)
[docs]
def delete_article_draft(sfdc_object, version_id: str, use_knowledge_management_endpoint: bool = True):
"""This function deletes an unpublished knowledge article draft.
.. versionadded:: 1.4.0
:param sfdc_object: The instantiated SalesPyForce object
:type sfdc_object: class[salespyforce.Salesforce]
:param version_id: The 15-character or 18-character ``Id`` (Knowledge Article Version ID) value
:type version_id: str
:param use_knowledge_management_endpoint: Leverage the ``/knowledgeManagement/articleVersions/masterVersions/``
endpoint rather than the ``/sobjects/Knowledge__kav/`` endpoint
(``True`` by default)
:type use_knowledge_management_endpoint: bool
:returns: The API response from the DELETE request
:raises: :py:exc:`RuntimeError`
"""
if use_knowledge_management_endpoint:
endpoint = f'/services/data/{sfdc_object.version}/knowledgeManagement/articleVersions/masterVersions/{version_id}'
else:
endpoint = f'/services/data/{sfdc_object.version}/sobjects/Knowledge__kav/{version_id}'
return sfdc_object.delete(endpoint)