Trouble when sending POST through API

I am trying to make a program to automatically sort my steam screenshots into respective folders, but am having trouble with uploading from c# currently it just returns "Field Name Missing" and 400 (bad request) in short, i double checked all the document required arguments, and have deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, isFavorite, assetData there is no errors in the console, and it seems if i change the filename for assetData to anything else, it gives an error for unsupported type, so i belive this is correct code (its sloppy because i was trying to get it to work before cleaning it) Init code
new Task(async () => {
await ImmichAPI.POSTHeaders("http://10.0.0.63:8089/api/assets?apiKey=<API KEY>", "C:\\Users\\dokid\\OneDrive\\Pictures\\Screenshots\\Screenshot 2025-05-18 210444.png", new Dictionary<string, string> {
// { "assetData", Convert.ToHexString(System.IO.File.ReadAllBytes("C:/Users/dokid/OneDrive/Pictures/1153105160697020576.webp")) },
// { "assetData", "atsrwqtr"},
{ "deviceAssetId", "web-Screenshot 2025-05-18 210444.png-1747624855719" },
{ "deviceId", "WEB" },
{ "fileCreatedAt", "2025-05-19T03:20:55.718Z" },
{ "fileModifiedAt", "2025-05-19T03:20:55.718Z" },
{ "isFavorite", "false" },
});
}).Start();
new Task(async () => {
await ImmichAPI.POSTHeaders("http://10.0.0.63:8089/api/assets?apiKey=<API KEY>", "C:\\Users\\dokid\\OneDrive\\Pictures\\Screenshots\\Screenshot 2025-05-18 210444.png", new Dictionary<string, string> {
// { "assetData", Convert.ToHexString(System.IO.File.ReadAllBytes("C:/Users/dokid/OneDrive/Pictures/1153105160697020576.webp")) },
// { "assetData", "atsrwqtr"},
{ "deviceAssetId", "web-Screenshot 2025-05-18 210444.png-1747624855719" },
{ "deviceId", "WEB" },
{ "fileCreatedAt", "2025-05-19T03:20:55.718Z" },
{ "fileModifiedAt", "2025-05-19T03:20:55.718Z" },
{ "isFavorite", "false" },
});
}).Start();
Post Code
public static async Task<string> POSTHeaders(Uri url, string path, Dictionary<string, string> postValues) {
MultipartFormDataContent content = new MultipartFormDataContent();
var fileContent = new StreamContent(File.OpenRead(path));
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
content.Add(new FormUrlEncodedContent(postValues));
content.Add(fileContent, "assetData", "Screenshot 2025-05-18 210444.png");


using (HttpResponseMessage response = await client.PostAsync(
url,
content)) {
string responseString = await response.Content.ReadAsStringAsync();
Form1.Log($"{responseString}");
return responseString;
}
}
public static async Task<string> POSTHeaders(Uri url, string path, Dictionary<string, string> postValues) {
MultipartFormDataContent content = new MultipartFormDataContent();
var fileContent = new StreamContent(File.OpenRead(path));
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
content.Add(new FormUrlEncodedContent(postValues));
content.Add(fileContent, "assetData", "Screenshot 2025-05-18 210444.png");


using (HttpResponseMessage response = await client.PostAsync(
url,
content)) {
string responseString = await response.Content.ReadAsStringAsync();
Form1.Log($"{responseString}");
return responseString;
}
}
21 Replies
Immich
Immich3w ago
:wave: Hey @DokiDerg, Thanks for reaching out to us. Please carefully read this message and follow the recommended actions. This will help us be more effective in our support effort and leave more time for building Immich :immich:. References - Container Logs: docker compose logs docs - Container Status: docker ps -a docs - Reverse Proxy: https://immich.app/docs/administration/reverse-proxy - Code Formatting https://support.discord.com/hc/en-us/articles/210298617-Markdown-Text-101-Chat-Formatting-Bold-Italic-Underline#h_01GY0DAKGXDEHE263BCAYEGFJA Checklist I have... 1. :ballot_box_with_check: verified I'm on the latest release(note that mobile app releases may take some time). 2. :blue_square: read applicable release notes. 3. :blue_square: reviewed the FAQs for known issues. 4. :blue_square: reviewed Github for known issues. 5. :ballot_box_with_check: tried accessing Immich via local ip (without a custom reverse proxy). 6. :blue_square: uploaded the relevant information (see below). 7. :blue_square: tried an incognito window, disabled extensions, cleared mobile app cache, logged out and back in, different browsers, etc. as applicable (an item can be marked as "complete" by reacting with the appropriate number) Information In order to be able to effectively help you, we need you to provide clear information to show what the problem is. The exact details needed vary per case, but here is a list of things to consider: - Your docker-compose.yml and .env files. - Logs from all the containers and their status (see above). - All the troubleshooting steps you've tried so far. - Any recent changes you've made to Immich or your system. - Details about your system (both software/OS and hardware). - Details about your storage (filesystems, type of disks, output of commands like fdisk -l and df -h). - The version of the Immich server, mobile app, and other relevant pieces. - Any other information that you think might be relevant. Please paste files and logs with proper code formatting, and especially avoid blurry screenshots. Without the right information we can't work out what the problem is. Help us help you ;) If this ticket can be closed you can use the /close command, and re-open it later if needed.
DokiDerg
DokiDergOP3w ago
as reassurance, i captured it in wireshark, and the headers definitly send correctly (in my opinion)
No description
Mraedis
Mraedis3w ago
Wild guess: it doesn't like spaces in the name
DokiDerg
DokiDergOP3w ago
odd, i copied most of the data from the website sending the api, just to check if i typed it wrong, ill give it a try
Mraedis
Mraedis3w ago
My guess is wild for a reason :p
DokiDerg
DokiDergOP3w ago
nah its very fair, sanity check type of thing unfortunately, after creating a file with no spaces, it did the same thing
Mraedis
Mraedis3w ago
a little confused as to where your upload is happening
DokiDerg
DokiDergOP3w ago
File.OpenRead(path) its turning it into binary, to send along with post data then it gets added in content.Add(fileContent, "assetData", "...")
Mraedis
Mraedis3w ago
Did you check out the API docs?
DokiDerg
DokiDergOP3w ago
i read this one https://immich.app/docs/api/upload-asset/ made sure i send every single REQUIRED item, apikey also is sent
Mraedis
Mraedis3w ago
I'm reading:
-H 'Content-Type: multipart/form-data' \
-H 'Accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-H 'Accept: application/json' \
But I don't see those with yours wait the json one is, just not hte multipart
DokiDerg
DokiDergOP3w ago
its part of c# MultipartFormDataContent it automatically adds that stuff i double checked in wireshark to make sure it added that kinda stuff, i can check again to see if it matches what yours has content type may not have been added, which is weird because i thought i read it was, let me see if it fixes it well now it gives boundry not found, so thats progress, not sure if its backward or forward progress, but its something
Mraedis
Mraedis3w ago
interesting what if you remove the content type and change accept to */*
DokiDerg
DokiDergOP3w ago
"deviceAssetId must be a string", "deviceAssetId should not be empty", "deviceId must be a string", "deviceId should not be empty", "fileCreatedAt must be a Date instance", "fileCreatedAt should not be empty", "fileModifiedAt must be a Date instance", "fileModifiedAt should not be empty" i get all these errors so i think that worked? and i just have something else wrong maybe
Mraedis
Mraedis3w ago
something unescaped or such :p
Mraedis
Mraedis3w ago
not sure if wireshark visualization or something else going on here
No description
DokiDerg
DokiDergOP3w ago
weird
DokiDerg
DokiDergOP3w ago
looking at uploading from the website, definitly a wireshark thing
No description
DokiDerg
DokiDergOP3w ago
good catch though i gotta head to bed, its getting pretty late my time, thank you for the help, i think you put me on the right path to solve it, and hopefully i can tomorrow, because it seems like its not sending headers now after doing a custom content type so if i can send the headers correctly, then it should work
schuhbacca
schuhbacca3w ago
Here's a working c# example to upload a file to my server:
var filePath = "mytestfile.jpeg";
var apiUrl = "https://mydomain.com/api/assets";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "my-api-key");

using var form = new MultipartFormDataContent();
using var fileStream = File.OpenRead(filePath);
var fileContent = new StreamContent(fileStream);
fileContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");

form.Add(fileContent, "assetData", Path.GetFileName(filePath));
form.Add(new StringContent("deviceAssetId123"), "deviceAssetId");
form.Add(new StringContent("deviceId123"), "deviceId");
form.Add(new StringContent(DateTime.UtcNow.ToString("o")), "fileCreatedAt");
form.Add(new StringContent(DateTime.UtcNow.ToString("o")), "fileModifiedAt");

var response = await client.PostAsync(apiUrl, form);
var result = await response.Content.ReadAsStringAsync();

Console.WriteLine($"Response: {response.StatusCode}");
Console.WriteLine(result);
var filePath = "mytestfile.jpeg";
var apiUrl = "https://mydomain.com/api/assets";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "my-api-key");

using var form = new MultipartFormDataContent();
using var fileStream = File.OpenRead(filePath);
var fileContent = new StreamContent(fileStream);
fileContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");

form.Add(fileContent, "assetData", Path.GetFileName(filePath));
form.Add(new StringContent("deviceAssetId123"), "deviceAssetId");
form.Add(new StringContent("deviceId123"), "deviceId");
form.Add(new StringContent(DateTime.UtcNow.ToString("o")), "fileCreatedAt");
form.Add(new StringContent(DateTime.UtcNow.ToString("o")), "fileModifiedAt");

var response = await client.PostAsync(apiUrl, form);
var result = await response.Content.ReadAsStringAsync();

Console.WriteLine($"Response: {response.StatusCode}");
Console.WriteLine(result);
DokiDerg
DokiDergOP3w ago
thank you, that worked amazinginly, ill need to modifiy it to keep the file creation time from the original, but thats not that difficult to do

Did you find this page helpful?