Integration

Push-token API

Ignisfox push targets deliver cert material to your servers via a pull model: your server fetches the latest cert over HTTPS, authenticated by an opaque token. This means Ignisfox never needs inbound access to your network — a huge simplification for firewalled / air-gapped environments.

Create a push target at /dashboard/push; it emits a single token. Install the token in an env var or config file on the target server, then run one of the commands below on whatever schedule makes sense (cron, systemd timer, Windows Task Scheduler).

Endpoint

GET https://www.ignisfox.com/api/push/<TOKEN>/fetch?kind=<KIND>

Path parameters

  • TOKEN — the opaque token shown when you created the push target. Treat it like a password. Rotate any time from the push-targets page.

Query parameters

  • kind=cert — just the leaf certificate (PEM)
  • kind=chain — intermediate chain only (PEM)
  • kind=fullchain — leaf + intermediates (PEM)
  • kind=key — private key (PEM). Only works if the target group has a key attached.
  • kind=pfx — PKCS#12 bundle (binary). Requires a group password to be set.

Linux / macOS — cron

#!/bin/bash
set -euo pipefail

TOKEN='pt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
DEST=/etc/ssl/ignisfox

mkdir -p "$DEST"
curl -sSL -o "$DEST/fullchain.pem.new" \
  "https://www.ignisfox.com/api/push/$TOKEN/fetch?kind=fullchain"
curl -sSL -o "$DEST/privkey.pem.new" \
  "https://www.ignisfox.com/api/push/$TOKEN/fetch?kind=key"

# Atomic swap — only replace if both downloads succeeded
mv "$DEST/fullchain.pem.new" "$DEST/fullchain.pem"
mv "$DEST/privkey.pem.new"   "$DEST/privkey.pem"

systemctl reload nginx

Install at /etc/cron.d/ignisfox-pull with a daily or hourly schedule:

0 3 * * * root /usr/local/bin/ignisfox-pull.sh

Windows — Scheduled Task

PowerShell script (save as C:\ssl\pull.ps1):

$Token = 'pt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
$Dest  = 'C:\ssl'
$Base  = "https://www.ignisfox.com/api/push/$Token/fetch"

New-Item -ItemType Directory -Force -Path $Dest | Out-Null
Invoke-WebRequest "$Base?kind=pfx"  -OutFile "$Dest\server.pfx.new"
Move-Item -Force "$Dest\server.pfx.new" "$Dest\server.pfx"

# Example IIS binding update (adjust site name + thumbprint logic)
Import-Module WebAdministration
Import-PfxCertificate -FilePath "$Dest\server.pfx" `
  -CertStoreLocation Cert:\LocalMachine\My

Register with schtasks:

schtasks /create /sc DAILY /st 03:00 /tn "Ignisfox Pull" ^
  /tr "powershell -NoProfile -ExecutionPolicy Bypass -File C:\ssl\pull.ps1"

Auth + failure modes

  • 401 Unauthorized — token is wrong, rotated, or the target was deleted. Replace the token and retry.
  • 404 Not Found — valid token, but the group doesn't have the requested kind. Check the vault.
  • 429 Too Many Requests — per-target rate limit. Space fetches out (once an hour is plenty).
  • 503 / timeouts — Vercel edge hiccup. Retry with backoff; your script should never delete the existing cert if the fetch fails.

Rotation

To rotate a token, visit /dashboard/push → Rotate on the row. The old token stops working immediately; paste the new one into your server configs and re-run the pull script once to verify.

Recommended schedule

Pull hourly. Ignisfox caches serve the same bytes when nothing changed, so frequent pulls are cheap. That way your servers pick up a rotated cert within an hour of an ACME renewal or a manual upload without you writing any cross-service event plumbing.

Error responses

Every non-2xx response is JSON with an error field describing the cause. Script against these exact shapes so your deploy pipeline can distinguish transient from permanent failures.

401 — bad or missing token

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
  "error": "Missing bearer token. Use Authorization: Bearer <ingest-token>."
}

Likely cause: header not set, or the token was rotated. Rotate again from /dashboard/push and update your server's env file.

404 — cert group or kind doesn't exist

HTTP/1.1 404 Not Found
Content-Type: application/json

{
  "error": "No private key in this cert group"
}

You asked for ?kind=key but the group only has a leaf + chain. Upload the key, or switch to ?kind=fullchain.

429 — rate limited

HTTP/1.1 429 Too Many Requests
Retry-After: 38
Content-Type: application/json

{
  "error": "Too many requests. Slow down and try again in a minute — sorry for the friction, it stops abuse of our public tools."
}

Honour Retry-After. Default cap is 120 requests per minute per IP — normal schedules never hit this. If your whole fleet shares a NAT and does hit it, reach out via Contact Us and we'll raise it.

500 — something went sideways on our side

HTTP/1.1 500 Internal Server Error
Content-Type: application/json

{
  "error": "Handler crashed: <details>"
}

Treat as transient. Retry with exponential backoff (start at 10s). If it persists beyond a few minutes, check our status page or email support — we'll have a Sentry event for it.