API Reference
Log In
API Reference

File Upload to S3

Step 1 of 2 for adding files to an applicant profile.

Recent Requests
Log in to see full request history
TimeStatusUser Agent
Retrieving recent requests…
LoadingLoading…

This is part 1 of uploading files to an applicant. In this documentation, you'll be uploading to your account's S3.

❗️

Secure data access is required

If your call returns with Secure data access is required, you'll need to contact [email protected] to enable your account to access secure data.

Part 2 is to link the file to the applicant. See next article on Link Applicant to Files in S3 to complete the upload to the applicant.

Optional attribution

Set attribute_to_applicant to true to show the applicant as the actor for the upload in the History panel. Omit this option to attribute the upload to the caller. A Fountain One OAuth token attributes it to the Hire user with the token's email: your own user for a personal key, the integration's user for an integration key. A Hire API key, or a token whose email matches no Hire user, attributes it to the account owner. A request that sends both a Hire API key and a token is attributed by the Hire API key.

import json
import xml.etree.ElementTree
import mimetypes
import os
import requests

HOST="api.fountain.com"
API_KEY="K-9NB9DkxU7NdrB9eRBHCA"
APPLICANT="6d0d9434-2817-4b96-9ad4-e33a7f2a0adb"
FILENAME="dog.jpg"
UPLOAD_FILE=(FILENAME, open(FILENAME, 'rb'), mimetypes.guess_type(FILENAME)[0])
UPLOAD_KEY="test"

UPLOAD_URL="https://%s/v2/applicants/%s/secure_documents/upload" % (HOST, APPLICANT)
LINK_UPLOAD_URL="https://%s/v2/applicants/%s/secure_documents/link_upload" % (HOST, APPLICANT)

HEADERS = { 'X-ACCESS-TOKEN': API_KEY }

upload_response = requests.post(UPLOAD_URL, headers=HEADERS)
upload_response_json = json.loads(upload_response.text)
form_data = upload_response_json['form_data']
form_data['Content-type'] = ""

s3_upload_response = requests.post(upload_response_json['url'], data=form_data, files={'file': UPLOAD_FILE})

s3_upload_response_xml = xml.etree.ElementTree.fromstring(s3_upload_response.text)
s3_filename = s3_upload_response_xml.find("Key").text

finish_upload_data = {
    'key': UPLOAD_KEY,
    's3_key': s3_filename,
    'size': os.path.getsize(FILENAME),
}
finish_upload_response = requests.post(LINK_UPLOAD_URL, headers=HEADERS, json=finish_upload_data)
print(finish_upload_response)
using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using System.Xml.XPath;

var localFilePath = @"/Users/userName/Downloads/the_file.png";
var host = "https://us-2.fountain.com";
var apiKey = "your_api_key";
var applicantId = "29345e1b-6224-467a-964c-da077ebed994";

// Open file stream to the local file on disk
var fileStream = new FileStream(localFilePath, FileMode.Open);

// Create a new HttpClient with default headers for the API key
var hireClient = new HttpClient();
hireClient.DefaultRequestHeaders.Add("X-ACCESS-TOKEN", apiKey);

// Get an upload URL so that the file can be uploaded to the applicant
var urlResponse = await hireClient.PostAsync($"{host}/api/v2/applicants/{applicantId}/secure_documents/upload", null);
var presignedPayload = await urlResponse.Content.ReadFromJsonAsync<Payload>(new JsonSerializerOptions { PropertyNameCaseInsensitive = true, PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower });

// Upload the file to the presigned URL with a multipart form
var formData = new MultipartFormDataContent();

// Copy the form data from the presignedPayload to the formData
// This has the x-amz-signature, target s3 key and other fields from a presigned upload payload
foreach (var item in presignedPayload.FormData)
{
  formData.Add(new StringContent(item.Value), item.Key);
}
formData.Add(new StringContent(""), "Content-Type"); // required due to a content validation rule
formData.Add(new StreamContent(fileStream), "file", Path.GetFileName(localFilePath));

// POST the file to the presigned URL (S3)
var s3Client = new HttpClient();
var uploadResponse = await s3Client.PostAsync(presignedPayload.Url, formData);
// You would want to use ReadAsStreamAsync here and pass it directly to XPathDocument but
// this makes it easy to log the response if there was a problem
var textResponse = await uploadResponse.Content.ReadAsStringAsync();
if (uploadResponse.StatusCode != HttpStatusCode.Created)
{
  Console.WriteLine("Error uploading file");
  Console.WriteLine(textResponse);
  return;
}
var xmlDocument = new XPathDocument(new StringReader(textResponse));
var navigator = xmlDocument.CreateNavigator();
var keyNode = navigator.SelectSingleNode("/PostResponse/Key");
if (keyNode is null) {
  Console.WriteLine("Unexpected response from S3");
  Console.WriteLine(textResponse);
  return;
}

// Now link the uploaded file residing on S3 to the applicant
var linkResponse = await hireClient.PostAsJsonAsync($"{host}/api/v2/applicants/{applicantId}/secure_documents/link_upload", new LinkPayload
{
  Key = "some_file", // this is the data key you are uploading the file to
  S3Key = keyNode.Value,
  Size = fileStream.Length.ToString()
}, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower });
if (linkResponse.StatusCode != HttpStatusCode.OK)
{
  Console.WriteLine($"Error linking file: {linkResponse.StatusCode}");
  return;
}

public readonly struct LinkPayload
{
  public string Key { get; init; } // data key
  public string S3Key { get; init; } // s3 key
  public string Size { get; init; }
}

public readonly struct Payload
{
    public string Url { get; init; }
    public string Host { get; init; }
    public Dictionary<string, string> FormData { get; init; }
    public int MinSize { get; init; }
    public int MaxSize { get; init; }
    public bool OnlyImages { get; init; }
    public string Type { get; init; }
}
Path Params
string
required
Body Params
string

path/to/file.upload

boolean

When true, attributes the upload to the applicant (rather than the caller) in the History panel.

Responses

Language
Credentials
Header
LoadingLoading…
Response
Click Try It! to start a request and see the response here! Or choose an example:
application/json