diff --git a/docs/reference.md b/docs/reference.md
index ab3e5a25eb9d533e54741c60b57cab52cec3329b..af8425cb586794f20e928d886d9681230fe53008 100644
--- a/docs/reference.md
+++ b/docs/reference.md
@@ -2088,6 +2088,12 @@ using single sign-on, allowing access only to administrators (members
 of the *admins* group). This is quite useful for admin web interfaces
 of internal services that do not support SSO integration of their own.
 
+`enable_api_proxy`: If true, place the service behind authentication
+using a mechanism more appropriate for non-interactive APIs (HTTP
+Basic Authentication using Application-Specific Passwords). Only members
+of the *admins* group will have access. When this option is set, you
+also need to specify a unique `auth_service` to be used for ASPs.
+
 #### HTTP (All domains)
 
 `horizontal_endpoints`: List of HTTP endpoints exported by the
diff --git a/docs/reference.pdf b/docs/reference.pdf
index ac02d89969fb52c08f50515ae1be4eb588125181..20cdfe312c22e9bb0c692c41f91d48381801eac8 100644
Binary files a/docs/reference.pdf and b/docs/reference.pdf differ
diff --git a/plugins/inventory/float.py b/plugins/inventory/float.py
index e67df79ecb905ae7792d9ae24b952ab3ef688613..17685c3358e54554f9df0b76a807f0b0974fa640 100644
--- a/plugins/inventory/float.py
+++ b/plugins/inventory/float.py
@@ -332,6 +332,7 @@ def _build_public_endpoints_map(services):
                 'name': upstream_name,
                 'service_name': service_name,
                 'port': pe['port'],
+                'enable_api_proxy': pe.get('enable_api_proxy', False),
                 'enable_sso_proxy': pe.get('enable_sso_proxy', False),
                 'sharded': pe.get('sharded', False),
             }
@@ -385,6 +386,7 @@ def _build_horizontal_upstreams_map(services):
                 'name': upstream_name,
                 'service_name': service_name,
                 'port': ep['port'],
+                'enable_api_proxy': False,
                 'enable_sso_proxy': False,
                 'sharded': False,
             }
diff --git a/roles/float-infra-nginx/handlers/main.yml b/roles/float-infra-nginx/handlers/main.yml
index 397098e82ed346d037bf36e723e0c2a9a44260b2..a21681d9178fa5523531eb5196c2847706a2cc66 100644
--- a/roles/float-infra-nginx/handlers/main.yml
+++ b/roles/float-infra-nginx/handlers/main.yml
@@ -7,6 +7,9 @@
 - name: restart sso-proxy
   systemd: name=sso-proxy.service state=restarted enabled=yes masked=no
 
+- name: restart api-proxy
+  systemd: name=api-proxy.service state=restarted enabled=yes masked=no
+
 - name: reload firewall
   systemd:
     name: firewall.service
diff --git a/roles/float-infra-nginx/tasks/api-proxy.yml b/roles/float-infra-nginx/tasks/api-proxy.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6d7f27d5686a9e5c90db4ac6dce4b5edffcff9f7
--- /dev/null
+++ b/roles/float-infra-nginx/tasks/api-proxy.yml
@@ -0,0 +1,24 @@
+---
+
+- set_fact:
+    api_proxy_auth_services: "{{ services.values() | selectattr('public_endpoints', 'defined') | map(attribute='public_endpoints') | flatten | selectattr('enable_api_proxy', 'defined') | selectattr('enable_api_proxy') | map(attribute='auth_service') }}"
+
+- name: Configure api-proxy auth services
+  copy:
+    dest: "/etc/auth-server/services.d/api-proxy.yml"
+    content: |
+      {% for s in api_proxy_auth_services %}
+      {{ s }}:
+        backends:
+          - backend: file
+            params:
+              src: users.yml
+              static_groups: [admins]
+        enforce_2fa: true
+        rate_limits:
+          - ip_ratelimit
+          - failed_login_blacklist
+          - anti_bruteforce_blacklist
+      {% endfor %}
+  when: "api_proxy_auth_services"
+
diff --git a/roles/float-infra-nginx/tasks/main.yml b/roles/float-infra-nginx/tasks/main.yml
index 48b47283c5a996d01bcec7d3a82cf20e240bd527..83461947a62763183a882db9c27e15436d814700 100644
--- a/roles/float-infra-nginx/tasks/main.yml
+++ b/roles/float-infra-nginx/tasks/main.yml
@@ -3,3 +3,7 @@
 # Only set up nginx if there are public_endpoints defined.
 - import_tasks: nginx.yml
   when: float_enable_http_frontend
+
+- import_tasks: api-proxy.yml
+  when: float_enable_http_frontend
+
diff --git a/roles/float-infra-nginx/tasks/nginx.yml b/roles/float-infra-nginx/tasks/nginx.yml
index e4ba5f2dea85155db84193b584f37d986cb623f7..e4c3e46f2b260ae1370d9644b21c6d6b30a43002 100644
--- a/roles/float-infra-nginx/tasks/nginx.yml
+++ b/roles/float-infra-nginx/tasks/nginx.yml
@@ -6,6 +6,7 @@
     state: present
   vars:
     packages:
+      - api-proxy
       - sso-proxy
       - nginx-full
       - libnginx-mod-http-headers-more-filter
