Sync Manager
Track sync job history and recover from failures
All cards below communicate through this WireGuard gateway β router tunnel
π₯ Firewalls to Connect and Disconnect Residential Clients
Push firewall rules via HTTPS (port 443) through secure WireGuard tunnel (port 51820)
π΅ Router REST API over HTTPS port 443 via WireGuard tunnel (port 51820 is separate)
Must match a registered router's location_name in RouterVault
π Firewall Rules (Will be pushed to router)
/ip firewall filter
add action=accept chain=forward comment=\
"iSurf X - Permit Vault Sync While Suspended" dst-address-list=\
isurfx_vault src-address-list=morosos
add action=accept chain=forward comment="iSurf X - Permit DNS aviso" \
dst-port=53 protocol=udp src-address-list=aviso
add action=accept chain=forward comment=\
"iSurf X - Permit DNS morosos for lookup redirection" dst-port=53 \
protocol=udp src-address-list=morosos
add action=drop chain=forward comment="iSurf X - Bloquear todo morosos" \
dst-address-list=!isurfx_vault src-address-list=morososClick "Push Firewalls to Router" to apply these rules directly to the physical router via REST API
How it works (Direct HTTPS via WireGuard tunnel):
π‘ Step 1: Lookup router in RouterVault database by location_name
π‘ Step 2: Push firewall rules directly to physical router REST API via WireGuard tunnel (HTTPS)
π‘ Step 3: Rules apply immediately on the router
π΅ Rule 1: Permit vault sync for suspended clients (morosos can reach isurfx_vault)
π΅ Rule 2: Allow DNS (port 53) for active clients (aviso)
π΅ Rule 3: Allow DNS redirection lookup for suspended clients (morosos)
π΅ Rule 4: Block all traffic from suspended clients (morosos) except vault access
π Address Lists: aviso = active clients | morosos = suspended clients | isurfx_vault = vault server
β Path: Base44 β WireGuard Tunnel β Physical Router REST API (HTTPS:443)
Manually add or remove a client IP from the firewall address lists
π§ͺ TEST ROUTER β HTTPS Management
β Registered Routers (0)
β No HTTPS routers found. Migrate a router to HTTPS path first (use the Path Migration button in the Residential Clients table).
β ADD NEW ROUTERS ADMIN / AGREGAR NUEVOS ROUTERS ADMINISTRADORES
Register a new router in the system, then paste the generated script into WinBox Terminal (done once per router)
β Registered Routers (0)
STEP 1 β Register Router in App Database:
Router ID (number)
Location Name
Vault Folder Name (auto-filled)
WG Tunnel IP *
Port (HTTPS)
API Username *
API Password *
Notes (optional)
STEP 2 β Paste this in WinBox Terminal (one time only):
This creates the polling script + scheduler on the router
/system script add name=vault-pull source={
:local routerId "YOUR_ROUTER_ID"
:local proxyUrl "https://app.base44.app/api/apps/698e12939020081099647ada/functions/gcsVoucherProxy"
:do {
/tool fetch url=$proxyUrl http-method=post \
http-data="{\"router_id\":\"$routerIdStr\"}" \
http-header-field="Content-Type: application/json" \
dst-path=vouchers_pending.rsc check-certificate=no
} on-error={
:log warning ("vault-pull: fetch failed for router " . $routerId)
}
:delay 2s
:if ([/file find name="vouchers_pending.rsc"] != "") do={
:local fSize [/file get vouchers_pending.rsc size]
:if ($fSize > 100) do={
/import file-name=vouchers_pending.rsc
:log info ("vault-pull: Import complete - router " . $routerId)
} else={
:log debug ("vault-pull: No new vouchers - router " . $routerId)
}
/file remove vouchers_pending.rsc
} else={
:log warning ("vault-pull: File not found after fetch")
}
}
/system scheduler add name=vault-pull interval=00:05:00 on-event="/system script run vault-pull"β After pasting, the router will automatically pull vouchers every 5 min via HTTPS
Copy the script below and paste it in WinBox Terminal, then add the scheduler manually
β οΈ INSTRUCCIONES β DO THIS IN ORDER:
- In WinBox β System β Scripts β find
vault-pullβ DELETE IT - Click + to add new script β Name:
vault-pull - Paste the script below into the Source field β click OK
- In WinBox β System β Scheduler β if
vault-pullexists, leave it. If not, paste the scheduler command. - Click Run Script once manually to verify it works
Select Router to Configure:
π RouterOS Script (copy & paste in WinBox Terminal):
/tool fetch url="https://app.base44.app/api/apps/698e12939020081099647ada/functions/gcsVoucherProxy" http-method=post http-data="{"router_id":"1"}" http-header-field="Content-Type: application/json" dst-path=vouchers_pending.rsc check-certificate=no
:delay 2s
:if ([/file find name="vouchers_pending.rsc"] != "") do={
:local fSize [/file get vouchers_pending.rsc size]
:if ($fSize > 100) do={
/import file-name=vouchers_pending.rsc
} else={
:log debug "No new vouchers yet"
}
/file remove vouchers_pending.rsc
} else={
:log warning "Fetch failed - file vouchers_pending.rsc does not exist"
}β° RouterOS Scheduler Command (copy & paste in WinBox Terminal):
/system scheduler add name=vault-pull interval=00:05:00 on-event="vault-pull"
β This automatically creates the 5-minute scheduler in your router
Tests every hop: Physical Router β vault.isurfx.com/router/usage β syncVoucherUsageFromPhysicalRouter
Router POSTs session data β vault.isurfx.com/router/usage β Base44
How it works:
- Reads
/user-manager sessionβ every used voucher with its uptime (theuserlist carries no uptime in RouterOS v7, so a script that reads only that list sends nothing) - Also reads
/ip hotspot activefor currently connected users - POSTs
code + uptimetovault.isurfx.com/router/usageβ proxied to Base44 - Auth goes out as one comma-separated header list β a semicolon separator makes the vault reply 401
- If a push is refused (vault rate limit), the script retries 3 times and logs a warning, so the sale is not lost silently
- Scheduler runs every 5 minutes β no WireGuard, pure HTTPS
Select Router to Configure:
Router API Token (Authorization: Bearer)
β οΈ Paste the token above β without it the vault answers 401 and the script pushes nothing.
π RouterOS Script (copy & paste in WinBox Terminal):
:local routerId "1"
:local syncUrl "https://vault.isurfx.com/router/usage"
:local apiToken "PASTE_ROUTER_TOKEN_HERE"
# --- PART 1: PHYSICAL USER MANAGER SESSIONS ---
:local umSessions [/user-manager session print as-value]
:foreach s in=$umSessions do={
:local user ($s->"user")
:local uptime ($s->"uptime")
# Only push if the voucher has actually been active online
:if ($user != "" && $uptime != "" && $uptime != "0s" && $uptime != "00:00:00") do={
:local payload "{\"router_id\":\"$routerId\",\"code\":\"$user\",\"uptime\":\"$uptime\"}"
:local sent false
:local tries 0
:while (!$sent && $tries < 3) do={
:set tries ($tries + 1)
:do {
/tool fetch url=$syncUrl http-method=post http-data=$payload http-header-field="Content-Type: application/json,Authorization: Bearer $apiToken" dst-path=sync_resp_um.tmp check-certificate=no
:set sent true
} on-error={
:delay 4s
}
}
:do { /file remove sync_resp_um.tmp } on-error={ :log debug "sync-vouchers: User Manager endpoint skip or error" }
:if (!$sent) do={ :log warning ("sync-vouchers: UM push FAILED after 3 tries -> " . $user) }
# 1-second safety pacing gap
:delay 1s
}
}
# --- PART 2: ACTIVE HOTSPOT SESSIONS ---
:local hsSessions [/ip hotspot active print as-value]
:foreach h in=$hsSessions do={
:local user ($h->"user")
:local uptime ($h->"uptime")
:if ($user != "" && $uptime != "" && $uptime != "0s" && $uptime != "00:00:00") do={
:local payload "{\"router_id\":\"$routerId\",\"code\":\"$user\",\"uptime\":\"$uptime\"}"
:local sent false
:local tries 0
:while (!$sent && $tries < 3) do={
:set tries ($tries + 1)
:do {
/tool fetch url=$syncUrl http-method=post http-data=$payload http-header-field="Content-Type: application/json,Authorization: Bearer $apiToken" dst-path=sync_resp_hs.tmp check-certificate=no
:set sent true
} on-error={
:delay 4s
}
}
:do { /file remove sync_resp_hs.tmp } on-error={ :log debug "sync-vouchers: Hotspot endpoint skip or error" }
:if (!$sent) do={ :log warning ("sync-vouchers: HS push FAILED after 3 tries -> " . $user) }
# 1-second safety pacing gap
:delay 1s
}
}
:log info "sync-vouchers: Pure HTTPS synchronization cycle finished."β° RouterOS Scheduler Command (copy & paste in WinBox Terminal):
/system scheduler add name=usage-sync interval=00:05:00 on-event="usage-sync"
β This automatically creates the 5-minute scheduler in your router
Converts active vouchers with hours_used > 0 to sold β fixes undercounted dashboard totals
Run this once per subaccount after a historical router sync. Processes 50 vouchers per batch with 5s delay to avoid rate limits.
Uploads the voucher .rsc file directly to vault.isurfx.com via HTTPS PUT. Physical routers poll the vault server every 5 minutes to fetch and import pending vouchers automatically.
No batches pending vault upload.
MANUAL: los lotes quedan en cola sin enviarse. TΓΊ decides cuΓ‘ndo publicarlos con Sync Now o con los botones de esta tarjeta.
This keeps the same router_id and vault_folder_name for the location
Copy the script below and paste it in WinBox Terminal, then add the scheduler manually
0
Suspended Clients
0
Pending Router Sync
How it works:
- Router polls
getSuspendRSCendpoint every 5 minutes - Platform returns a
suspend.rscwith block/unblock commands - Router imports the script β adds/removes IPs from
blockedlist - Overdue clients lose internet access automatically β
Select Router to Configure:
π RouterOS Script (copy & paste in WinBox Terminal):
:local routerId "1"
:local suspendUrl "https://app.base44.app/api/apps/698e12939020081099647ada/functions/getSuspendRSC"
:do {
/tool fetch url=$suspendUrl http-method=post http-data="{\"router_id\":\"$routerId\"}" http-header-field="Content-Type: application/json" dst-path=suspend.rsc check-certificate=no
} on-error={
:log warning ("suspend-poll: Could not reach suspend endpoint for router " . $routerId)
}
:delay 2s
:if ([/file find name="suspend.rsc"] != "") do={
:local fSize [/file get suspend.rsc size]
:if ($fSize > 10) do={
:log info ("suspend-poll: Importing " . $fSize . " bytes - router " . $routerId)
/import file-name=suspend.rsc
:log info ("Suspend rules applied - router " . $routerId)
} else={
:log debug ("suspend-poll: No pending changes - router " . $routerId)
}
/file remove suspend.rsc
} else={
:log warning ("suspend-poll: Fetch failed - suspend.rsc not found")
}No sync jobs found
