This content from the SAP Concur Community was machine translated for your convenience. SAP does not provide any guarantee regarding the correctness or completeness of this machine translated text. View original text custom.banner_survey_translated_text
I’m working on an integration that uploads receipt images to Concur and then associates each image with the correct expense entry. I can successfully retrieve expenses and upload receipt images - but I’m struggling with the final step: attaching the uploaded image to the expense.
Here’s what I’ve tried and observed so far:
curl -sS -H "Authorization: Bearer $TOKEN" \ "$BASE/expensereports/v4/users/$USER_ID/context/TRAVELER/reports/$REPORT_ID/expenses/$ENTRY_ID"
This returns the expected JSON with fields like receiptImageId: null and isImageRequired: true.
curl -X POST "https://us2.api.concursolutions.com/api/v3.0/expense/receiptimages" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: image/png" \ -F "file=@Receipt-20251008.png"
The upload succeeds and returns an ImageID like:
gWnJus1jbr9lkA4skeP4GfmF$s8aZMp1$sQHdZiqgKbNEdwJHCn27ESMXlE07Dozn4SgQ
I attempted several variants of the PATCH call, for example:
curl --location --request PATCH \ "https://us2.api.concursolutions.com/api/expense/expensereport/v4/users/$USER_ID/context/TRAVELER/reports/$REPORT_ID/expenses/$ENTRY_ID" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/merge-patch+json" \ --data-raw '{"receiptImageId": "gWnJus1jbr9lkA4skeP4GfmF$s8aZMp1$sQHdZiqgKbNEdwJHCn27ESMXlE07Dozn4SgQ"}'
and also tried the company-level route:
curl --location --request PATCH \ "https://us2.api.concursolutions.com/expensereports/v4/reports/$REPORT_ID/expenses/$ENTRY_ID" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/merge-patch+json" \ --data-raw '{"receiptImageId": "gWnJus1jbr9lkA4skeP4GfmF$s8dZMp1$sQHdZiqgKbNEdwJHCn27ESMXlE07Dozn4SgQ"}'
However:
The /expensereports/v4/... route returns 401 Unauthorized — “This endpoint is only accessible by a valid company JWT.”
The /api/expense/expensereport/v4/... route returns 403 Forbidden — even though my token has the expense.report.readwrite, receipts.writeonly, and IMAGE scopes.
This is the documentation I followed:
https://developer.concur.com/api-reference/expense/expense-report/v4.reports.html
…the PATCH operation seems valid for updating fields like receiptImageId. But the combination of 401/403 responses suggests this might depend on tenant enablement or API family configuration.
Questions
Any clarification, examples, or working patterns from others who have implemented this successfully would be hugely appreciated.