Submit Form API - Help Center | Oplix

Submit Form API

Overview

The /v2/submitform endpoint allows game studios to submit in-game forms (like feedback or bug reports) to the Oplix Engine using secure token-based authentication. This endpoint accepts multipart/form-data, allowing submissions to include structured form data, logs, device/game information, a screenshot (either as a file upload or a base64 string), and multiple additional file uploads (like crash logs or save files). Submissions are queued for asynchronous processing.

Note This endpoint utilizes a token exchange mechanism detailed in the authentication flow below.

URL:

  • Base Endpoint: https://backend.oplix.io/api/engine
  • Endpoint: POST /v2/submitform
  • HTTP Method: POST
  • Content-Type: multipart/form-data

Headers:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Authorization: Bearer YOUR_ACCESS_TOKEN
  • Authorization: Must contain a valid Oplix access token prefixed with Bearer .
  • Content-Type: Must be multipart/form-data to support the mix of text fields and potential file uploads. Ensure you include the correct boundary definition.

In-Game Authentication Flow

Here’s a clear flow you should follow to securely call the POST /v2/submitform endpoint:

1. Obtain Tokens (First Time Auth)

To retrieve your first Access Token and Refresh Token, call:

Endpoint: POST /auth/token

Request Body:

{
  "appId": "YOUR_APP_ID",
  "clientSecret": "YOUR_CLIENT_SECRET"
}

Response Example:

{
  "accessToken": "ACCESS_TOKEN",
  "refreshToken": "REFRESH_TOKEN",
  "expiresIn": 900
}

Important: Your client secret is a sensitive credential gained in the Team Settings page on the Oplix Dashboard. It must be kept secure and never exposed to end users. Each client secret is tied to your team account and can be revoked independently from your app ID if compromised.

2. Check Access Token Validity

Before calling /v2/submitform, ensure your Access Token is still valid:

  • Access Token expires in: 15 minutes
  • You can check expiry using the expiresIn field or by storing the expiry timestamp.

3. Refresh Token (When Access Token Expired)

If your Access Token has expired, use your stored Refresh Token to obtain a new one.

Endpoint: POST /auth/refresh

Request Body:

{
  "refreshToken": "YOUR_REFRESH_TOKEN"
}

Response Example:

{
  "accessToken": "NEW_ACCESS_TOKEN",
  "refreshToken": "NEW_REFRESH_TOKEN",
  "expiresIn": 900
}

Note: If the Refresh Token has expired (after 7 days) or is invalid, you must go back to Step 1 and re-authenticate. Implement safe retry logic with a max retry limit to prevent infinite loops and a potential IP block for excessive rate limit violations.

4. Make the API Call to Submit the Form

Once you have a valid Access Token, make a POST request to /v2/submitform using multipart/form-data.

HTTP Request Structure:

The request must be structured as multipart/form-data, containing various parts for the text fields and any files being uploaded.

POST /v2/submitform HTTP/1.1
Host: backend.oplix.io
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="appId"

YOUR_APP_ID
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="formData"

{"fields":[{"question":"What is your issue?","response":"Game crashes","exclude":false},{"question":"Email","response":"test@example.com","exclude":true}]}
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="logs"

["Log line 1", "Log line 2"]
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="formDescription"

Bug Report
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="device"

{"os_system":"Windows 11","cpu":"Intel Core i9","graphics_device_name":"NVIDIA RTX 4090","ram":"32GB"}
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="gameInfo"

{"quality_level":"Ultra","resolution":"3840x2160","fps":"120"}
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="templateType"

Bug Report
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="screenshot"; filename="screenshot.png"
Content-Type: image/png

<Binary data for screenshot.png>
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="files"; filename="crashlog.log"
Content-Type: text/plain

<Binary data for crashlog.log>
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="files"; filename="savegame.sav"
Content-Type: application/octet-stream

<Binary data for savegame.sav>
------WebKitFormBoundary7MA4YWxkTrZu0gW--

Form Data Fields:

The following fields should be included as distinct parts in your multipart/form-data request:

Request Fields

