ipmap.dev Documentation
ipmap.dev maps any server IP to a clean subdomain with automatic HTTPS. This guide covers everything from your first API call to advanced integrations.
Quickstart
1. Simply run the command in your BASH shell, the script will prompt you to enter your email address and select the server IP and create a subdomain.
# Easy start.
curl -sSL https://get.ipmap.dev| bash
2. Get a subdomain in one command. If the email doesn't exist yet, an account is created automatically and the API key is returned once.
# First call — account is created automatically
curl -X POST https://api.ipmap.dev/v1/subdomains \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","ip":"188.94.12.47"}'
Response:
{
"subdomain": "188-94-12-47.ipmap.link",
"ip": "188.94.12.47",
"type": "free",
"status": "active",
"api_key": "ipm_a3f9d2e8b1c74051f6a0e9d3b2c81749",
"message": "Account created. Save your api_key — it will not be shown again."
}
Authentication
All API requests (except the first registration call) require a Bearer token in the Authorization header.
Authorization: Bearer ipm_your_api_key_here
If you send an email that already has an account without a Bearer token, you'll get a 401 error with a link to your dashboard where you can view your key.
Plans & Limits
| Plan | Subdomains | Custom names | Change IP | Support |
|---|---|---|---|---|
| Free | 3 | ❌ IP-based only | ❌ | Docs + email |
| Starter — $5/mo | 10 | ✅ myapp.ipmap.link | ✅ | Docs + email |
| Pro — $15/mo | 20 | ✅ myapp.ipmap.link | ✅ | Priority + managed |
Rate limit: 60 requests per minute per IP address across all endpoints.
Create Subdomain
Request body
| Parameter | Type | Description |
|---|---|---|
| ip required | string | Your server's public IPv4 or IPv6 address |
| email optional | string | Only on first call (no Bearer token) — creates account and returns API key |
| name optional | string | Custom subdomain name (Starter/Pro only). Leave empty for free IP-based name. |
# Free plan — name is generated from IP
curl -X POST https://api.ipmap.dev/v1/subdomains \
-H "Authorization: Bearer ipm_xxxx" \
-H "Content-Type: application/json" \
-d '{"ip":"188.94.12.47"}'
# Response
{
"subdomain": "188-94-12-47.ipmap.link",
"type": "free",
"status": "active"
}
# Starter/Pro — custom name
curl -X POST https://api.ipmap.dev/v1/subdomains \
-H "Authorization: Bearer ipm_xxxx" \
-H "Content-Type: application/json" \
-d '{"ip":"188.94.12.47","name":"myapp"}'
# Response
{
"subdomain": "myapp.ipmap.link",
"type": "custom",
"status": "active"
}
List Subdomains
curl https://api.ipmap.dev/v1/subdomains \
-H "Authorization: Bearer ipm_xxxx"
# Response
{
"subdomains": [
{
"name": "myapp",
"subdomain": "myapp.ipmap.link",
"ip": "188.94.12.47",
"type": "custom",
"status": "active",
"created_at": "2026-01-15T10:30:00Z"
}
],
"used": 1,
"limit": 20,
"plan": "starter"
}
Update IP
| Parameter | Type | Description |
|---|---|---|
| ip required | string | New public IPv4 or IPv6 address |
curl -X PUT https://api.ipmap.dev/v1/subdomains/myapp \
-H "Authorization: Bearer ipm_xxxx" \
-d '{"ip":"45.33.100.200"}'
custom subdomains support IP updates. Free IP-based subdomains (e.g. 188-94-12-47.ipmap.link) have the IP embedded in the name — delete and recreate to change.
Delete Subdomain
curl -X DELETE https://api.ipmap.dev/v1/subdomains/myapp \
-H "Authorization: Bearer ipm_xxxx"
# Response
{ "deleted": true }
Account Info
curl https://api.ipmap.dev/v1/account \
-H "Authorization: Bearer ipm_xxxx"
{
"email": "[email protected]",
"plan": "starter",
"plan_expires_at": "2026-02-15T00:00:00Z",
"used": 5,
"limit": 20
}
Checkout URL
# plan = "starter" or "pro"
curl https://api.ipmap.dev/v1/checkout/starter \
-H "Authorization: Bearer ipm_xxxx"
{ "checkout_url": "https://buy.paddle.com/..." }
Redirect the user to the returned URL to complete payment. The email is pre-filled automatically.
Nginx Integration
After creating your subdomain (e.g. myapp.ipmap.dev → 188.94.12.47), configure Nginx on your server:
# /etc/nginx/sites-available/myapp
server {
listen 80;
server_name myapp.ipmap.link;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name myapp.ipmap.link;
# SSL via Let's Encrypt (certbot)
ssl_certificate /etc/letsencrypt/live/myapp.ipmap.link/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapp.ipmap.link/privkey.pem;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Then get your SSL certificate:
certbot --nginx -d myapp.ipmap.link
systemctl reload nginx
https://myapp.ipmap.link with a valid SSL certificate.
Apache Integration
# /etc/apache2/sites-available/myapp.conf
<VirtualHost *:80>
ServerName myapp.ipmap.link
Redirect permanent / https://myapp.ipmap.link/
</VirtualHost>
<VirtualHost *:443>
ServerName myapp.ipmap.link
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/myapp.ipmap.link/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/myapp.ipmap.link/privkey.pem
ProxyPreserveHost On
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
</VirtualHost>
a2enmod ssl proxy proxy_http
a2ensite myapp
certbot --apache -d myapp.ipmap.link
systemctl reload apache2
Caddy Integration
Caddy handles HTTPS automatically — no certbot needed.
# Caddyfile
myapp.ipmap.link {
reverse_proxy localhost:3000
}
caddy reload
Docker Integration
Use ipmap.dev with a simple Nginx container:
# docker-compose.yml
version: '3.9'
services:
app:
image: your-app
expose:
- "3000"
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- /etc/letsencrypt:/etc/letsencrypt:ro
depends_on:
- app
Or automate subdomain creation in your deploy script:
#!/bin/bash
SERVER_IP=$(curl -s ifconfig.me)
# Create/update subdomain on deploy
curl -X POST https://api.ipmap.dev/v1/subdomains \
-H "Authorization: Bearer $IPMAP_API_KEY" \
-d "{\"ip\":\"$SERVER_IP\",\"name\":\"myapp\"}"
Traefik Integration
# docker-compose.yml with Traefik
version: '3.9'
services:
traefik:
image: traefik:v3
command:
- --providers.docker=true
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --certificatesresolvers.le.acme.httpchallenge=true
- [email protected]
- --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
ports:
- "80:80"
- "443:443"
app:
image: your-app
labels:
- traefik.http.routers.app.rule=Host(`myapp.ipmap.link`)
- traefik.http.routers.app.tls.certresolver=le
FAQ
Why is my subdomain showing 127.0.0.1?
Your subscription may have expired. Subdomains over the free limit (3) are paused and pointed to 127.0.0.1 when a plan expires. Renew your subscription in the dashboard and they'll restore automatically within minutes.
How long does DNS propagation take?
New subdomains typically resolve within 30–60 seconds. In rare cases it may take a few minutes. Use dig myapp.ipmap.link to check.
Can I use a wildcard subdomain?
Not currently. Each subdomain maps to exactly one IP. Wildcard support is on the roadmap.
What IP validation is performed?
We reject private IP ranges (10.x.x.x, 192.168.x.x, 172.16-31.x.x) and reserved ranges. Only publicly routable IPv4 and IPv6 addresses are accepted.
Is traffic routed through ipmap.dev?
No. ipmap.dev is a DNS-only service. All traffic goes directly from clients to your server. We only manage DNS records.
Error Codes
| HTTP Code | Meaning |
|---|---|
| 400 | Bad request — invalid IP, name, or missing required field |
| 401 | Unauthorized — missing or invalid API key |
| 402 | Plan limit reached — upgrade to create more subdomains |
| 404 | Subdomain not found or doesn't belong to your account |
| 429 | Rate limit exceeded — max 60 requests/minute |
| 500 | Internal server error — try again or contact support |
All errors return a JSON body: {"error": "Description of the error"}