@@ -17,20 +18,32 @@
     dest: /etc/default/sso-proxy
   notify: restart sso-proxy
 
-- name: Configure ssoproxy
+- name: Configure sso-proxy
   template:
-    src: proxy.yml.j2
+    src: sso-proxy.yml.j2
     dest: /etc/sso/proxy.yml
     owner: root
     group: sso-proxy
     mode: 0640
   notify: restart sso-proxy
 
-- name: Add user sso-proxy to credentials group
+- name: Configure api-proxy
+  template:
+    src: api-proxy.yml.j2
+    dest: /etc/api-proxy.yml
+    owner: root
+    group: api-proxy
+    mode: 0640
+  notify: restart api-proxy
+
+- name: Add proxy users to credentials group
   user:
-    name: sso-proxy
+    name: "{{ item }}"
     groups: ssoproxy-credentials
     append: yes
+  loop:
+    - api-proxy
+    - sso-proxy
 
 - name: Enable sso-proxy systemd unit
   systemd:
diff --git a/roles/float-infra-nginx/templates/api-proxy.yml.j2 b/roles/float-infra-nginx/templates/api-proxy.yml.j2
new file mode 100644
index 0000000000000000000000000000000000000000..78f44c7a8c060ff3743aef4986a2b421ae7ea513
--- /dev/null
+++ b/roles/float-infra-nginx/templates/api-proxy.yml.j2
@@ -0,0 +1,24 @@
+---
+
+backends:
+{% for service in services.values() -%}
+{% for endpoint in service.get('public_endpoints', []) -%}
+{% if endpoint.get('enable_api_proxy') %}
+  - host: "{{ endpoint.name }}.{{ domain_public[0] }}"
+{% if endpoint.get('scheme') == 'https' %}
+    tls_server_name: "{{ service.name }}.{{ domain }}"
+    client_tls:
+      cert: "/etc/credentials/x509/ssoproxy/client/cert.pem"
+      key: "/etc/credentials/x509/ssoproxy/client/private_key.pem"
+      ca: "/etc/credentials/x509/ssoproxy/ca.pem"
+{% endif %}
+    upstream:
+      - {{ service.name }}.{{ domain }}:{{ endpoint.port }}
+    auth_service: "{{ endpoint.auth_service }}"
+    allowed_groups:
+{% for group in endpoint.get('allowed_groups', ['admins']) %}
+      - {{ group }}
+{% endfor %}
+{% endif -%}
+{% endfor -%}
+{% endfor %}
diff --git a/roles/float-infra-nginx/templates/nginx-upstream.j2 b/roles/float-infra-nginx/templates/nginx-upstream.j2
index 1b3e6bc984d20eef687c48d41bfecfae532b07b0..10894843f669107ba1688aae405bc982968fab3b 100644
--- a/roles/float-infra-nginx/templates/nginx-upstream.j2
+++ b/roles/float-infra-nginx/templates/nginx-upstream.j2
@@ -5,6 +5,11 @@ upstream {{ upstream.name }}{% if shard %}_{{ shard }}{% endif %} {
         Talk directly to the SSO proxy on localhost.
 #}
         server 127.0.0.1:5003;
+{% elif upstream.enable_api_proxy | default(False) %}
+{#
+        Talk directly to the api-proxy on localhost.
+#}
+        server 127.0.0.1:5009;
 {% else %}
 {#
         Use the internal endpoint name, which resolves to multiple IP
diff --git a/roles/float-infra-nginx/templates/nginx-vhost.j2 b/roles/float-infra-nginx/templates/nginx-vhost.j2
index 244cc8b201febeb7c3d2f03c5b95fd49bb0cb703..67064c5cdf91fd7727ab137aa2690826c9704200 100644
--- a/roles/float-infra-nginx/templates/nginx-vhost.j2
+++ b/roles/float-infra-nginx/templates/nginx-vhost.j2
@@ -8,14 +8,14 @@
         location {{ pe_config.path }} {
                 include /etc/nginx/snippets/block.conf;
                 include /etc/nginx/snippets/proxy.conf;
-{% if not upstream.enable_sso_proxy and pe_config.get('scheme', 'https') == 'https' %}
+{% if not upstream.enable_sso_proxy and not upstream.enable_api_proxy and pe_config.get('scheme', 'https') == 'https' %}
                 proxy_pass https://{{ pe_config.float_upstream_name }}{% if upstream.sharded and shard %}_{{ shard }}{% endif %};
                 include /etc/nginx/snippets/proxy-ssl.conf;
                 proxy_ssl_name {{ upstream.service_name }}.{{ domain }};
 {% else %}
                 proxy_pass http://{{ pe_config.float_upstream_name }}{% if upstream.sharded and shard %}_{{ shard }}{% endif %};
 {% endif %}
-{% if not upstream.enable_sso_proxy %}
+{% if not upstream.enable_sso_proxy and not upstream.enable_api_proxy %}
                 proxy_cache global;
 {% endif %}
         }
diff --git a/roles/float-infra-nginx/templates/proxy.yml.j2 b/roles/float-infra-nginx/templates/sso-proxy.yml.j2
similarity index 100%
rename from roles/float-infra-nginx/templates/proxy.yml.j2
rename to roles/float-infra-nginx/templates/sso-proxy.yml.j2