API Documentation
Configure Arguox to POST photo metadata to your own endpoint. No authentication required on Arguox's side — you own the URL, you own the data.
Overview
Arguox sends a single POST request to a user-configured HTTPS URL every time a photo is captured. The request body is application/json and includes all enabled metadata fields, the action type, and the captured image encoded as Base64.
There is no Arguox API key, account, or server involved. You supply the endpoint; Arguox delivers the payload.
Setup
Open Settings → API Config
Tap the gear icon on the Camera screen to open Settings, then scroll to the API Config section.
Choose a button mode
Select Single for one CAPTURE button or Dual for separate IN and OUT buttons, each with its own endpoint.
Enter your endpoint URL(s)
Paste your HTTPS endpoint URL. For Dual mode, set separate URLs for IN and OUT actions.
Enable Auto-upload on Capture
When toggled on, Arguox POSTs immediately after every capture. When off, uploads queue for manual retry.
Configure metadata fields (optional)
In Settings → Metadata, toggle which fields appear in the payload: Location, Date & Time, Device Info.
Endpoint
POST {your-configured-url}
Content-Type: application/json Your endpoint must accept a POST request with a JSON body. No special headers are added by Arguox beyond Content-Type.
http:// URLs. Your endpoint must serve a valid TLS certificate. Payload Fields
Only fields that are enabled in Settings appear in the payload. Fields omitted when offline are noted below.
Core (always present)
| Field | Description |
|---|---|
| action | "CAPTURE", "IN", or "OUT" — depends on button mode. |
| imageBase64 | The captured image encoded as Base64. Decode and save as JPEG on your server. |
| imageFileName | Suggested filename, e.g. IMG_20260514_103007.jpg. |
Time Toggle in Settings
| Field | Description |
|---|---|
| timestamp | ISO 8601 UTC timestamp from the device clock. |
| date | Local date, e.g. 2026-05-14. |
| time | Local time in 12-hour or 24-hour format depending on user setting. |
| timezone | IANA timezone name, e.g. Etc/UTC. |
| unixTimestamp | Unix epoch seconds. |
Location Toggle in Settings Omitted offline
| Field | Description |
|---|---|
| latitude | GPS latitude. Precision configurable in Settings. |
| longitude | GPS longitude. |
| street | Reverse-geocoded street name via Nominatim. |
| barangay | Sub-district / barangay if available. |
| city | City or municipality. |
| province | Province, state, or region. |
| country | Full country name. |
| countryCode | ISO 3166-1 alpha-2 (two-letter country code). |
| postalCode | Postal / ZIP code if available. |
Device Info Toggle in Settings
| Field | Description |
|---|---|
| deviceName | Human-readable device name. |
| deviceBrand | Manufacturer brand, e.g. Samsung. |
| deviceModel | Model identifier, e.g. SM-S921B. |
| osVersion | OS name and version, e.g. Android 15. |
Camera & Manual
| Field | Description |
|---|---|
| cameraType | "rear" or "front". |
| flashStatus | "on" or "off". |
| manualDetails | Array of free-text lines defined in Settings. Empty array if none set. |
Environmental Toggle in Settings → Environmental All off by default
Each field is toggled independently. Fields not enabled are omitted from both the overlay and the payload. Weather and humidity require an internet connection (Open-Meteo API); altitude is GPS-derived and works offline.
| Field | Description |
|---|---|
| altitude | Metres above sea level from the GPS fix. e.g. "12.3 m". |
| pressure | Barometric pressure from the device sensor. e.g. "1013.2 hPa". Omitted on devices without a barometer. |
| weather | Current weather condition from Open-Meteo. e.g. "Partly cloudy". Omitted offline. |
| humidity | Relative humidity from the same Open-Meteo request. e.g. "72%". Omitted offline. |
Full Example
Complete payload — all fields enabled, Dual mode, IN action:
{
"action": "IN",
"timestamp": "2026-05-14T10:30:00Z",
"date": "2026-05-14",
"time": "10:30:00 AM",
"timezone": "Etc/UTC",
"unixTimestamp": 1747218600,
"latitude": "37.7749",
"longitude": "-122.4194",
"street": "Main Street",
"barangay": "Sample District",
"city": "Sample City",
"province": "Sample Region",
"country": "Sample Country",
"countryCode": "--",
"postalCode": "00000",
"deviceName": "Samsung Galaxy S24",
"deviceBrand": "Samsung",
"deviceModel": "SM-S921B",
"osVersion": "Android 15",
"cameraType": "rear",
"flashStatus": "off",
"manualDetails": ["Job #1042", "Supervisor: Juan Lobby"],
"imageBase64": "BASE64_ENCODED_JPEG_DATA",
"imageFileName": "IMG_20260514_103007.jpg"
} Minimal payload (Single mode, offline)
{
"action": "CAPTURE",
"timestamp": "2026-05-14T10:30:00Z",
"date": "2026-05-14",
"time": "10:30:00 AM",
"timezone": "Etc/UTC",
"unixTimestamp": 1747218600,
"manualDetails": [],
"imageBase64": "BASE64_ENCODED_JPEG_DATA",
"imageFileName": "IMG_20260514_103007.jpg"
} When offline, location fields are omitted entirely. Timestamp, device info, and manual details are still present.
Offline & Upload Queue
Photo capture and local gallery save always succeed regardless of connectivity. The free ad-supported tier still requires internet to serve ads — Remove Ads unlocks full offline use.
When the device is offline at capture time:
- GPS and reverse-geocoded address are omitted from overlay and payload.
- Device clock is used for the timestamp (same as when online).
- The API POST is queued on your device.
When internet reconnects, queued uploads retry automatically. The QUEUE pill shows pending + failed count.
imageFileName or a composite of action + unixTimestamp + deviceModel. Timestamps
Arguox uses the device's own clock to timestamp each capture — there's no external time-verification API and no drift check, so the shutter never waits on a network round-trip.
The device time is written directly to the timestamp value in the payload.
Error Handling
Arguox considers any HTTP 2xx response a success. Any other status code (including 3xx redirects) is treated as a failure and queued for retry.
Retry behavior
- Automatic retry when internet reconnects.
- Manual per-item retry via the Queue modal.
- Batch retry via "Retry Failed" button.
- Retry count and last retry timestamp stored per item on your device.
Recommended server response
HTTP/1.1 200 OK
Content-Type: application/json
{ "status": "ok" } Google Sheets & Drive
Use a free Google Apps Script web app as your endpoint. Every capture will save the photo to your Google Drive and log a row in your Google Sheet — no server, no hosting, no cost.
Open Google Apps Script
Go to script.google.com and click New project. Rename it to anything you like, e.g. "Arguox Receiver".
Paste the script below
Replace the default code with the complete script shown below. It creates the Drive folder and Sheet automatically on the first request.
Deploy as a Web App
Click Deploy → New deployment → Type: Web app. Set Execute as: Me and Who has access: Anyone. Click Deploy and copy the URL.
Add the URL to Arguox
In Arguox Capture → Settings → API Config, paste the deployment URL as your endpoint. Enable Auto-upload. Done.
Apps Script code
function doPost(e) {
try {
var data = JSON.parse(e.postData.contents);
// 1. Save photo to Google Drive
var driveLink = "";
if (data.imageBase64 && data.imageFileName) {
var folder = getOrCreateFolder("Arguox Captures");
var bytes = Utilities.base64Decode(data.imageBase64);
var blob = Utilities.newBlob(bytes, "image/jpeg", data.imageFileName);
var file = folder.createFile(blob);
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
driveLink = file.getUrl();
}
// 2. Log row to Google Sheets
var sheet = getOrCreateSheet("Arguox Logs");
sheet.appendRow([
data.date || "",
data.time || "",
data.action || "",
data.latitude || "",
data.longitude || "",
[data.street, data.city, data.country].filter(Boolean).join(", "),
[data.deviceBrand, data.deviceModel].filter(Boolean).join(" "),
data.imageFileName || "",
driveLink,
new Date().toISOString(),
]);
return ContentService
.createTextOutput(JSON.stringify({ status: "ok", driveLink: driveLink }))
.setMimeType(ContentService.MimeType.JSON);
} catch (err) {
return ContentService
.createTextOutput(JSON.stringify({ status: "error", message: err.message }))
.setMimeType(ContentService.MimeType.JSON);
}
}
// ── helpers ──────────────────────────────────────────────────────────────────
function getOrCreateFolder(name) {
var folders = DriveApp.getFoldersByName(name);
return folders.hasNext() ? folders.next() : DriveApp.createFolder(name);
}
function getOrCreateSheet(name) {
var files = DriveApp.getFilesByName(name);
var ss;
if (files.hasNext()) {
ss = SpreadsheetApp.open(files.next());
} else {
ss = SpreadsheetApp.create(name);
var sheet = ss.getActiveSheet();
sheet.setName("Logs");
sheet.appendRow([
"Date", "Time", "Action",
"Latitude", "Longitude", "Address",
"Device", "Filename", "Drive Link", "Received At"
]);
sheet.setFrozenRows(1);
}
return ss.getActiveSheet();
} What you get
Google Drive
Arguox Captures /
IMG_20260519_093012.jpg
IMG_20260519_093847.jpg
IMG_20260519_102201.jpg
One file per capture, auto-organized in a folder.
Google Sheets — Arguox Logs
| Date | Time | Action | Address | Filename |
| 2026-05-19 | 09:30 | CAPTURE | Site St, Location City | IMG_093012.jpg |
| 2026-05-19 | 09:38 | IN | Site St, Location City | IMG_093847.jpg |
| 2026-05-19 | 10:22 | OUT | Site St, Location City | IMG_102201.jpg |
One row per capture with Drive link included.