We noticed that JavaScript is disabled in your browser. We suggest enabling it for a better experience.
We noticed you're using an older version of Internet Explorer. We suggest you update to the latest version for a better experience.
Skip to main content

Example code for accessing the OpenForms API

OpenForms has phased out support for version 1, 2, and 3 API keys.

As of July 2024, we no longer offer integrations built with these keys. 

If you're building a new integration today, make sure you're using a version 4 or later API key. If your organization uses integrations built on older version API keys, they will no longer work and you will need to create a version 4 key and update your integration. 

Not sure how to get started? Contact support and we'll point you in the right direction.   

In this example, we will use version 4 of the OpenForms API to:

  • Retrieve applicant names and CV attachments from a hypothetical job application form.

  • Push the names and uploads to a third party system.

  • Update the form responses on the OpenForms server with an identifier and status from the third party system.

All code examples are in C#, and any lines of code beginning with // are instructional text. If you'd like to view the complete working code for this project, you can find it here


  • A form called Job Application Form

  • Two fields within the form - a Text field, “name,” and a FileUpload field, “CV”

  • At least one submission

  • A version 4 API key with appropriate permissions

Calls Used

  • GET - /api/v4/forms

  • GET - /api/v4/responses

  • GET - /api/v4/files/{fileId}/download

  • PATCH - /api/v4/responses/{responseId}

Code walkthrough

We start by defining our API key and OpenForms API base URL according to our region (US or AU).

private const string myApiKey = "YOUR_API_KEY";
private const string baseOpenFormsApiUrl = "https://api.au.openforms.com";

Now that we have these, we need a way to contact and authenticate with the API. In this example, we’ll be using 2 types of requests, GET and PATCH. For these, we can use the following methods:

private static async Task<dynamic> GetApiData(string endpoint, string param)
using (HttpClient client = new HttpClient())
// Send OpenForms API key as part of the 'X-API-KEY' header.
client.DefaultRequestHeaders.Add("X-API-KEY", myApiKey);

// Send the request and get a response.
string response = await client.GetStringAsync(baseOpenFormsApiUrl + endpoint + param);

return JObject.Parse(response);

private static async Task PatchApiData(string endpoint, string param)

using (HttpClient client = new HttpClient())
// Send OpenForms API key as part of the 'X-API-KEY' header.
client.DefaultRequestHeaders.Add("X-API-KEY", myApiKey);

HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("PATCH"), baseOpenFormsApiUrl + endpoint + param) { Content = null };

// Send the request and get a response.
await client.SendAsync(request);

As you can see, authentication with OpenForms works by providing our API Key in the X-API-KEY request header with each request.

Now that we have a way to contact the OpenForms API, we can start using it. First, we want to use the forms endpoint to get details about our job application form.

// The form name we want to get data from.
string formName = "Job Application Form";

// Send a request to get the details of the given form and include the form structure.
dynamic forms = await GetApiData("/api/v4/forms", "?keyword=" + HttpUtility.UrlEncode(formName) + "&loadStructure=true");

// Extract the form of interest.
dynamic form = forms.items[0];

The piece of code above will send a request to the forms endpoint, while using the keyword and loadStructure parameters in order to limit our results to just our form (assuming the name is unique), and to get some details of our form. Once executed, the form object will contain all the properties of our form, as described in the API swagger.

Now that we have our form, we can proceed to get responses from it. We will use the responses endpoint using the formId and loadAnswers parameters to limit our results to just our job application form and to include the answers to those responses.

// Send a request to get the responses of the given form using the form ID including the answers.
dynamic responses = await GetApiData("/api/v4/responses", "?formId=" + form.id + "&loadAnswers=true");

Once this code is executed, our responses object with have all the response details, including answers, to our job application form.

Having retrieved these responses, we want to go through them and extract some piece of information that will be sent to a third-party system. In this example, we will get the applicant’s name and their uploaded CV file for each response.

We will then send items to our third-party system, which will return a unique identifier. Lastly, we will update the OpenForms submissions to include this unique identifier for cross-referencing.

// Go through all the responses and collect the data needed.
foreach (dynamic response in responses.items)
// Get the value of the field called 'Name'.
string applicantName = GetFieldAnswer(form, response, "Name").value.Value;
// Download the file uploaded to the field 'CV'.
FileInfo cvFile = DownloadFile("/api/v4/files/", GetFieldAnswer(form, response, "CV").files[0]);

// Send our data to a third-party system and get an identifier back.
string externalSystemId = SendDataToThirdPartySystem(applicantName, cvFile);

// Cleanup the downloaded file.

// Update the OpenForms response with the third-party system ID that we got and status 'Received'.
await PatchApiData("/api/v4/responses/" + response.id, "?externalId=" + externalSystemId + "&externalStatus=Received");

The above code snippet starts by looping through all responses. It starts by retrieving the applicant’s name from each response, using a helper method. Response answers are linked to forms by the elementId attribute, and this helper method has a simple logic to map a response to a form, in order to return the answer for a given field.

private static dynamic GetFieldAnswer(dynamic form, dynamic response, string targetField)
// Go through the form sections.
foreach (dynamic section in form.sections)
// Go through the form fields.
foreach (dynamic field in section.fields)
// We found the field on the form.
if (targetField.Equals(field.name.Value))
// Go through the response answers.
foreach (dynamic answer in response.answers)
// We found the corresponding answer.
if (answer.elementId.Value == field.elementId.Value)
return answer;

We then use another helper method to download the submitted file into a temporary location by calling the files endpoint and returning a reference to that file. The following piece of code is dependent on permissions to the system’s temporary files directory.

private static FileInfo DownloadFile(string endpoint, dynamic file)
using (WebClient client = new WebClient())
client.Headers.Add("X-API-KEY", myApiKey);
string downloadPath = Path.GetTempPath() + file.fileName;
string downloadUrl = baseOpenFormsApiUrl + endpoint + file.fileId + "/download";

client.DownloadFileAsync(new Uri(downloadUrl), downloadPath);
while (client.IsBusy) { }

return new FileInfo(downloadPath);

Now that we have both the applicant’s name and their uploaded file, we can send them to our third-party system. In this example, we have a dummy method that simulates some processing and returns a random unique identifier. In your application, you will need to write your own logic on how this data will be sent to your third-party system.

private static string SendDataToThirdPartySystem(string applicantName, FileInfo cvFile)

// Here you will write your logic to send this data to your third-party system and optionally receive an identifier back.
return Guid.NewGuid().ToString();

Once the data is submitted to the third-party system, and we get a unique identifier back, we can delete the file that we just downloaded, and proceed to update the OpenForms response with that identifier as well as a status of our choice.

In our case, we simply set the status to ‘Received’ to indicate that the job application has been received by the third-party system. We are doing this by calling the responses endpoint again using the externalId and externalStatus parameters. For this example, we are not validating the OpenForms response to confirm that the update was successful, but this is something you can optionally do in your own application.

Was this helpful?