0

Upload documents to be attached to applications

by
Published Oct 17, 2025

Uploading files to this endpoint enables you to attach them to an application later. Please keep in mind that the auto-generated code on the right-hand side when adding a file from this tool should only be considered as a guide, and might not work when copy-pasting in your code directly. Please refer to the documentation for the language/library you are using on how to upload a multipart-form-data file.

Script personio Verified

The script

Submitted by hugo697 Bun
Verified 235 days ago
1
//native
2
type Personio = {
3
	clientId: string
4
	clientSecret: string
5
}
6
type Base64 = string
7
/**
8
 * Upload documents to be attached to applications
9
 * Uploading files to this endpoint enables you to attach them to an application later. Please keep in mind that the auto-generated code on the right-hand side when adding a file from this tool should only be considered as a guide, and might not work when copy-pasting in your code directly. Please refer to the documentation for the language/library you are using on how to upload a multipart-form-data file.
10
 */
11
export async function main(
12
	auth: Personio,
13
	X_Company_ID: string,
14
	body: {
15
		file: {
16
			base64: Base64
17
			type:
18
				| 'image/png'
19
				| 'image/jpeg'
20
				| 'image/gif'
21
				| 'application/pdf'
22
				| 'appication/json'
23
				| 'text/csv'
24
				| 'text/plain'
25
				| 'audio/mpeg'
26
				| 'audio/wav'
27
				| 'video/mp4'
28
			name: string
29
		}
30
	},
31
	X_Personio_Partner_ID?: string,
32
	X_Personio_App_ID?: string
33
) {
34
	const url = new URL(`https://api.personio.de/v1/recruiting/applications/documents`)
35

36
	const formData = new FormData()
37
	for (const [k, v] of Object.entries(body)) {
38
		if (v !== undefined) {
39
			if (['file'].includes(k)) {
40
				const { base64, type, name } = v as {
41
					base64: Base64
42
					type: string
43
					name: string
44
				}
45
				formData.append(
46
					k,
47
					new Blob([Uint8Array.from(atob(base64), (m) => m.codePointAt(0)!)], {
48
						type
49
					}),
50
					name
51
				)
52
			} else {
53
				formData.append(k, String(v))
54
			}
55
		}
56
	}
57
	const response = await fetch(url, {
58
		method: 'POST',
59
		headers: {
60
			...(X_Personio_Partner_ID ? { 'X-Personio-Partner-ID': X_Personio_Partner_ID } : {}),
61
			...(X_Personio_App_ID ? { 'X-Personio-App-ID': X_Personio_App_ID } : {}),
62
			'X-Company-ID': X_Company_ID,
63
			Authorization: 'Bearer ' + (await getOAuthToken(auth, 'https://api.personio.de/oauth2/token'))
64
		},
65
		body: formData
66
	})
67
	if (!response.ok) {
68
		const text = await response.text()
69
		throw new Error(`${response.status} ${text}`)
70
	}
71
	return await response.json()
72
}
73

74
async function getOAuthToken(auth: Personio, tokenUrl: string): Promise<string> {
75
	const params = new URLSearchParams({
76
		grant_type: 'client_credentials',
77
		client_id: auth.clientId,
78
		client_secret: auth.clientSecret
79
	})
80

81
	const response = await fetch(tokenUrl, {
82
		method: 'POST',
83
		headers: {
84
			Authorization: 'Basic ' + btoa(`${auth.clientId}:${auth.clientSecret}`),
85
			'Content-Type': 'application/x-www-form-urlencoded'
86
		},
87
		body: params.toString()
88
	})
89

90
	if (!response.ok) {
91
		const text = await response.text()
92
		throw new Error(`OAuth token request failed: ${response.status} ${text}`)
93
	}
94

95
	const data = await response.json()
96
	return data.access_token
97
}
98