Cardholders forget receipts. This tutorial builds a small helper, such as a chat bot or a phone shortcut, that lists a person's purchases that still need one and attaches a photo to the right purchase. It works with any member's own API key, so each person only ever sees their own card.
1. List what needs a receipt attention.mine lists purchases on the caller's own cards that still need a receipt, newest first.
cURL Node.js Python
Copy curl -G https://app.getoatmilk.com/api/v1/accounting/attention.mine \
-H "Authorization: Bearer $OATMILK_API_KEY" \
--data-urlencode 'limit=10' const response = await fetch ( "https://app.getoatmilk.com/api/v1/accounting/attention.mine?limit=10" , {
headers : {
Authorization : `Bearer ${process.env.OATMILK_API_KEY}` ,
},
});
const { data, error } = await response. json ();
if (! response. ok) throw new Error ( `${error.code}: ${error.message}` );
console. log ( data); import os
import requests
response = requests. get (
"https://app.getoatmilk.com/api/v1/accounting/attention.mine" ,
headers={
"Authorization" : f"Bearer {os.environ['OATMILK_API_KEY']}" ,
},
params={
"limit" : "10" ,
},
timeout= 30 ,
)
payload = response. json ()
if not response. ok:
raise RuntimeError ( f"{payload['error']['code']}: {payload['error']['message']}" )
print ( payload[ "data" ]) attention.mine response Copy {
"data" : {
"total" : 1 ,
"cards" : [
"4242"
],
"items" : [
{
"id" : "7f0f6c1e-1c1f-4b5e-9c8d-2f5e8e3c1a10" ,
"merchant" : "Synthetic Office Supply" ,
"date" : "2026-09-18" ,
"currency" : "CAD" ,
"amountMinor" : "4520" ,
"lastFour" : "4242"
}
],
"nextCursor" : null
}
} 2. Attach a photo to one purchase Send the photo with receiptFor set to the purchase's ID. Oatmilk compares the receipt with that purchase only, and refuses it if the purchase no longer needs one.
cURL Node.js Python
Copy curl https://app.getoatmilk.com/api/v1/accounting/uploads.inline \
-H "Authorization: Bearer $OATMILK_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"filename": "receipt.jpg",
"mimeType": "image/jpeg",
"contentBase64": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA==",
"receiptFor": "7f0f6c1e-1c1f-4b5e-9c8d-2f5e8e3c1a10"
}' const response = await fetch ( "https://app.getoatmilk.com/api/v1/accounting/uploads.inline" , {
method : "POST" ,
headers : {
Authorization : `Bearer ${process.env.OATMILK_API_KEY}` ,
"Content-Type" : "application/json" ,
"Idempotency-Key" : crypto. randomUUID (),
},
body : JSON. stringify ({
"filename" : "receipt.jpg" ,
"mimeType" : "image/jpeg" ,
"contentBase64" : "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA==" ,
"receiptFor" : "7f0f6c1e-1c1f-4b5e-9c8d-2f5e8e3c1a10"
}),
});
const { data, error } = await response. json ();
if (! response. ok) throw new Error ( `${error.code}: ${error.message}` );
console. log ( data); import os
import uuid
import requests
response = requests. post (
"https://app.getoatmilk.com/api/v1/accounting/uploads.inline" ,
headers={
"Authorization" : f"Bearer {os.environ['OATMILK_API_KEY']}" ,
"Idempotency-Key" : str ( uuid. uuid4 ()),
},
json={
"filename" : "receipt.jpg" ,
"mimeType" : "image/jpeg" ,
"contentBase64" : "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA==" ,
"receiptFor" : "7f0f6c1e-1c1f-4b5e-9c8d-2f5e8e3c1a10" ,
},
timeout= 30 ,
)
payload = response. json ()
if not response. ok:
raise RuntimeError ( f"{payload['error']['code']}: {payload['error']['message']}" )
print ( payload[ "data" ]) 3. Or forward it by email Some people would rather forward the email receipt. inbox.address gives the address to forward to; anything sent there from the person's own verified email is filed as theirs.
cURL Node.js Python
Copy curl https://app.getoatmilk.com/api/v1/accounting/inbox.address \
-H "Authorization: Bearer $OATMILK_API_KEY" const response = await fetch ( "https://app.getoatmilk.com/api/v1/accounting/inbox.address" , {
headers : {
Authorization : `Bearer ${process.env.OATMILK_API_KEY}` ,
},
});
const { data, error } = await response. json ();
if (! response. ok) throw new Error ( `${error.code}: ${error.message}` );
console. log ( data); import os
import requests
response = requests. get (
"https://app.getoatmilk.com/api/v1/accounting/inbox.address" ,
headers={
"Authorization" : f"Bearer {os.environ['OATMILK_API_KEY']}" ,
},
timeout= 30 ,
)
payload = response. json ()
if not response. ok:
raise RuntimeError ( f"{payload['error']['code']}: {payload['error']['message']}" )
print ( payload[ "data" ]) Pause the reminders While your helper does the chasing, a person can pause Oatmilk's own reminder emails for up to 90 days with chase.preferences.update.