diff --git a/roles/archwiki/templates/nginx.d.conf.j2 b/roles/archwiki/templates/nginx.d.conf.j2
index 5cbe53565228f458d5fc6e52c206c1ee3681040a..363e0111676ccff64454ac0b94345040f359c9ef 100644
--- a/roles/archwiki/templates/nginx.d.conf.j2
+++ b/roles/archwiki/templates/nginx.d.conf.j2
@@ -1,6 +1,10 @@
 fastcgi_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=wiki:100m inactive=60m;
 fastcgi_cache_key "$scheme$request_method$host$request_uri";
 
+# rate limit API endpoint
+limit_req_zone $binary_remote_addr zone=api_zone:10m rate=5r/s;
+limit_req_status 429;
+
 upstream archwiki {
     server unix://{{ archwiki_socket }};
 }
@@ -81,6 +85,17 @@ server {
         add_header X-Cache $upstream_cache_status;
     }
 
+    # mediawiki API endpoint
+    location ~ ^/api\.php {
+        limit_req zone=api_zone burst=10 delay=5;
+        try_files $uri =404;
+        access_log   /var/log/nginx/{{ archwiki_domain }}/access.log main;
+        access_log   /var/log/nginx/{{ archwiki_domain }}/access.log.json json_main;
+        fastcgi_pass   archwiki;
+        fastcgi_index  index.php;
+        include        fastcgi.conf;
+    }
+
     # normal PHP FastCGI handler
     location ~ ^/[^/]+\.php$ {
         try_files $uri =404;