Field Name Type Required Max Size Notes
appId String Required The unique ID for the application submitting the form
formData JSON String Required Structured form data including questions, responses, and exclude flags
logs JSON String / Array Optional Array of log lines or single string containing log data
formDescription String Required Form category type (e.g., 'Bug Report', 'Feedback')
device JSON String Optional Detailed device info - mandatory fields required for hardware analytics
gameInfo JSON String Optional Game information - mandatory fields required for hardware analytics
templateType String Required Identifier for the form template being used
screenshot File / Base64 Optional 2MB Binary file upload (recommended) or base64-encoded data URI string. File upload takes priority if both provided
files File Upload(s) Optional 2MB each Up to 10 additional files (logs, save files, crash dumps). 5MB total ingress limit including screenshot

Token Expiry Summary

  • Access token expiration: 15 minutes
  • Refresh token expiration: 7 days

Form Data Structure with Exclude Flags:

The formData field should be a JSON string containing an object with a fields array. Each element in the array represents a form question/response and supports an exclude flag. If a question’s response is sensitive or should be excluded from Oplix AI engine processing, set exclude to true.

Example of formData JSON String:

{
    "fields": [
        {
            "question": "What is your issue?",
            "response": "The game crashes randomly after level 5.",
            "exclude": false
        },
        {
            "question": "What is your email?",
            "response": "hello@oplix.io",
            "exclude": true
        },
        {
            "question": "Additional comments",
            "response": "This started after the latest patch update.",
            "exclude": false
        }
    ]
}
  • exclude: true: This question and response will not be automatically processed by certain AI features but will still be stored and viewable.
  • exclude: false: The question and response will be processed as standard form data.

Device and Game Information Structure:

The device and gameInfo fields should be JSON strings containing key-value pairs. Certain keys are mandatory for hardware analytics (see below).

Example of device JSON String:

{
    "os_system": "Windows 10",
    "cpu": "Intel i7",
    "graphics_device_name": "NVIDIA GTX 1080",
    "ram": "16GB",
    "storage": "512GB SSD"
}

Example of gameInfo JSON String:

{
    "quality_level": "High",
    "resolution": "1920x1080",
    "fps": "60",
    "game_mode": "Multiplayer"
}

Screenshot Handling

The /v2/submitform endpoint supports including one screenshot per submission.

Methods:

  1. File Upload (Recommended): Include the screenshot as a file part named screenshot in your multipart/form-data request.
  2. Base64 String: Include a base64-encoded data URI string as the value for the text field named screenshot. Example: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA...".

Guidelines:

  • Priority: If both a screenshot file and a screenshot base64 field are sent, the file upload will be prioritized and processed.
  • Size Limit: Each uploaded file (including the screenshot if sent as a file) has a maximum size limit of 2MB. Base64 strings contribute to the overall field size limit. Exceeding these will result in errors.
  • Format: Common image formats like PNG or JPEG only

File Upload Handling

You can attach multiple additional files (up to 10) to your form submission, however the total allowable ingress for this endpoint is 5MB inclusive of the screenshot above.

Guidelines:

  1. Field Name: Each file must be sent as a file part named files in your multipart/form-data request.
  2. Size Limit: Each individual file must not exceed 2MB.
  3. Total Files: A maximum of 10 files (in addition to the optional screenshot file) can be uploaded per submission using the files field name.
  4. Content Types: Include the appropriate Content-Type for each file (e.g., text/plain, application/zip, application/octet-stream).

Required Device and Game Information Fields

NOTE - While the device and gameInfo fields allow for custom key-value pairs, certain keys are mandatory within their respective JSON strings to enable hardware analytics functionality in the Oplix Dashboard. These fields must be included with exact key names as specified below.

Mandatory Device Information Fields

The following fields must be included in the device JSON string:

Device Information Fields

Field Name Type Required Notes
cpu String Required CPU model name
fps String Required Current FPS value
os_system String Required Operating system version
device_model String Required Detailed device model
memory_usage Number Required Current memory usage (e.g., MB or GB as number)
network_type String Required Network connection type (e.g., 'WiFi', 'Ethernet', 'Cellular')
battery_level String Required Battery percentage (e.g., '95%')
battery_status String Required Charging status (e.g., 'Charging', 'Discharging', 'Full')
device_orientation String Required Device orientation (e.g., 'Landscape', 'Portrait')
system_memory_size String Required Total system memory (e.g., '16GB')
graphics_device_name String Required GPU name
graphics_device_type String Required Graphics API type (e.g., 'Direct3D11', 'Vulkan', 'Metal')
graphics_memory_size String Required GPU memory size (e.g., '8GB')
graphics_device_vendor String Required GPU manufacturer (e.g., 'NVIDIA', 'AMD', 'Intel')
graphics_device_version String Required Graphics driver version

