Skip to content
NetConfig NetConfig

Network Automation Reference

NetConfig NetConfig

Network Automation Reference

  • Cisco
  • Fortigate
  • Meraki
  • Palo Alto
  • Cisco
  • Fortigate
  • Meraki
  • Palo Alto
Close

Search

  • Facebook
  • Telegram
  • X
  • Pinterest
  • Reddit
NetConfig NetConfig

Network Automation Reference

NetConfig NetConfig

Network Automation Reference

  • Cisco
  • Fortigate
  • Meraki
  • Palo Alto
  • Cisco
  • Fortigate
  • Meraki
  • Palo Alto
Close

Search

  • Facebook
  • Telegram
  • X
  • Pinterest
  • Reddit
Home/Fortigate/FortiGate Static Route with REST API and Python-2026
Fortigate

FortiGate Static Route with REST API and Python-2026

By Bhardwaj Vishnu
July 1, 2026 5 Min Read
0

Published: July 2026 · Category: Automation · Author: Network Troves · Applies to: FortiGate (FortiOS 7.x/8.x), Python 3.x

FortiGate static route with REST API automation is what I set up today instead of clicking through the GUI or hand-typing CLI commands. If you’re managing more than a handful of firewalls, this is one of the first automation wins worth building.

Pushing a route this way means sending a POST request to /api/v2/cmdb/router/static, authenticated with a bearer token instead of username/password. It’s the same underlying config the GUI writes, just triggered from a script.

Why I Set Up FortiGate Static Route with REST API

I had a new /24 that needed a static route pointing out wan1 via a specific gateway. One route, one firewall — not worth automating on its own. But I wanted the pattern in place before I’m doing this across a dozen branch FortiGates where consistency and speed actually matter.

Environment

  • FortiGate-60F running FortiOS v8.0.0, build 167
  • Python 3.x with the requests and urllib3 libraries
  • REST API admin profile with a generated API token
  • Management access over HTTPS to the FortiGate’s admin interface

Generating the API Token

Before any of this works, you need a REST API admin configured under System > Administrators, scoped to the right permission profile, with an API token generated. Fortinet ties the token to a specific source IP by default (a trusted host restriction), so if your script runs from a different subnet than expected, you’ll get an auth failure before you even get to the routing logic. I keep tokens scoped tightly — no reason to hand a script full super-admin rights just to write one config table.

The Script

Here’s the working script, cleaned up:

python
import requests
import json
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

FORTIGATE_IP = "your.fortigate.ip"
API_TOKEN = "your-api-token-here"

DESTINATION_SUBNET = "10.200.10.0 255.255.255.0"
GATEWAY_IP = "192.168.70.1"
OUTBOUND_INTERFACE = "wan1"

url = f"https://{FORTIGATE_IP}/api/v2/cmdb/router/static"

headers = {
    'Content-Type': 'application/json',
    'Authorization': f'Bearer {API_TOKEN}'
}

payload = {
    "json": {
        "dst": DESTINATION_SUBNET,
        "gateway": GATEWAY_IP,
        "device": OUTBOUND_INTERFACE,
        "comment": "Provisioned automatically via Python REST API script"
    }
}

response = requests.post(url, headers=headers, json=payload, verify=False)

if response.status_code == 200:
    output = response.json()
    print("Configuration Applied Successfully!")
    print(json.dumps(output, indent=4))
else:
    print(f"Failed! HTTP Status Code: {response.status_code}")
    print(response.text)

A couple of details that tripped me up the first time I wrote something like this:

  • The dst field format. FortiOS wants destination and subnet mask as a single space-separated string ("10.200.10.0 255.255.255.0"), not CIDR notation. Send CIDR and you’ll get a 400 back.
  • The payload wrapper. The FortiOS CMDB API expects the actual route attributes nested under a top-level "json" key. Miss that and the request technically succeeds but writes nothing useful.
  • verify=False. Fine for a lab or internal management network with a self-signed cert. In production, I’d rather pin the cert or add it to a trust store than blanket-disable TLS verification — silencing the warning doesn’t remove the risk, it just hides it. If you’re debugging a request that isn’t landing the way you expect, the workflow in my FortiGate debug commands guide for packet flow and IPsec applies here too — same diagnose debug toolkit, just pointed at a config push instead of traffic.

Verification

After running the script, the API returned "status": "success" with "http_status": 200 and an mkey of 2 — that’s the internal object index FortiOS assigned the new route entry.

Checking Network > Static Routes in the GUI confirmed it: the 10.200.10.0/24 route showed up pointed to 192.168.70.1 via wan1, marked Enabled, with the comment field carrying through exactly as sent in the script.

FortiGate static route with REST API
Static route provisioned via the FortiGate REST API, verified in the GUI and confirmed through system event logs.

I also pulled the event log under Log & Report > System Events, which recorded the transaction cleanly — config path router.static, config object 2, with the destination, gateway, device, and comment all logged as config attributes. That log entry is useful if you’re building an audit trail for changes pushed outside the GUI, the same habit I lean on when I’m auditing switch-side changes in my FortiSwitch SNMPv3 configuration via FortiLink writeup.

