# 401 Unauthorized when using Gateway API

**URL:** <https://forum.inductiveautomation.com/t/401-unauthorized-when-using-gateway-api/117190>\
**Category:** Ignition\
**Created:** [September 25, 2026, 5:17pm UTC](https://forum.inductiveautomation.com/t/401-unauthorized-when-using-gateway-api/117190 "2026-09-25T17:17:55Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![lucs100](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lucs100/32/86254_2.png) [@lucs100](https://forum.inductiveautomation.com/u/lucs100)\
**Post date:** [September 25, 2026, 5:17pm UTC](https://forum.inductiveautomation.com/t/401-unauthorized-when-using-gateway-api/117190/1 "2026-09-25T17:17:55Z")

</div>

I'm trying to make a call to `/data/api/v1/scan/projects/`. I've created an API key and I'm trying to use it to authenticate, but I am always given a 401 Unauthorized response.

> **cURL verbose output**
>
> ```python
> $ curl -X GET --header "X-Ignition-API-Token: sgjFTTi7v-[...redacted...]H1ikp-uMuE" localhost:8088/data/api/v1/gateway-info -v
> Note: Unnecessary use of -X or --request, GET is already inferred.
> * Host localhost:8088 was resolved.
> * IPv6: ::1
> * IPv4: 127.0.0.1
> * Trying [::1]:8088...
> * Connected to localhost (::1) port 8088
> > GET /data/api/v1/gateway-info HTTP/1.1
> > Host: localhost:8088
> > User-Agent: curl/8.5.0
> > Accept: */*
> > X-Ignition-API-Token: sgjFTTi7v-[...redacted...]H1ikp-uMuE
> >
> < HTTP/1.1 401 Unauthorized
> < Date: Fri, 25 Sep 2026 17:05:12 GMT
> < Referrer-Policy: strict-origin-when-cross-origin
> < X-Content-Type-Options: nosniff
> < X-Frame-Options: SAMEORIGIN
> < X-XSS-Protection: 1; mode=block
> < Cache-Control: must-revalidate,no-cache,no-store
> < Content-Type: text/html;charset=iso-8859-1
> < Content-Length: 340
> <
> <html>
> <head>
> <meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1"/>
> <title>Error 401</title>
> </head>
> <body><h2>HTTP ERROR 401 Unauthorized</h2>
> <table>
> <tr><th>URI:</th><td>/data/api/v1/gateway-info</td></tr>
> <tr><th>STATUS:</th><td>401</td></tr>
> <tr><th>MESSAGE:</th><td>Unauthorized</td></tr>
> </table>
> 
> </body>
> </html>
> 
> ```

I've also tried using the base URLs `http://localhost:8088` and `https://localhost:8088`, as well as disabling "Require secure connections for API Keys", with no success.

My gateway's Web Server settings seem normal:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/4/f/4f9407c77ce40bd5d0e9439eb284901055de7b2d.png)  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/7/6/7672ab6759309a082706b56a9aeaa78b3d6341a7.png)

Interesting, on a local development instance of my gateway, I'm able to make this call with no issues:

> **cURL verbose output**
>
> ```python
> $ curl -X GET --header "X-Ignition-API-Token: sD-p_kIILyo[...redacted...]ovGemIE" localhost:8089/data/api/v1/gateway-info -v
> Note: Unnecessary use of -X or --request, GET is already inferred.
> * Host localhost:8089 was resolved.
> * IPv6: ::1
> * IPv4: 127.0.0.1
> * Trying [::1]:8089...
> * Connected to localhost (::1) port 8089
> > GET /data/api/v1/gateway-info HTTP/1.1
> > Host: localhost:8089
> > User-Agent: curl/8.5.0
> > Accept: */*
> > X-Ignition-API-Token: sD-p_kIILyo[...redacted...]ovGemIE
> >
> < HTTP/1.1 200 OK
> < Date: Fri, 25 Sep 2026 17:14:07 GMT
> < Referrer-Policy: strict-origin-when-cross-origin
> < X-Content-Type-Options: nosniff
> < X-Frame-Options: SAMEORIGIN
> < X-XSS-Protection: 1; mode=block
> < Content-Type: application/json
> < Content-Length: 441
> <
> * Connection #0 to host localhost left intact
> {"name":"[redacted]","redundancyRole":"Independent","redundantPeerAddress":"","edition":"standard","hostname":"localhost","port":"8089","ignitionVersion":"8.3.9 (b2026082511)","deploymentMode":"development","timeZone":"Eastern Standard Time","timeZoneId":"America/Toronto","jvmVersion":"17.0.19","allowUnsignedModules":true,"license":{"mode":"Trial","validForVersion":8,"expirationDate":"Sep 25, 2026, 11:49:55 AM","licenseRestrictions":[]}}
> 
> ```

The local gateway's Web Server settings are slightly different as SSL/HTTPS is not configured so I can imagine this has something to with it, but I'm not sure what the problem could be. (Note port 8089 on my host machine is mapped to 8088 in the container.)

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/5/2/528e75bae55e471ac220922542ec64466c773bca.png)  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/b/c/bc04e9035b0f1689d1bdac3593f319f4458cbae3.png)