Mandatory Game Information Fields

The following fields must be included in the gameInfo JSON string:

Game Information Fields

Field Name Type Required Notes
resolution String Required Display resolution (e.g., '1920x1080')
full_screen String Required Screen mode (e.g., 'True', 'False', 'Borderless')
render_path String Required Rendering pipeline (e.g., 'Deferred', 'Forward')
active_scene String Required Current game scene or level name
game_version String Required Game build version (e.g., '1.2.3', 'Build 456')
session_time String Required Current session duration (e.g., '0h 15m 30s')
shader_level String Required Shader complexity level (e.g., 'High', 'SM5')
quality_level String Required Graphics quality setting (e.g., 'Low', 'Medium', 'High', 'Ultra')
engine_version String Required Game engine version (e.g., 'Unity 2022.3.1f1', 'Unreal 5.1')
selected_language String Required Game language selected by player (e.g., 'en', 'fr', 'de')
player_preferences String Required Any key user preferences as a string (can be JSON stringified if complex)

Important Notes:

  • All specified mandatory fields must be included in your submission’s device and gameInfo JSON strings, even if some values are empty strings or placeholder values (e.g., “N/A”) if not applicable.
  • The key names must match exactly as shown above (case-sensitive).
  • You may include additional custom fields beyond these required ones within the same JSON strings.
  • Missing or incorrectly named mandatory fields will result in limited or unavailable functionality in the hardware analytics dashboard.

Response Structure:

The response indicates whether the submission was successfully accepted for processing. It does not wait for file uploads or backend processing to complete.

Success Response (200 OK):

Returned immediately after the submission is successfully added to the processing queue.

{
    "message": "Form submitted successfully",
    "submissionId": "c65b1ea0-362d-471a-b6e7-c8f853f160ea"
}
  • message: Confirms the submission was received.
  • submissionId: A unique identifier for this submission, useful for tracking or support purposes.
  • Note: URLs for uploaded files are not included in this immediate response, as processing happens asynchronously.

Error Responses:

Error Response (401 Unauthorized):

Occurs due to authentication or authorization issues:

  • Missing Authorization header.
  • Invalid token format (e.g., not starting with Bearer ).
  • Token signature verification failed.
  • Access token has expired (requires refresh).
  • Token has been revoked.
  • Incorrect token type used.
  • The appId provided in the body does not exist or is invalid.
{
  "error": "Token expired",
  "code": "TOKEN_EXPIRED"
}
{
    "error": "Invalid token",
    "code": "INVALID_TOKEN"
}
{
    "error": "Invalid app ID. The specified application could not be found."
    // Note: Status code will be 401 for this specific App ID lookup failure
}

Error Response (400 Bad Request):

  • Missing required fields like appId.
  • Invalid JSON format for formData, logs, device, or gameInfo fields.
  • formData structure is invalid (e.g., not parsable into the expected array format).
{
    "error": "Missing app_id parameter"
}
{
    "error": "Invalid JSON format for field 'formData'"
}
{
    "error": "Invalid formData format: Expected an array"
}

Error Response (413 Payload Too Large):

  • May occur if the total request size, exceeds server limits. The specific error message might vary based on what limit was hit.
{
    "error": "File too large"
}

Error Response (429 Too Many Requests):

  • Rate limit exceeded.
{
    "error": "Too many requests",
    "retryAfter": 58, // Optional: Indicates seconds to wait
    "message": "Rate limit exceeded. Please try again later."
}

Error Response (500 Internal Server Error):

  • An unexpected error occurred on the server during initial request handling or queueing.
{
    "error": "Internal server error during processing"
}

Suggested Player Experience

  • Implement robust client-side handling for multipart/form-data uploads, including progress indicators for larger files (screenshot, additional files).
  • Consider potential network interruptions or upload failures. Implement retry logic on the client-side if an upload fails before the API call is made, or if the API call itself fails due to network issues.
  • Request timeouts should still be considered, especially for players on slower connections uploading large files, even though the server responds quickly. The upload itself still needs to complete.

Additional Information:

  • CORS Support: The API includes CORS headers to allow cross-origin requests from web-based game clients.
  • App ID Validation: Ensure that the appId is valid and corresponds to a registered application associated with your team.
  • Secret Keys: Revoked client secrets immediately invalidate all associated tokens. Each secret key is uniquely tied to your team within Oplix and can be used with any of your team’s apps.