Yazam API Reference
Two complementary REST APIs for file security filtering. Choose the interface that best fits your integration architecture.
Overview
Yazam API provides two distinct REST APIs under the same server. Both share the same authentication system and response format - but differ in their state model and workflow.
Authentication
Both APIs share the same four authentication methods. Apply the appropriate method on every request as required by the server configuration.
Obtain a token via GET /logon (see Endpoints), then supply it in every request.
Authorization: Bearer <TOKEN>
Username and password encoded in Base64.
Authorization: Basic <base64(user:pass)>
Integrated Windows authentication via default network credentials (e.g. UseDefaultCredentials in .NET).
No authentication header required. Must be explicitly enabled on the server.
Optionally enabled. The client must present a valid certificate whose Subject is pre-configured on the server.
Encryption & TLS
https://.GET /logon
/composite) and the Native API (/native). Use it to obtain a Bearer token when token-based authentication is configured on the server.Authenticates the caller and returns a Bearer token for subsequent requests. Credentials are passed in HTTP headers.
Request Headers
| Header | Type | Required | Description |
|---|---|---|---|
| User | string | Required | Username for authentication. |
| Password | string | Required | Password for authentication. |
Response
Returns a token string to be used as Authorization: Bearer <TOKEN> in all subsequent calls to both APIs.
Overview
The Composite API handles file filtering in a single multipart/form-data POST request. It is stateless - no session is maintained between calls, making it fully compatible with load balancers and horizontal scaling.
Endpoints
The primary endpoint. Submits one or more files for security filtering in a single synchronous request. Body must be multipart/form-data.
Body Parts
| Part Name | Type | Required | Description |
|---|---|---|---|
| file | file | Repeatable | File(s) to filter. Both filename and filename* are supported in Content-Disposition. May appear multiple times. |
| policy | string | Required | Filtering policy name recognized by the engine. |
| client | string | Optional | Identifier of the requesting entity. |
| relation | string | Optional | Software submitting the files. A number 194-255 or a predefined name. |
| password | string | Repeatable | Password(s) for decrypting protected streams. |
| history | string | Optional | Enable history and define its content in the summary. |
| report | string | Optional | Destination for storing the filtering report server-side. |
| return | string | Up to ×2 | Which files to return and the summary format. See return parameter. |
| comment | string | Optional | Arbitrary text associated with a submitted file. Must use the same filename/filename* parameter in its Content-Disposition header as the corresponding file part. |
Response
Returns multipart/form-data with a summary part (the filtering result) and optional file parts (returned files with original filename*).
Returns a JSON array of all defined filtering policy names.
[ "DefaultPolicy", "StrictPolicy", "EmailPolicy" ]
Retrieves shared server-side configuration.
Overwrites shared server-side configuration for the given resource.
The Return Parameter
The return parameter can appear up to twice in a single request - once to specify which files to return, and once to set the summary format.
File Selection
Summary Format
return=modified and return=json together to get filtered files and a machine-readable summary in one response.Response Summary Structure
The summary may include the following fields and elements. Any tag except the root may appear multiple times at the same level.
Root - <Result>
| if multiple.<File> - Data Stream (only recursive element - can contain itself)
Blocked, Modified, or Intact.<Annotation> - Information about the stream (does not alter its status)
<Event> - Modification of the stream (not including embedded ones)
<Block> - Rejection of the stream
<File> - Embedded Data Stream
<File> is the only recursive element - it can contain itself. Embedded streams follow the exact same structure as the parent <File> element described above. See also: ... (see above) in the Word reference.<Result> may appear multiple times at the same level.Response Summary Examples
Generic examples of the filtering summary in both JSON and XML formats.
{
"Date": "2025-08-26 11:49:24Z",
"Policy": "POLICY_NAME",
"Client": "CLIENT",
"ProductVersion": "VERSION",
"Antivirus": "ANTIVIRUS_ENGINE",
"Files": [
{
"Name": "FILE1_NAME",
"Size": "129144",
"Path": "C:\\Temp\\FILE1",
"Status": "Modified",
"Partial": "0",
"Protected": "0",
"Duration": "31",
"History": "251",
"Results": [
{
"Type": "Reencoded",
"History": "352",
"Description": "File was regenerated.",
"Kind": "Modification"
}
]
},
{
"Name": "FILE2_NAME",
"Size": "108",
"Path": "C:\\Temp\\FILE2",
"Status": "Modified",
"Partial": "1",
"Protected": "0",
"Duration": "0",
"History": "252",
"Files": [
{
"Name": "EMBEDDED_FILE",
"Size": "43",
"Path": "C:\\Temp\\EMBEDDED_TMP",
"Status": "Blocked",
"Partial": "0",
"Protected": "0",
"Duration": "0",
"Type": "Script",
"History": "253",
"Results": [
{
"Type": "LinkSetPossible",
"History": "353",
"Description": "Navigation can be manipulated.",
"Kind": "Rejection"
}
]
}
]
}
],
"Results": [
{ "Description": "ANTIVIRUS_ENGINE", "Kind": "Antivirus" }
]
}
<Result Date="2025-08-26 14:11:22Z" Policy="POLICY_NAME" Client="CLIENT" ProductVersion="VERSION" Antivirus="ANTIVIRUS_ENGINE"> <Antivirus>ANTIVIRUS_ENGINE</Antivirus> <File Name="FILE1_NAME" Size="129144" Path="C:\Temp\FILE1" Status="Modified" Partial="0" Protected="0" Duration="15" History="254"> <Event Type="Reencoded" History="354">File was regenerated.</Event> </File> <File Name="FILE2_NAME" Size="108" Path="C:\Temp\FILE2" Status="Modified" Partial="1" Protected="0" Duration="0" History="255"> <File Name="EMBEDDED_FILE" Size="43" Path="C:\Temp\EMBEDDED_TMP" Status="Blocked" Partial="0" Protected="0" Duration="0" Type="Script" History="256"> <Block Type="LinkSetPossible" History="355">Navigation can be manipulated.</Block> </File> </File> </Result>
C# (.NET)
using (MultipartFormDataContent job = new MultipartFormDataContent { { new StringContent("<POLICY_NAME>"), "policy" }, { new StringContent("<CLIENT>"), "client" }, { new StringContent("modified"), "return" } }) { job.Add(new StreamContent(File.OpenRead("<PATH_TO_FILE1>")), "file", "<FILE1_NAME>"); job.Add(new StreamContent(File.OpenRead("<PATH_TO_FILE2>")), "file", "<FILE2_NAME>"); using (HttpClient hc = new HttpClient(new HttpClientHandler(), true) { BaseAddress = new Uri(@"https://<HOST>/composite/"), Timeout = Timeout.InfiniteTimeSpan }) using (HttpResponseMessage response = await hc.SendAsync( new HttpRequestMessage(HttpMethod.Post, "") { Content = job }, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)) { response.EnsureSuccessStatusCode(); MultipartMemoryStreamProvider result = await response.Content .ReadAsMultipartAsync(new MultipartMemoryStreamProvider()).ConfigureAwait(false); foreach (HttpContent part in result.Contents) { if (part.Headers.ContentDisposition.Name == "summary") Console.WriteLine("Summary: \n" + part.ReadAsStringAsync().ConfigureAwait(false)); else if (part.Headers.ContentDisposition.Name == "file") using (Stream file = await part.ReadAsStreamAsync().ConfigureAwait(false)) { Console.WriteLine("Modified file: " + part.Headers.ContentDisposition.FileNameStar + ", size: " + file.Length); // process file ... } } } }
Python
import os, requests from requests_toolbelt.multipart import decoder import pyrfc6266 path1 = r"<PATH_TO_FILE1>" path2 = r"<PATH_TO_FILE2>" fn1 = os.path.basename(path1) fn2 = os.path.basename(path2) with open(path1, "rb") as f1, open(path2, "rb") as f2: r = requests.post( "https://<HOST>/composite/", data=[ ("policy", "<POLICY_NAME>"), ("client", "<CLIENT>"), ("return", "modified"), ("return", "json"), ], files=[ ("file", (fn1, f1, "application/octet-stream")), ("file", (fn2, f2, "application/octet-stream")), ], # Add authentication here if required ) multipart_data = decoder.MultipartDecoder.from_response(r) for part in multipart_data.parts: cd = part.headers.get(b"Content-Disposition", b"").decode("ascii", "ignore") disp, params = pyrfc6266.parse(cd) name = next(p for p in params if p.name == "name").value if name == "summary": print(part.text) elif name == "file": print(next(p for p in params if p.name == "filename*").value)
Overview & Sessions
The Native API maintains a server-side session per client interaction. The session corresponds to a running instance of the filtering engine. Unlike the Composite API, files are submitted and retrieved one at a time across multiple HTTP calls.
Session Identity
On the first POST the server assigns a session ID and returns it in both a Set-Cookie header and a X-Session-ID response header. Include this ID on all subsequent calls.
Naming Streams
Every stream must be identified by a filename with the correct extension - the engine uses the extension to determine the stream type.
Content-Name: report.docx/native?name=report.docxSession Workflow
A complete session follows these five steps in order. Always end with DELETE to free server resources immediately.
201 Created.200 OK.policy and optional parameters. The engine filters all submitted streams synchronously. Optionally stream progress via progress=comet. Returns HTTP 200 OK.200 OK.204 No Content. Do not skip this step.Endpoints
Submits a raw data stream to the current session. The first call (no session ID) creates a new session.
Request Headers / Query Params
| Parameter | Type | Required | Description |
|---|---|---|---|
| Content-Name or ?name= | string | Required | URL-encoded filename with extension. Reusing an existing name appends a chunk to that stream. |
| X-Session-ID or cookie | string | 2nd+ call | Omit on the very first request to start a new session. Required on all subsequent calls. |
Request Body
Raw binary stream content (no multipart wrapping).
Response
Triggers synchronous filtering of all streams in the current session. Parameters can be sent as JSON, application/x-www-form-urlencoded, or query string properties.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| policy | string | Required | Filtering policy recognized by the engine. |
| client | string | Optional | Entity originating the process. Defaults to the authenticated user. |
| relation | string | Optional | Software submitting the files. A number 194-255 or a predefined name. |
| password | string | Repeatable | One or more passwords for decrypting encrypted streams. |
| history | string | Optional | Enable history and define its content. Overrides server defaults. |
| report | string | Optional | Destination path for storing the filtering report server-side. |
| return | string | Optional | Output format: xml, json, html, or csv. |
| progress | string | Optional | Set to comet to stream progress line-by-line in the response body, followed by an empty line then the final result. Requires ResponseHeadersRead in .NET. |
Response
Filtering summary in the requested format. With progress=comet: progress lines → empty line → final result.
/native?policy=MyPolicy&return=json.Retrieves a single filtered stream from the session. Call once per stream after the PUT filtering step.
Request Headers / Query Params
| Parameter | Type | Required | Description |
|---|---|---|---|
| Content-Name or ?name= | string | Name or Path | Filename used during submission. |
| Content-Path or ?path= | string | Name or Path | Physical path from the filtering response. Allows direct retrieval of any stream including embedded ones. |
Response
Raw binary content of the filtered stream. 200 OK.
Terminates the session and immediately frees all server-side resources. Always call DELETE when done.
Response
204 No Content - session deleted, no body.
DELETE is strongly recommended to release server resources immediately.Returns a JSON array of all defined policy names. Equivalent to GET /composite/policies.
DELETE the session afterwards.GET retrieves, POST sets shared server-side configuration.
DELETE when finished. Note: the Native API uses POST to set configuration, unlike the Composite API which uses PUT.
Status Codes
| 200 OK | Request succeeded. Body contains the requested data. |
| 201 Created | Request has succeeded with a new filtering session created and its ID generated. |
| 204 No Content | Request succeeded with no body (e.g. DELETE). |
| 400 Bad Request | Required parameter missing or invalid - missing session ID, stream name, policy, unknown output format, or invalid URL path. |
| 404 Not Found | Session is busy (serving another concurrent request) or expired (timed out or deleted). |
| 405 Method Not Allowed | HTTP method not permitted on this endpoint. |
| 500 Server Error | Filtering engine failed. Consult the response headers for details. |
C# (.NET)
Complete single-file session including optional real-time progress streaming via comet mode.
using (HttpClient hc = new HttpClient( new HttpClientHandler { Credentials = new NetworkCredential("<user>", "<pass>") }, true) { BaseAddress = new Uri(@"https://<host>:<port>/native/") }) { // 1. Submit the file hc.DefaultRequestHeaders.Add("Content-Name", WebUtility.UrlEncode("<file name>")); (await hc.PostAsync("", new StreamContent(File.OpenRead("<file path>")))).EnsureSuccessStatusCode(); // 2. Filter with progress streaming HttpResponseMessage result = await hc.SendAsync( new HttpRequestMessage(HttpMethod.Put, "") { Content = new FormUrlEncodedContent(new[] { new KeyValuePair<string,string>("policy", "<policy>"), new KeyValuePair<string,string>("client", "<client>"), new KeyValuePair<string,string>("progress", "comet") }) }, HttpCompletionOption.ResponseHeadersRead); result.EnsureSuccessStatusCode(); using (TextReader rdr = new StreamReader(await result.Content.ReadAsStreamAsync())) { while (true) { string p = await rdr.ReadLineAsync(); if (string.IsNullOrEmpty(p)) break; Console.WriteLine(p); } Console.WriteLine(await rdr.ReadToEndAsync()); // filtering result } // 3. Retrieve filtered file using (var resp = await hc.GetStreamAsync(""), out_ = File.Create("<output>")) await resp.CopyToAsync(out_); // 4. Clean up session await hc.DeleteAsync(""); }
using (HttpClient hc = new HttpClient( new HttpClientHandler { Credentials = new NetworkCredential("<user>", "<pass>") }, true) { BaseAddress = new Uri(@"https://<host>:<port>/native/") }) { // 1. Submit the file hc.DefaultRequestHeaders.Add("Content-Name", WebUtility.UrlEncode("<file name>")); (await hc.PostAsync("", new StreamContent(File.OpenRead("<file path>")))).EnsureSuccessStatusCode(); // 2. Filter var result = await hc.PutAsync("", new FormUrlEncodedContent(new[] { new KeyValuePair<string,string>("policy", "<policy>"), new KeyValuePair<string,string>("client", "<client>") })); result.EnsureSuccessStatusCode(); Console.WriteLine(await result.Content.ReadAsStringAsync()); // 3. Retrieve filtered file using (var resp = await hc.GetStreamAsync(""), out_ = File.Create("<output>")) await resp.CopyToAsync(out_); // 4. Clean up session await hc.DeleteAsync(""); }
Python
import os from urllib.parse import quote import requests base_url = "http://127.0.0.1:8008/native" def filter_file(session, file_path, policy, client="", return_format="JSON"): file_name = os.path.basename(file_path) encoded_name = quote(file_name) # Submit the file with open(file_path, "rb") as file: response = session.post( base_url, data=file, headers={"Content-Name": encoded_name} ) response.raise_for_status() # Filter the file data = { "policy": policy, "client": client, "return": return_format } response = session.put(base_url, json=data) response.raise_for_status() print(response.text) # Retrieve filtered file altered_file_path = f"altered_{file_name}" response = session.get(f"{base_url}?name={encoded_name}") response.raise_for_status() with open(altered_file_path, "wb") as file: file.write(response.content) return altered_file_path file_paths = [ r"C:\path\to\file1.jpg", r"C:\path\to\file2.xml" ] session = requests.Session() # Optional: add authentication to the session if required # (for example Basic auth, Bearer token, or client certificate). try: for file_path in file_paths: altered_file_path = filter_file(session, file_path, "full") print(f"Altered file saved as: {altered_file_path}") finally: response = session.delete(base_url) response.raise_for_status()
Postman Guide
Recommended steps for setting up Postman to test both APIs.
1 - Create an Environment
base_url → https://<YOUR_HOST> policy → <POLICY_NAME> client → postman-test bearer_token → (auto-populated by logon request)
2 - Obtain a Bearer Token
Method: GET · URL: {{base_url}}/logon · Headers: User + Password
const token = pm.response.text(); if (token) pm.environment.set("bearer_token", token.trim());
3 - Composite POST Request
Method: POST · URL: {{base_url}}/composite · Auth: Bearer {{bearer_token}} · Body: form-data
| Key | Type | Value |
|---|---|---|
| policy | Text | {{policy}} |
| client | Text | {{client}} |
| return | Text | modified |
| return | Text | json |
| file | File | Select file → repeat row for each file |
return row and enter the format value - both will be sent in the same request.4 - Native API Session
For the Native API, create a Postman Collection with 4 requests in sequence:
Content-Name: filename.ext. Save the returned X-Session-ID to environment.policy, client, optionally progress=comet. Header: X-Session-ID: {{session_id}}.?name=filename.ext. Header: X-Session-ID: {{session_id}}. Save response as binary.X-Session-ID: {{session_id}}. Always run this - add it as a Collection-level post-request script.