Photos go straight to EMS’s private storage, not through the API, and EMS then processes them exactly like uploads in the dashboard: it checks the file really is an image, straightens it, strips hidden metadata such as location, resizes it and makes a thumbnail. You need a key with the media:write scope. JPEG, PNG, GIF and WebP are accepted, up to 20 MB.
1

Start the upload

Tell EMS about the file: its name, type and exact size in bytes.
2

Post the file to storage

Send a multipart/form-data POST to upload.url with every upload.fields entry first and the file last, in a field named file. Don’t add your API key here; the signed fields are the permission. The form works for 15 minutes, for this one file only.
The type and size must match what you declared in step 1, or storage refuses the file.
3

Complete it and wait

Then poll every second or two until status is ready or failed:
Use item.id as a speaker’s photo_media_id. If it failed, error says why (for example, the file isn’t really an image).