Puchify

VPN Gateways API

Site-to-site VPN gateway management.

List VPN gateways

GET /api/v1/vpn-gateways
const { data: gateways } = await puchify.vpnGateways.list({ status: "active" })
gateways = puchify.vpn_gateways.list(status="active")
gateways, err := client.VPNGateways.List(ctx, &puchify.VPNGatewayListParams{
  Status: puchify.String("active"),
})
puchify vpn list --status active
curl https://api.puchify.com/api/v1/vpn-gateways \
  -H "Authorization: Bearer $PUCHIFY_API_KEY"

Query parameters:

ParameterTypeDescription
cursorstringPagination cursor
limitinteger (1-100)Results per page (default 50)
statusstringFilter by status (creating, active, deleting, deleted)
sortname | created_atSort field
orderasc | descSort direction

Create a VPN gateway

POST /api/v1/vpn-gateways
const { data: gateway } = await puchify.vpnGateways.create({
  name: "site-a-vpn",
  region: "us-east",
  tunnel_type: "ipsec",
  remote_network_cidr: "10.0.0.0/16",
  remote_peer_ip: "203.0.113.200",
  pre_shared_key: "•••••••••••",
})
gateway = puchify.vpn_gateways.create(
    name="site-a-vpn",
    region="us-east",
    tunnel_type="ipsec",
    remote_network_cidr="10.0.0.0/16",
    remote_peer_ip="203.0.113.200",
    pre_shared_key="•••••••••••",
)
gateway, err := client.VPNGateways.Create(ctx, &puchify.CreateVPNGatewayInput{
  Name: "site-a-vpn", Region: "us-east",
  TunnelType:       puchify.String("ipsec"),
  RemoteNetworkCIDR: "10.0.0.0/16",
  RemotePeerIP:     "203.0.113.200",
  PreSharedKey:     "•••••••••••",
})
puchify vpn create --name site-a-vpn --region us-east \
  --tunnel-type ipsec --remote-cidr 10.0.0.0/16 --remote-ip 203.0.113.200
curl -X POST https://api.puchify.com/api/v1/vpn-gateways \
  -H "Authorization: Bearer $PUCHIFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"site-a-vpn","region":"us-east","tunnel_type":"ipsec","remote_network_cidr":"10.0.0.0/16","remote_peer_ip":"203.0.113.200","pre_shared_key":"•••••••••••"}'

Request body:

FieldTypeRequiredDescription
namestringyesGateway name (2-40 chars)
regionstringyesRegion ID
tunnel_typeipsec | wireguardyesVPN tunnel protocol
remote_network_cidrstringyesRemote network CIDR block (e.g., 10.0.0.0/16)
remote_peer_ipstringyesPublic IP of the remote VPN peer
pre_shared_keystringnoPSK for IPsec (auto-generated if omitted)
local_network_cidrstringnoLocal network CIDR (defaults to the VPC CIDR)

Get a VPN gateway

GET /api/v1/vpn-gateways/{id}
const { data: gateway } = await puchify.vpnGateways.get("vpn_abc123")
gateway = puchify.vpn_gateways.get("vpn_abc123")
gateway, err := client.VPNGateways.Get(ctx, "vpn_abc123")
puchify vpn get vpn_abc123
curl https://api.puchify.com/api/v1/vpn-gateways/vpn_abc123 \
  -H "Authorization: Bearer $PUCHIFY_API_KEY"

Update a VPN gateway

PATCH /api/v1/vpn-gateways/{id}
const { data: gateway } = await puchify.vpnGateways.update("vpn_abc123", {
  remote_network_cidr: "10.1.0.0/16",
})
gateway = puchify.vpn_gateways.update("vpn_abc123", remote_network_cidr="10.1.0.0/16")
gateway, err := client.VPNGateways.Update(ctx, "vpn_abc123", &puchify.UpdateVPNGatewayInput{
  RemoteNetworkCIDR: puchify.String("10.1.0.0/16"),
})
puchify vpn update vpn_abc123 --remote-cidr 10.1.0.0/16
curl -X PATCH https://api.puchify.com/api/v1/vpn-gateways/vpn_abc123 \
  -H "Authorization: Bearer $PUCHIFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"remote_network_cidr":"10.1.0.0/16"}'

Request body:

FieldTypeRequiredDescription
namestringnoNew gateway name
remote_network_cidrstringnoUpdated remote CIDR block
pre_shared_keystringnoRotate the pre-shared key

Delete a VPN gateway

DELETE /api/v1/vpn-gateways/{id}
await puchify.vpnGateways.delete("vpn_abc123")
puchify.vpn_gateways.delete("vpn_abc123")
err := client.VPNGateways.Delete(ctx, "vpn_abc123")
puchify vpn delete vpn_abc123
curl -X DELETE https://api.puchify.com/api/v1/vpn-gateways/vpn_abc123 \
  -H "Authorization: Bearer $PUCHIFY_API_KEY"

Get tunnel status

GET /api/v1/vpn-gateways/{id}/status
const { data: status } = await puchify.vpnGateways.getStatus("vpn_abc123")
status = puchify.vpn_gateways.get_status("vpn_abc123")
status, err := client.VPNGateways.GetStatus(ctx, "vpn_abc123")
puchify vpn status vpn_abc123
curl https://api.puchify.com/api/v1/vpn-gateways/vpn_abc123/status \
  -H "Authorization: Bearer $PUCHIFY_API_KEY"

Returns live tunnel status including up/down state, bytes transferred, and last handshake time.

Polling for readiness

const gateway = await puchify.vpnGateways.waitFor("vpn_abc123", "active", {
  timeout: 300_000,
  pollInterval: 5_000,
})
gateway = puchify.vpn_gateways.wait_for("vpn_abc123", "active", timeout=300)
gateway, err := puchify.WaitFor(ctx, client.VPNGateways.Get, "vpn_abc123", "active",
  puchify.WithTimeout(5*time.Minute),
)

Response shape

{
  "data": {
    "id": "vpn_abc123",
    "name": "site-a-vpn",
    "status": "active",               // creating | active | deleting | deleted
    "region": "us-east",
    "tunnel_type": "ipsec",
    "local_network_cidr": "172.16.0.0/16",
    "remote_network_cidr": "10.0.0.0/16",
    "remote_peer_ip": "203.0.113.200",
    "local_ip": "203.0.113.150",
    "tunnel_status": "up",
    "bytes_sent": 104857600,
    "bytes_received": 52428800,
    "last_handshake": "2026-05-28T10:35:00Z",
    "created_at": "2026-05-28T10:30:00Z",
    "updated_at": "2026-05-28T10:32:00Z"
  },
  "meta": {
    "persistence": "synced",
    "provider": "connected"
  }
}

Error codes

CodeDescription
404VPN gateway not found
409Conflict — gateway is in a transient state (e.g., provisioning or deleting)
422Invalid CIDR block, peer IP, or tunnel type

On this page