0

Upload direct cost attachment

by
Published Oct 17, 2025

The *Upload direct cost attachment* endpoint uploads an attachment and assigns it against a specific `directCostId`. [Direct costs](https://docs.codat.io/accounting-api#/schemas/DirectCost) are business expenses that don't impact Accounts Payable. **Integration-specific behaviour** For more details on supported file types by integration see [Attachments](https://docs.codat.io/accounting-api#/schemas/Attachment).

Script codat Verified

The script

Submitted by hugo697 Bun
Verified 235 days ago
1
//native
2
type Codat = {
3
	encodedKey: string
4
}
5
type Base64 = string
6
/**
7
 * Upload direct cost attachment
8
 * The *Upload direct cost attachment* endpoint uploads an attachment and assigns it against a specific `directCostId`.
9

10
[Direct costs](https://docs.codat.io/accounting-api#/schemas/DirectCost) are business expenses that don't impact Accounts Payable.
11

12
**Integration-specific behaviour**
13

14
For more details on supported file types by integration see [Attachments](https://docs.codat.io/accounting-api#/schemas/Attachment).
15

16
 */
17
export async function main(
18
	auth: Codat,
19
	companyId: string,
20
	connectionId: string,
21
	directCostId: string,
22
	body: {
23
		file: {
24
			base64: Base64
25
			type:
26
				| 'image/png'
27
				| 'image/jpeg'
28
				| 'image/gif'
29
				| 'application/pdf'
30
				| 'appication/json'
31
				| 'text/csv'
32
				| 'text/plain'
33
				| 'audio/mpeg'
34
				| 'audio/wav'
35
				| 'video/mp4'
36
			name: string
37
		}
38
	}
39
) {
40
	const url = new URL(
41
		`https://api.codat.io/companies/${companyId}/connections/${connectionId}/push/directCosts/${directCostId}/attachment`
42
	)
43

44
	const formData = new FormData()
45
	for (const [k, v] of Object.entries(body)) {
46
		if (v !== undefined) {
47
			if (['file'].includes(k)) {
48
				const { base64, type, name } = v as {
49
					base64: Base64
50
					type: string
51
					name: string
52
				}
53
				formData.append(
54
					k,
55
					new Blob([Uint8Array.from(atob(base64), (m) => m.codePointAt(0)!)], {
56
						type
57
					}),
58
					name
59
				)
60
			} else {
61
				formData.append(k, String(v))
62
			}
63
		}
64
	}
65

66
	const response = await fetch(url, {
67
		method: 'POST',
68
		headers: {
69
			Authorization: `Basic ${auth.encodedKey}`
70
		},
71
		body: formData
72
	})
73
	if (!response.ok) {
74
		const text = await response.text()
75
		throw new Error(`${response.status} ${text}`)
76
	}
77
	return await response.text()
78
}
79