Update an Answer Set Programmatically

API Version: v2.0
Method: GET, PUT, PATCH
Endpoint: /WorkItems/{workItemId}/AnswerSet/Content

You can update an answer set externally and return it to Advance using the API. This is useful when you need to add data from an external source, such a reference number from a third-party application.

Overview

When data is added to a work item, Advance saves this in the form of HotDocs Answer XML. Typically new information is added to an answer set through an interview with a user, but it is also possible to update an answer set externally and return this data to HotDocs.

Take care when sending HotDocs Answer XML to a work item that has existing work item versions. If there are existing answers which you wish to retain, ensure you keep them in the replacement answer file. 

Workflow

1. (Optional) Retrieve the existing answer set

If you want to edit an existing answer set, use the GET endpoint to download the answer set in HotDocs Answer XML format.

2. Edit or update the answer set

Modify the XML in your application or process. Validate the answer set against the HotDocs Answer Set schema.

3. Return the updated answer set

  • Use PUT to replace the entire answer set.
  • Use PATCH to update specific answers (overlay update).

When answer sets can be updated

You can update an answer set when the current work item version is in one of these states:

State Update Allowed
Saved Yes
Completed Yes
PostProcessingFailed Yes

Attempting to update the answer set in any other state will result in an error.

Requirements for successful updates

To ensure your changes are applied correctly:

  • Update the Answer XML before creating a new work item version or
  • Wait until the work item version is completed.

This ensures that your updated answer set can be attached to the new work item version and that the Core Assembly Session (CAS) is not locked.

To update an answer set

To update the entire answer set (PUT)

Use this method when you want to replace the full answer set with a complete Answer XML document:

  • PUT /WorkItems/{workItemId}/AnswerSet/Content

This endpoint replaces the entire answer set. Make sure your XML includes all the answers you wish to retain, not just any new ones.

To update only specific answers (PATCH)

If you only need to update a subset of answers you can use the PATCH endpoint:

  • PATCH /WorkItems/{workItemId}/AnswerSet/Content

This endpoint performs an overlay update, meaning:

  • you only provide the answers you want to change, and
  • any other existing answers remain unchanged.

This is the preferred method for small or incremental changes.

There are additional considerations if you are updating image values in your answer set.

Code Example

using System.Text;
using System.Text.Json;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
namespace HotDocsAdvance.Help.CodeExamples.AnswerSets;
// Code assumes a valid token has been obtained.
/// <summary>
///  This class demonstrates how to update an Answer Set in HotDocs Advance using the PATCH endpoint.
/// </summary>
/// <remarks>
/// The relevant endpoint is a PATCH found on the swagger documentation under the workitem section,
/// and the answerSet sub resource.
/// </remarks>
/// <param name="httpClient"> Standard framework HttpClient. </param>
/// <param name="baseAdvanceApiUrl"> Base URL for your environment and tenancy's HD Advance API. No version required.
/// E.g. For a swagger documentation found on https://sometenancy.mycompanydomain.com/api/rest/documentation/index.html
/// The base url would be: https://tenancy.yourorganization.com/api
/// </param>
/// <param name="token"> A working HD Advance API access token. See the relevant documentation as to how to get a token.</param>
/// <param name="xsdStrings"> A collection of  key (xml namespace) and value (xml schema (XSD) as strings) pairs to use
/// while validating the answers. </param>
public class UpdateAnswerSetCodeExample(
    HttpClient httpClient,
    string baseAdvanceApiUrl,
    string token,
    ICollection<KeyValuePair<string, string>> xsdStrings)
{
    // These two lines define XML namespaces to be reused across the code.
    private static readonly XNamespace hd = "http://www.hotdocs.com/schemas/answer_set/2017";
    private static readonly XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
    /// <summary>
    /// This is a placeholder class, that serves a purpose only for this code example. It is meant to contain and expose
    /// result of the operation when successful.
    /// </summary>
    public class PatchAnswerSetResponse
    {
        public ICollection<string> UnresolvedImageReferences { get; set; } = [];
    }
    public async Task<PatchAnswerSetResponse?> UpdateAnswerSetAsync(Guid workItemId)
    {
        // Creates the full URI for HD Advance API 2.0 AnswerSet PATCH, endpoint (overlay).
        // Please note the correct usage of forward slashes, or utilize another method to construct the full patch URI.
        var patchAnswersUri = new Uri(new Uri(baseAdvanceApiUrl),
            $"rest/v2/WorkItems/{workItemId}/AnswerSet/Content");
        var constructedAnswerXml = PrepareNewAnswerSet();
        if(!ValidateAgainstSchemas(new XDocument(constructedAnswerXml)))
        {
            throw new InvalidOperationException("The answer set is not valid.");
        }
        
        // Constructs the request message, with the provided answer XML as content and the relevant access token.
        using var requestContent =
            new StringContent(constructedAnswerXml.ToString(), Encoding.UTF8, "application/xml");
        using var requestMessage = new HttpRequestMessage(HttpMethod.Patch, patchAnswersUri);
        requestMessage.Headers.Add("Authorization", $"Bearer {token}");
        requestMessage.Content = requestContent;
        // Executes the requests, enforces a successful response (HTTP status 2xx),
        // and returns the response content parsed in the appropriate format.
        var response = await httpClient.SendAsync(requestMessage);
        response.EnsureSuccessStatusCode(); // Handle relevant error scenarios accordingly. E.g. Http Codes: 401, 403, 404, 409, etc.
        return JsonSerializer.Deserialize<PatchAnswerSetResponse>(await response.Content.ReadAsStringAsync());
    }
    private static XElement PrepareNewAnswerSet()
    {
        // The root element of an HD answer set, including the namespace.
        var root = new XElement(hd + "answerSet");
        // Adding the namespaces for compatibility.
        root.Add(new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"));
        root.Add(new XAttribute(XNamespace.Xmlns + "hd", "http://www.hotdocs.com/schemas/answer_set/2017"));
        // Adding standard HD answer set attributes.
        root.Add(new XAttribute("version", "2.0"));
        root.Add(new XAttribute("title", ""));
        // Adding the answers themselves.
        root.Add(GetTextAnswerWithValue("FirstName", null));
        root.Add(GetTextAnswerWithValue("LastName", "Thomson"));
        root.Add(GetTextAnswerWithValue("FamilyName", "Rodriguez"));
        return root;
    }
    private static XElement GetTextAnswerWithValue(string variableName, string? value)
    {
        // This method creates an answer with the correct namespaces, values and variable names.
        var answer = new XElement(hd + "textAnswer", new XAttribute("name", variableName));
        answer.Add(value is null
            ? new XElement(hd + "value", new XAttribute(xsi + "nil", true))
            : new XElement(hd + "value", value));
        return answer;
    }
    private bool ValidateAgainstSchemas(XDocument answersXml)
    {
        bool isXmlValid = true;
        var schemaSet = new XmlSchemaSet();
        foreach ((string targetNamespace, string xsd) in xsdStrings)
        {
            schemaSet.Add(targetNamespace, XmlReader.Create(new StringReader(xsd)));
        }
        answersXml.Validate(schemaSet, (o, e) => { isXmlValid = false; });
        return isXmlValid;
    }
}

Next Steps