POST /files/ endpoint returning 500 for form_media uploads (v2 API)

Hey all,

I’ve been building a Power Automate flow to push updated CSV media files (used with select_one_from_file/pulldata) to a few of our projects on kf.kobotoolbox.org, and I’ve hit a wall on the file upload endpoint specifically.

POST /api/v2/assets/{uid}/files/ returns a plain 500 every time I try to create a new form_media file, regardless of how I build the request. Here’s what I’ve ruled out so far:

Tried three completely separate implementations - a hand-built multipart request in Power Automate, .NET’s HttpClient/MultipartFormDataContent via PowerShell, and curl.exe. All three fail identically.
Tried a CSV and a JPG, so it’s not content-specific.
Tried against three different assets in our account, so it’s not one particular project.
GET and DELETE on the same /files/ endpoint work fine with the same token. PATCH on /deployment/ also works fine. It’s just the POST that’s broken.
The exact same files upload without any issue through the web UI (Project Settings > Media).

The response is just Kobo’s own generic Django error page (Server error (500), “something went wrong when trying to process your request”), not a JSON validation error, so I’m assuming it’s an unhandled exception on your end rather than something I’m sending wrong - especially since request format, file type and asset all vary but the result doesn’t.

Request body I’m sending (multipart/form-data): file_type=form_media, description={filename}, content=@{file}. Straight out of the API docs’ own example.

Server is kf.kobotoolbox.org, and I have three asset UIDs I’m happy to share if it helps you look into a specific case.

Has anyone else run into this recently, or is there something obviously missing from what I’m sending?

Thanks

Hi @pcranley Welcome back to the forum.
I believe the following topicay help with your question.

Thanks again to @osmanburcu for sharing this approach.

Thanks for this, @jorcabrera. I think it’s solving a different problem though. I understand this general approach could be adapted to avoid API v2’s POST entirely, but as Osman highlights, it comes with its own risks and limitations, including storing data via a public GitHub-hosted file. That might be fine for adding an extra option to an “other” list, but the risks are higher when the data involved is sensitive.

My main concern is that POST /files/ itself is returning a 500 regardless of file type, content, or client (tested with a hand-built multipart request, .NET’s HttpClient, and curl), and all fail identically. This solution doesn’t touch that, since it never calls that endpoint at all. Still hoping someone can take a look at the actual upload endpoint.

hi @pcranley,

I tried what you are trying to achieve for couple of month but i couldn’t find any possible work around.

The problem with the Kobo is you can’t provide authentication when you would like to get data from a link and also the link must containt the file name and the extention so Sharepoint or drive is out of option. If your data has senstive information, i wouldn’t recomend this solution as well.

Thanks @osmanburcu, genuinely inspired work!
Update: I found a solution to my issue. Both POST methods I tried were failing due to a missing metadata/filename field. Adding metadata: {“filename”: “…”} fixed the multipart route entirely (credit to the working script in How to replace csv media file or delete existing media file using kobo v2 API - #13 by uchechinedu01 ). Separately, the base64 method needed the base64 string prefixed as data:;base64,… rather than bare (per kobotoolbox/kpi#5316). With these fixes, both upload methods now work cleanly and I can successfully POST my CSV for lookup. POSTing in case this saves someone else the same debugging loop.