A server from start to finish
One continuous run, in the order you would actually do it: a private network, a server with a public address, the firewall in front of it, a backup, and then a clean-up that leaves nothing billable behind. Getting started covers the first token and the first call - this guide assumes you have both.
Every call below was run against a live project. Identifiers in the answers are made up; yours will differ.
1. See what you are working in
curl -H "Authorization: Bearer $FBX_TOKEN" \
https://api.fiberax.com/v1/project
{ "data": { "id": 4711, "name": "my-project", "status": "Active" } }
A token belongs to one project, so this also tells you which project you are about to change. A
suspended project still answers reads, and so does a project whose owner has an unpaid invoice; both
refuse the calls that would create new spending, with 402 - money rather than rights.
What stays allowed is anything that REDUCES the bill: deleting a server, releasing an address,
removing a key or a card, switching scheduled backups off. You are never locked out of lowering your
own costs.
2. A private network
Servers talk to each other over a private network. You get one by default; make your own when you want a separate address range:
curl -X POST -H "Authorization: Bearer $FBX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"backend","cidr":"10.42.0.0/24"}' \
https://api.fiberax.com/v1/networks
{ "data": null,
"task": { "id": "0cd9cb...", "status": "pending", "is_terminal": false,
"poll": "/v1/tasks/0cd9cb..." } }
The network does not exist yet when this returns, and the answer carries no identifier - unlike a server, which is given its number immediately. The work happens on the platform and takes about a minute. Poll the task, then list the networks to learn the new identifier:
curl -H "Authorization: Bearer $FBX_TOKEN" \
https://api.fiberax.com/v1/networks
{ "data": [
{ "id": 325, "name": "Default Network", "cidr": "10.0.0.0/24", "is_default": true,
"server_count": 0, "router": null },
{ "id": 601, "name": "backend", "cidr": "10.42.0.0/24", "is_default": false,
"server_count": 0, "router": null } ] }
3. A server with a public address
Ask for a fresh public address in the same call. The size fields depend on the type - a slider
type takes cores, memory_mb and disk_gb, a plan type takes
plan_id instead:
curl -X POST -H "Authorization: Bearer $FBX_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: backend-01-2026-09-16" \
-d '{
"name": "backend-01",
"server_type_id": 4,
"image": "fcf9f69c8630904c1d6d73a821f4e674",
"cores": 1,
"memory_mb": 1024,
"disk_gb": 10,
"public_ipv4": { "new": true },
"ssh_keys": [13]
}' \
https://api.fiberax.com/v1/servers
The server comes back as creating, and the address it received is already in the
answer:
{ "data": { "id": 11199, "name": "backend-01", "status": "creating", "power": false,
"ipv4": "203.0.113.24",
"ips": [ { "id": 56, "address": "203.0.113.24", "prefix": "/26",
"gateway": "203.0.113.1", "server_id": 11199, "primary": true } ] },
"task": { "id": "89cc0d...", "status": "pending", "is_terminal": false } }
Fields omitted for brevity.
Two things are worth doing here rather than later. Send an Idempotency-Key: if
the connection drops and you repeat the call with the same key, you get the same server back instead
of a second billable one. Note the other side of that: a refusal is remembered under the key as well,
so after fixing the request you need a NEW key - repeating with the old one returns the old refusal. Prefer {"reuse": true} to {"new": true}
once your project has addresses of its own: it takes a free address you already pay for, and only
allocates a new one when there is none.
4. Put it on the private network
A server created with a public address has one card. Add a second one on the network from step 2:
curl -X POST -H "Authorization: Bearer $FBX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"network_id":601}' \
https://api.fiberax.com/v1/servers/11199/network-interfaces
{ "data": { "id": "net1", "public": false, "network_id": 601, "firewall": false, "ips": [] },
"task": { "id": "3ed69d...", "status": "pending", "is_terminal": false } }
Fields omitted for brevity.
The card is named by the platform (net0, net1, ...), and that name is
what you use everywhere else. Reading the cards back shows both:
curl -H "Authorization: Bearer $FBX_TOKEN" \
https://api.fiberax.com/v1/servers/11199/network-interfaces
5. The firewall
The firewall is a state, not a list of commands: you send the whole set of rules you want, and
that is what the server ends up with. It filters the PUBLIC card only - traffic inside a private
network is not touched by it. Reading it always works; switching it ON for a server that has no
public card answers firewall_no_public_iface (409), because there would be nothing to
filter. Read it first - an empty answer is normal for a new server:
curl -H "Authorization: Bearer $FBX_TOKEN" \
https://api.fiberax.com/v1/servers/11199/firewall
{ "data": { "enabled": false, "policy_in": "drop", "policy_out": "accept", "rules": [] } }
Fields omitted for brevity.
Now let SSH and web traffic in, and drop the rest:
curl -X PUT -H "Authorization: Bearer $FBX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"enabled": true,
"policy_in": "drop",
"rules": [
{"direction":"in","action":"accept","enabled":true,"protocol":"tcp",
"destination_port":"22","description":"ssh"},
{"direction":"in","action":"accept","enabled":true,"protocol":"tcp",
"destination_port":"80,443","description":"web"}
]
}' \
https://api.fiberax.com/v1/servers/11199/firewall
Order matters: the first matching rule wins. The note on a rule is called
description; if you call it something else, the answer says so instead of dropping the
field quietly:
{ "status": 422, "code": "invalid_request",
"invalid_params": [ { "name": "rules", "reason": "item 0 contains an unknown field" } ] }
6. A backup before you change anything
curl -X POST -H "Authorization: Bearer $FBX_TOKEN" \
https://api.fiberax.com/v1/servers/11199/backups
{ "data": { "id": "2026-09-16T02:59:49Z", "server_id": 11199, "status": "creating",
"size_bytes": null, "created_at": "2026-09-16T04:59:49+02:00" } }
This call takes no body. The backup is identified by the moment it was taken, and that identifier is what you pass to restore or delete it. It is ready in well under a minute for a small disk - backups are incremental, so the time depends on what changed rather than on the size of the disk.
This is the one operation that does not come with a task, so watch the backup itself: read the
list until its status turns from creating to available, and
size_bytes stops being empty.
curl -H "Authorization: Bearer $FBX_TOKEN" \
https://api.fiberax.com/v1/servers/11199/backups
Backups are billed: by the gigabyte on most types, and at a flat monthly price per server on a
packaged GPU type. Keeping them costs money whether or not the server still exists - see the price
of your type in GET /v1/server-types/{id}/pricing.
Your project may already be taking backups on a schedule. Read the policy of this server to see when the next one is due:
curl -H "Authorization: Bearer $FBX_TOKEN" \
https://api.fiberax.com/v1/servers/11199/backup-policy
{ "data": { "enabled": true, "days": ["mon","tue","wed","thu","fri","sat","sun"],
"hour": 1, "minute": 25, "keep": 7,
"next_run": "2026-09-17T01:25:00+02:00", "last_run": null } }
Fields omitted for brevity.
7. Delete the server
curl -X DELETE -H "Authorization: Bearer $FBX_TOKEN" \
https://api.fiberax.com/v1/servers/11199
{ "data": { "server_id": 11199,
"billable_ips": [ { "id": 56, "address": "203.0.113.24", ... } ] },
"task": { "id": "e3cb0d...", "status": "pending", "is_terminal": false } }
Fields omitted for brevity.
Read billable_ips. Those addresses stay with your project and stay billed
after the server is gone - deleting a server does not release them. The field exists so that this
never comes as a surprise on the invoice.
8. Release the address
Wait until the server is actually gone, then release the address you no longer need:
curl -H "Authorization: Bearer $FBX_TOKEN" \
https://api.fiberax.com/v1/ips
{ "data": [ { "id": 56, "address": "203.0.113.24", "server_id": null, "primary": false } ] }
Fields omitted for brevity.
curl -X DELETE -H "Authorization: Bearer $FBX_TOKEN" \
https://api.fiberax.com/v1/ips/56
{ "data": { "deleted": 56 } }
An address with "server_id": null is attached to nothing and still costs money. If
you plan to create another server soon, keep it and ask for {"reuse": true} next
time - that is exactly what the field is for.
9. And the network
curl -X DELETE -H "Authorization: Bearer $FBX_TOKEN" \
https://api.fiberax.com/v1/networks/601
Answered with a task, like the creation was. A network with servers still on it is refused - take the cards off first.
What to keep in mind
- Deleting a server is not the end of the bill. Public addresses and backups outlive it. The delete answer names the addresses; backups are listed per server until you remove them.
- Tasks tell you the work finished, resources tell you what it finished as. Poll the task
until
is_terminal, then read the server. - Repeat safely. Send an
Idempotency-Keyon every create. A repeat with the same key returns the first answer instead of doing the work twice. - 409 means the state is in the way. Usually you change something and repeat; sometimes
the resource is simply held by a neighbour, and then
Retry-Aftersays how long to wait. Some refusals deliberately carry no such header, because waiting would not help - no free GPU capacity is one of them. Operations on one project are queued, so a parallel script of your own can be the reason you see 409. A503means we could not do it right now: the request was fine, try again later.