Any help on what might be causing the issue is super appreciated. Thank you 🙂

---

<div class="post-metadata">

**Author:** ![darwin](https://avatars.discourse-cdn.com/v4/letter/d/ee7513/32.png) [@darwin](https://forum.inductiveautomation.com/u/darwin)\
**Post date:** [September 25, 2026, 5:30pm UTC](https://forum.inductiveautomation.com/t/401-unauthorized-when-using-gateway-api/117190/2 "2026-09-25T17:30:39Z")

</div>

This looks like it could be an instance of this problem:

> [@Selecting Security Level in API Key not working 8.3.8](https://forum.inductiveautomation.com/t/selecting-security-level-in-api-key-not-working-8-3-8/116689/3):
>
> What collection (or Deployment Mode) was the Security Level created in? What collection or mode is the Gateway currently in? API Key creation only knows about Security Levels in the current mode of the Gateway. If you've created levels in some other collection/mode, you need to apply them during EDITING of the API Key. This is a limitation of the UI because we can't know about the levels of the other collections/modes until the user tells us to look in those collections/modes, but the first ave…

I have ran into issues on my own gateways where a deployment mode is set before I create the API Key. Usually the way I solve this is creating the key in the core collection (or whatever collection you've defined the additional security levels read permissions in) and then editing and assigning it roles after creation.

---

<div class="post-metadata">

**Author:** ![Marcus\_Sysum](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/marcus_sysum/32/57944_2.png) [@Marcus\_Sysum](https://forum.inductiveautomation.com/u/Marcus_Sysum)\
**Post date:** [September 25, 2026, 6:33pm UTC](https://forum.inductiveautomation.com/t/401-unauthorized-when-using-gateway-api/117190/3 "2026-09-25T18:33:41Z")

</div>

This is often over looked and since your not using https make sure this checkbox is not enabled when creating the api key

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/4/2/42353e2e5d01fe90a2238421fc3323de18de19f5.png)

---

<div class="post-metadata">

**Author:** ![darwin](https://avatars.discourse-cdn.com/v4/letter/d/ee7513/32.png) [@darwin](https://forum.inductiveautomation.com/u/darwin)\
**Post date:** [September 25, 2026, 6:45pm UTC](https://forum.inductiveautomation.com/t/401-unauthorized-when-using-gateway-api/117190/4 "2026-09-25T18:45:09Z")

</div>

I think the user mentioned that they tried toggling this option, it's always my first check too.

> I've also tried using the base URLs `http://localhost:8088` and `https://localhost:8088`, as well as disabling "Require secure connections for API Keys", with no success.

---

<div class="post-metadata">

**Author:** ![lucs100](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lucs100/32/86254_2.png) [@lucs100](https://forum.inductiveautomation.com/u/lucs100)\
**Post date:** [September 25, 2026, 6:45pm UTC](https://forum.inductiveautomation.com/t/401-unauthorized-when-using-gateway-api/117190/5 "2026-09-25T18:45:36Z")

</div>

This setting is disabled on my keys and I've tried over both HTTP and HTTPS ☹

---

<div class="post-metadata">

**Author:** ![lucs100](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lucs100/32/86254_2.png) [@lucs100](https://forum.inductiveautomation.com/u/lucs100)\
**Post date:** [September 25, 2026, 6:49pm UTC](https://forum.inductiveautomation.com/t/401-unauthorized-when-using-gateway-api/117190/6 "2026-09-25T18:49:14Z")

</div>

Moving my key from `core` to the current mode and back to `core` again shows my list of roles now, but they're all still disabled:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/f/a/fa33c951b75b5fbba131e44f860e1fcf846d4746.png)

Side question, is it documented anywhere what roles are required for each endpoint?

---

<div class="post-metadata">

**Author:** ![darwin](https://avatars.discourse-cdn.com/v4/letter/d/ee7513/32.png) [@darwin](https://forum.inductiveautomation.com/u/darwin)\
**Post date:** [September 25, 2026, 6:56pm UTC](https://forum.inductiveautomation.com/t/401-unauthorized-when-using-gateway-api/117190/7 "2026-09-25T18:56:46Z")

</div>

There's a user manual post about this that I can't find right now, but you can't assign user roles to api keys, only custom security levels. I create a separate "APIToken" parent security level with two children, "Read" and "Write" (the access level is set to public on my gateways). In the gateway security settings, I add these levels to the GW write and read permissions and then assign them to each key. These levels only exist to be able to assign to api keys, I don't actually assign them to users.

There are some intricacies related to which collection these definitions are created in depending on whether your gateway was in a deployment mode when they were created (see the first linked forum post I sent for a better explanation).

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/4/9/49b4c944328f88f381755e63e6de838963104386.png)

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/a/9/a961f742617bb8782b86f58c8b93daf6fb31ad79.png)

---

<div class="post-metadata">

**Author:** ![Marcus\_Sysum](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/marcus_sysum/32/57944_2.png) [@Marcus\_Sysum](https://forum.inductiveautomation.com/u/Marcus_Sysum)\
**Post date:** [September 25, 2026, 7:04pm UTC](https://forum.inductiveautomation.com/t/401-unauthorized-when-using-gateway-api/117190/8 "2026-09-25T19:04:11Z")

</div>

Have you created a new security level for the Api Key?

---

<div class="post-metadata">

**Author:** ![lucs100](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lucs100/32/86254_2.png) [@lucs100](https://forum.inductiveautomation.com/u/lucs100)\
**Post date:** [September 25, 2026, 7:17pm UTC](https://forum.inductiveautomation.com/t/401-unauthorized-when-using-gateway-api/117190/9 "2026-09-25T19:17:04Z")

</div>

Oh I see, the security on the local gateway (where API calls work) is tighter than on the production one (where they don't).

I've created API Read/Write levels on the production gateway (in `core` mode), assigned them to Gateway Read/Write permissions respectively (and made sure that these settings require any one level, not all levels), and assigned them to my key. However, I'm still getting a 401 Unauthorized on requests to the production gateway.

Setting this up on the local test gateway introduces the same problem. I made it so that either the Authenticated role or the APIKeys/Read level is required for gateway read permissions:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/9/d/9de21cacf71009c6e20b6b318372529e83016e27.png)

then assigned these levels to my API key:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/4/3/4355cc2dee501886bd08dc69a904b9f50ea402f5.png)

and now I am getting the same 401 Unauthorized error when making the request to my local test gateway. I'm assuming it's not a gateway modes issue because I can see the new security levels when editing the key, but I could be wrong.

---

<div class="post-metadata">

**Author:** ![darwin](https://avatars.discourse-cdn.com/v4/letter/d/ee7513/32.png) [@darwin](https://forum.inductiveautomation.com/u/darwin)\
**Post date:** [September 25, 2026, 7:28pm UTC](https://forum.inductiveautomation.com/t/401-unauthorized-when-using-gateway-api/117190/10 "2026-09-25T19:28:18Z")

</div>

One small thing I noticed in your curl requests as a sanity check is the api keys you used in the call don't seem to include the name of the key.

For example, I just created a key on one of my gateways called "test-token". I created it and it returned the key as `test-token:zkyQJpkbAo--RlKBX8KDCgnErx93Fs6snNC59duIYoQ`. The key is the entire string, including `test-token:`, not just the string after. If you only include the latter part of the key, it would give you a 401 error.

Now it's very possible that you scrambled the keys in your requests for security purposes, but I just wanted to confirm.

---

<div class="post-metadata">

**Author:** ![lucs100](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lucs100/32/86254_2.png) [@lucs100](https://forum.inductiveautomation.com/u/lucs100)\
**Post date:** [September 25, 2026, 7:41pm UTC](https://forum.inductiveautomation.com/t/401-unauthorized-when-using-gateway-api/117190/11 "2026-09-25T19:41:07Z")

</div>

That did it 😅

I wasn't sure whether to keep the name of the key in the string, since removing the name would change the error from 401 to 403 (or vice versa maybe... I can't exactly remember). The key without the name was working on the local test gateway, but now I realize that was because the security settings were making the endpoints public, so a malformed key would still work.

Thank you! Have a great weekend 😄
