The “help” I can offer is that if you go to the API Reference, there is nothing other than a CURL example. Cooking this recipe is up to you, or in this case, I’ll let o3 do it for you:
Below is a compact, drop-in Java 17 example that performs the documented HTTP POST to update a single file’s attributes inside an existing vector store, without touching any (undocumented) SDK helpers.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Map;
/**
* Updates the "attributes" map on a vector-store file via the raw REST API.
*
* Prerequisites
* - Java 17+ (for java.net.http.HttpClient)
* - The environment variable OPENAI_API_KEY must be present.
*
* Usage
* VectorStoreFileUpdater.update(
* "<YOUR_VECTOR_STORE_ID>",
* "<YOUR_FILE_ID>",
* Map.of("origin_filename", "sales_q3_2025.pdf") // <= up to 16 key/value pairs
* );
*/
public final class VectorStoreFileUpdater {
private static final String OPENAI_API_KEY =
System.getenv("OPENAI_API_KEY"); // Bearer token from env
private static final HttpClient HTTP =
HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
/**
* Executes the POST /v1/vector_stores/{vector_store_id}/files/{file_id} request.
*/
public static void update(
String vectorStoreId,
String fileId,
Map<String, Object> attributes) throws Exception {
if (OPENAI_API_KEY == null || OPENAI_API_KEY.isBlank()) {
throw new IllegalStateException("OPENAI_API_KEY env var is missing");
}
// ---- 1. Build JSON request body ----------------------------------------------------------
// The REST endpoint expects: {"attributes": { "key1": "value1", ... }}
StringBuilder json = new StringBuilder("{\"attributes\":{");
boolean first = true;
for (Map.Entry<String, Object> e : attributes.entrySet()) {
if (!first) json.append(',');
first = false;
json.append('"').append(escape(e.getKey())).append("\":");
Object v = e.getValue();
json.append(v instanceof Number || v instanceof Boolean
? v.toString()
: "\"" + escape(v.toString()) + '"');
}
json.append("}}");
byte[] bodyBytes = json.toString().getBytes(StandardCharsets.UTF_8);
// ---- 2. Compose the request --------------------------------------------------------------
String url = String.format(
"https://api.openai.com/v1/vector_stores/%s/files/%s",
vectorStoreId, fileId);
HttpRequest request = HttpRequest.newBuilder(URI.create(url))
.header("Authorization", "Bearer " + OPENAI_API_KEY)
.header("Content-Type", "application/json")
.timeout(Duration.ofSeconds(30))
.POST(HttpRequest.BodyPublishers.ofByteArray(bodyBytes))
.build();
// ---- 3. Fire & read response -------------------------------------------------------------
HttpResponse<String> response = HTTP.send(request, HttpResponse.BodyHandlers.ofString());
// ---- 4. Handle simple success/error cases -----------------------------------------------
if (response.statusCode() / 100 == 2) { // 2xx → success
System.out.println("Updated file attributes successfully:");
System.out.println(response.body()); // full JSON response
} else {
throw new RuntimeException(
"OpenAI API call failed: HTTP " + response.statusCode() + "\n" + response.body());
}
}
// --- small helper for JSON string escaping (no external libs) -------------------------------
private static String escape(String s) {
return s.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\b", "\\b")
.replace("\f", "\\f")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t");
}
}
How to integrate
-
Choose the call-site where your earlier client.vectorStores().files().update(updateParams) lived.
-
Instantiate your attributes map (max 16 pairs, each value ≤ 512 chars):
Map<String, Object> attrs = Map.of(
"origin_filename", "sales_q3_2025.pdf",
"processed", true,
"page_count", 42
);
-
Invoke:
VectorStoreFileUpdater.update(vectorStoreId, fileId, attrs);
-
A successful call prints the updated file object; any non-2xx status surfaces as a runtime exception for easy upstream handling.
This native approach sidesteps the undocumented SDK path, mirrors the official HTTP spec exactly, and is reusable anywhere in your codebase.
The little “helper” that AI imagined for string sanitation is unnecessary - the key and values are Unicode UTF-8 and can take any valid code point as a “character” up to the 512 char length, though you probably want to think about the query you’ll be writing against the stored values.
I can’t see what you are passing as input, but the request body is ultimately a JSON string with proper escapes mainly for double-quotes.