FortiGate static route with REST API
Static route provisioned via the FortiGate REST API, confirmed through system event logs.

Troubleshooting Notes

  • 401 Unauthorized — almost always the trusted host restriction on the API admin, not a bad token. Check the source IP the request is actually coming from.
  • 400 Bad Request on dst — check for CIDR notation instead of the space-separated mask format.
  • 200 response but no visible route — check VDOM. If you’re running multi-VDOM and the token’s admin profile is scoped to a non-root VDOM, the route lands somewhere you’re not looking.

Lessons Learned

The REST API mirrors the CMDB structure almost exactly, so if you already know your way around FortiGate config paths from the CLI (config router static), the API payload structure isn’t a big leap. The friction is almost entirely in formatting quirks like the dst field and the json wrapper — not in the networking logic itself. That’s the real value of setting up a FortiGate static route with REST API: once the payload format clicks, it’s a repeatable five-minute job instead of a GUI walkthrough on every box. If you’re new to FortiOS diagnostics generally, my FortiGate debug flow functions reference guide is a good companion piece for understanding how FortiOS processes config and traffic under the hood.

Best Practices

  • Scope API admin tokens to the minimum required permission profile
  • Restrict tokens to trusted source IPs rather than leaving them open
  • Store tokens in environment variables or a secrets manager, never hardcoded in a script that might end up in version control
  • Log every automated change with a descriptive comment field, like I did here, so it’s traceable later
  • Test against a lab FortiGate before pointing scripts at production

FAQ

Can I add a FortiGate static route without the GUI?
Yes. The FortiOS REST API accepts a POST request to /api/v2/cmdb/router/static with the destination, gateway, and outbound interface in the payload, authenticated by an API token.

What format does the FortiGate API expect for the destination subnet?
A space-separated string of network address and subnet mask, such as "10.200.10.0 255.255.255.0" — not CIDR notation.

Why does my FortiGate API request return 401?
Usually the API admin’s trusted host restriction is blocking the source IP the request is coming from, not an invalid token.

Is verify=False safe to use with the FortiGate REST API?
It’s acceptable for lab environments with self-signed certs, but in production it’s safer to properly trust the certificate rather than disable TLS verification entirely.

Does the FortiGate REST API support other routing protocols besides static routes?
Yes — CMDB endpoints exist for BGP, OSPF, and other router configuration objects under the same /api/v2/cmdb/router/ path structure.

🔧 Free Network Tools

Handy while you're troubleshooting — no signup needed.

📡 Ping Test Check connectivity and latency to any host. 🔌 Port Checker Verify if a TCP port is open and reachable. 🌐 My IP Find your current public IP address. 📧 MX Lookup Inspect a domain's mail server records.
Other Articles
FortiSwitch SNMPv3 configuration on FortiLink-managed switch GUI
Previous

FortiSwitch SNMPv3 Configuration via FortiLink Trick -2026

Cisco IKEv1 debug
Next

Cisco IKEv1 Debug Commands and States – Phase 1 & 2

No Comment! Be the first one.

    Leave a Reply Cancel reply

    Sign in with Google to comment — verifies you're a real person. No WordPress account is created; nothing beyond your name and email is used.

    ✓ Signed in — you can comment below.

    Your email address will not be published. Required fields are marked *

    On This Page0%
    1. Top
    2. 1. Why I Set Up FortiGate Static Route with REST API
    3. 2. Environment
    4. 3. Generating the API Token
    5. 4. The Script
    6. 5. Verification
    7. 6. Troubleshooting Notes
    8. 7. Lessons Learned
    9. 8. Best Practices
    10. 9. FAQ

    Network Tools

    📡 Ping Test Check connectivity and latency to any host. → 🔌 Port Checker Verify if a TCP port is open and reachable. → 🌐 My IP Find your current public IP address. → 📧 MX Lookup Inspect a domain's mail server records. →

    Cisco ISR Debug Flow Diagnostics Fortigate FortiGate IPsec Remote Access VPN Fortinet FortiOS FortiOS CLI IKEv2 IOS-XE iprope IPsec Licensing Network Security NPU Offload Offline Configuration Packet Flow Palo Alto PAN-OS Proxy ID Site-to-Site VPN TAC TFTP Troubleshooting VPN Troubleshooting

    NetConfig.io

    NetConfig is a technical blog dedicated to enterprise network engineering. We publish in-depth configuration guides, real-world troubleshooting walkthroughs, and practical tutorials covering the exact tools and technologies that network engineers work with every day.

    Quick Links

    Company info, legal & policies.

    • About us
    • Contact us
    • Disclaimer
    • Privacy Policy
    • Terms of Service

    Stay Updated

    Get new guides delivered to your inbox.

    Subscription form is not available at the moment
    Copyright 2026 - NetConfig.io All rights reserved.

    We use cookies to run this site and, with your permission, for analytics and ads. You can change your choice anytime from the footer link. Learn more