IPXO Unified Services API · v1.0.0
Do the most common tasks entirely through the API
Each workflow below is an ordered recipe — real endpoints, in the order an integration calls them. Every request shows its parameters and a sample successful response. Filter by what you do, paste your tenant UUID once, and every sample updates.
Before you begin: authentication and the systems map
All requests go to https://apigw.ipxo.com with an OAuth2 bearer token. The gateway fronts three subsystems with different path shapes — knowing which is which saves most integration confusion.
-
Get an access token
POSThttps://hydra.ipxo.com/oauth2/tokenParameters · 2
Param In Description grant_typeform · required Always client_credentials.scopeform Space-separated: billing,ecommerce,credits,nethub-data. Request only what you need.curl -s -X POST https://hydra.ipxo.com/oauth2/token \ -u "$CLIENT_ID:$CLIENT_SECRET" \ -d "grant_type=client_credentials" \ -d "scope=billing ecommerce credits nethub-data"
200Typical response (OAuth2 protocol-standard shape){ "access_token": "eyJhbGciOiJSUzI1NiIs…", "token_type": "bearer", "expires_in": 3599, "scope": "billing ecommerce credits nethub-data" }# Then send it on every call: curl -s https://apigw.ipxo.com/billing/v1/TENANT_UUID \ -H "Authorization: Bearer $ACCESS_TOKEN"
-
Know the three path shapes
Your API identity is a tenant (company). The Ecommerce and Credits systems call the same identifier
user_id— it's typically the same UUID.System Path shape What lives there Billing / IP Market /billing/v1/{tenantUUID}/…and/billing/v1/common/…Marketplace search, leases, monetization services, payouts, LOAs Ecommerce /ecommerce/public/{user_id}/…Cart, checkout, orders, invoices, payment methods, addresses Credits /credits/public/{user_id}/…Credit balance NetHub /nethub-data/{tenantUUID}/prefixes/…Discovered prefix inventory with WHOIS / geo / BGP / RPKI metadata Sanity check your token and tenant in one call:GET /billing/v1/{tenantUUID}returns the full tenant profile (sample under Tenant setup), including feature flags likeis_lesseeanduses_ecommerce_for_market.Verified from the portal source (2026-07-22): every backend is namespaced at the gateway — Billing at/billing/v1/…, Ecommerce at/ecommerce/public/…, Credits at/credits/public/…. Unprefixed/v1/…or/public/…paths (as in the original spec) appear nowhere in production client code; all paths in this guide include the prefixes. One caveat: the portal configs reference the staging host (apigw.staging.ipxo.org); production hostapigw.ipxo.comis per the spec — confirm before shipping externally.
Lease a subnet, end to end
From marketplace discovery to a paid, active lease: search → reserve → set up billing → checkout → confirm. Announcing the subnet (LOA) is the next workflow.
-
Search the marketplace
GET/billing/v1/{tenantUUID}/market/search?prefix_length=24The primary discovery endpoint. Keep the
pricing.uuid— you need it to reserve.Parameters · 19 · from backend source
Param In Description prefix_lengthquery · required CIDR prefix length, integer 8–24. registrars[]query RIR filter: afrinic,apnic,arin,lacnic,ripencc.price_minquery Numeric > 0. price_maxquery Numeric > 0. price_negotiablequery Boolean — only negotiable listings. promotionalquery Boolean — featured listings. addressquery IPv4 prefix match (mutually exclusive with octets).octets[]query Leading octets as array of ints 0–255 (mutually exclusive with address).geo_country_codequery 2-letter country code. geo_city_namequery 2–100 chars; letters, spaces, hyphens, periods, apostrophes only. geo_providers[]query maxmind,ipgeolocation,dbip,ipregistry,ipinfo,ip2location.geo_provider_match_typequery or(default) orand— how geo filters combine across providers.capabilities_rpki[]query automated,manual,unsupported.capabilities_whois_inetnum[]query Same values. capabilities_whois_routes[]query Same values. capabilities_whois_rdns[]query Same values. reservation_idquery Commitment reservation ID. limitquery 1–1000, default 100. sort[]query price,-price,address,-address(dash = descending).Recovered from the backend request validation (SearchRequest::rules), 2026-07-22 — the original spec documented only
prefix_length. Note there is no server-side pagination: the portal sendslimit=1000and pages client-side.curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/search?prefix_length=24&geo_country_code=US®istrars%5B%5D=arin&sort%5B%5D=price&limit=100" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Sample response (excerpt){ "data": [{ "notation": "40.183.32.0/24", "address_string": "40.183.32.0", "prefix_length": 24, "registrar": "arin", "pricing": { "uuid": "9df98051-0e47-4be7-96c2-f73101b010a2", "price": 215.51, "negotiable": false }, "geo_data": { "maxmind": { "country_code": "US" }, "ipinfo": { "city_name": "New York City" } }, "capabilities": { "rpki": "manual", "whois": { "inetnum": "automated", "rdns": "unsupported" } } }] }Alternative:GET /billing/v1/{tenantUUID}/market/ipv4?cidr=24returns price tiers per billing cycle, e.g."price": { "1": 39, "3": 117, "6": 234, "12": 468, "24": 936 }. Its filter set (from backend source): requiredcidr8–24, plusregistry(RIPENCC|LACNIC|AFRINIC|ARIN|APNIC) orregistrar_uuids[],price_min/price_max,wants_to_negotiate,address/octets[],geo_databases[](maxmind, ip2location, dbip, ipinfo),geo_country_code,geo_city_name,limit(10–1000),sort[]. -
Reserve the subnet
POST/billing/v1/{tenantUUID}/market/ipv4/services/reserveHolds the subnet so nobody else can lease it while you complete checkout.
Parameters · 2
Param In Description pricing_uuidbody UUID of the pricing entry from the search result. billing_cyclebody Cycle in months: 1, 3, 6, 12, or 24. curl -s -X POST "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/ipv4/services/reserve" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{ "pricing_uuid": "9df98051-0e47-4be7-96c2-f73101b010a2", "billing_cycle": 1 }'200Response shape · from backend source{ "uuid": "RESERVATION_UUID", "address": "40.183.32.0", "cidr": 24, "price": 215.51, "commitment_period": 1, "created_at": 1769731200 }Already reserved by someone else →
409"Subnet is already reserved". -
Create a billing address (first purchase only)
POST/ecommerce/public/{user_id}/addressesStored once, reused on every later cart and order. List existing ones with
GETon the same path.Parameters · 11
Param In Description company_namebody · required Legal company name (max 150). line_onebody · required Street address line 1 (2–100 chars). line_twobody Street address line 2. citybody · required City (max 90). province_codebody State/province code (e.g. TX, NY); must exist for the country. country_codebody · required ISO 3166-1 alpha-2 code; must match the tenant's country. postcodebody · required Postal code (max 20). contact_emailbody Billing contact email (optional despite spec examples). contact_phonebody Billing contact phone. vat_numberbody VAT number (validated; see vat_validation_statuson the stored address).company_codebody Company registration code. curl -s -X POST "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/addresses" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{ "company_name": "Acme Corp", "line_one": "123 Main St", "city": "New York", "province_code": "NY", "country_code": "US", "postcode": "10001", "contact_email": "[email protected]" }'
200Returns the created address including its
uuid(from backend source). One billing address per customer — a second create fails; required flags above are from the backend validation. -
Register a payment method (first purchase only)
GET/ecommerce/public/{user_id}/gatewaysList available gateways to get the gateway config UUID — for Stripe it includes the publishable key for client-side tokenisation.
curl -s "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/gateways" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Sample response{ "data": [ { "uuid": "9e072516-8236-4fa7-be0c-9de0b1c47c67", "gateway": "stripe", "config": { "public_key": "pk_test_51IQTJqEZwbJqxJ4z…" } }, { "uuid": "9e072516-8236-4fa7-be0c-9de0b1c47c68", "gateway": "paypal", "config": null } ], "meta": { "current_page": 1, "total": 2, "per_page": 10 } }POST/ecommerce/public/{user_id}/gateways/{gatewayConfig_uuid}/{paymentMethodType}Parameters · 2
Param In Description gatewayConfig_uuidpath · required Gateway configuration UUID from the list above. paymentMethodTypepath · required Type to add: cardorpaypal.curl -s -X POST "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/gateways/GATEWAY_CONFIG_UUID/card" \ -H "Authorization: Bearer $ACCESS_TOKEN"204Payment method registered. No response body.
-
Build the cart
GET/ecommerce/public/{user_id}/cartGet-or-create: returns the customer's active cart, creating one if none exists — this is where
cart_uuidcomes from. There is no explicit create-cart endpoint, by design.curl -s "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/cart" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Response shape · from backend source{ "data": { "uuid": "CART_UUID", "total": { … }, "sub_total": { … }, "tax_total": { … }, "credits_total": { … }, "discount_total": { … }, "remaining_total": { … }, "tax_breakdown": [ … ], "discount_breakdown": [ … ], "expires_at": "…" } }POST/ecommerce/public/{user_id}/cart/{cart_uuid}/linesParameters · 3
Param In Description cart_uuidpath · required UUID from the GET …/cartcall above.price_idbody · required UUID of the pricing entry to add. quantitybody Units to add; defaults to 1. curl -s -X POST "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/cart/CART_UUID/lines" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{ "price_id": "PRICE_UUID", "quantity": 1 }'200Returns the created cart line —
uuid,title,quantity,unit_price,sub_total,tax_total,total, billingperiod(from backend source).POST/ecommerce/public/{user_id}/cart/{cart_uuid}/addresses/{customerAddress_id}Parameters · 2
Param In Description cart_uuidpath · required Cart UUID. customerAddress_idpath · required Numeric ID of the address created in step 3. curl -s -X POST "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/cart/CART_UUID/addresses/ADDRESS_ID" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Returns the associated address (same AddressResource shape as step 3) — from backend source.
PATCH/ecommerce/public/{user_id}/cart/{cart_uuid}/payment-method/{paymentMethod_uuid}Parameters · 2
Param In Description cart_uuidpath · required Cart UUID. paymentMethod_uuidpath · required UUID of the registered payment method (step 4). curl -s -X PATCH "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/cart/CART_UUID/payment-method/PAYMENT_METHOD_UUID" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Returns the updated cart with recalculated totals (from backend source).
Resolved 2026-07-22: the previously flagged "no create-cart endpoint" gap isn't one —GET …/cartabove creates the cart implicitly (CartManager::getOrCreateCurrent). Worth a one-line confirmation from dev that this implicit contract is supported for external integrators. Optional: apply a promo code withPOST …/cart/{cart_uuid}/discount-code/{code}(200 with updated totals, or 204). -
Checkout
POST/ecommerce/public/{user_id}/cart/{cart_uuid}/checkoutCharges the selected payment method, creates the order and invoice, and consumes the cart. Gateway processing fees appear as separate order lines.
curl -s -X POST "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/cart/CART_UUID/checkout" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Response shape · from backend source{ "data": { "order": { "uuid": "ORDER_UUID", "status": "…", "placed_at": "…", "expires_at": "…", "sub_total": { … }, "tax_total": { … }, "total": { … }, "remaining_total": { … } }, "data": <payment-gateway response, null when fully covered by credits> } }The
order.uuidhere is what you use with the orders endpoints below. -
Confirm the lease is active
GET/billing/v1/{tenantUUID}/market/ipv4/servicesYour new lease appears as a billing service with
status: "active"and theserviceUUIDyou'll use for LOAs and termination.curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/ipv4/services" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Sample response (excerpt){ "data": [{ "billing_service": { "address": "68.164.7.0", "cidr": 24, "recurring_amount": 115, "status": "active", "next_due_date": 1775088000, "uuid": "a0f616fb-e93c-4371-b75c-c16ad8483a44", "pricing": { "uuid": "a0222aaf-5e33-4903-bccd-80f171c81ba4", "wants_to_negotiate": false } }, "loa": [{ "uuid": "a0fff148-29a1-4d52-9c2a-43a860bd9e2c", "asn": 213060, "as_name": "IPXO-Testing-ASN", "status": "Active" }], "market_service": { "expires_at": null, "registry": "arin", "uuid": "a0222aaf-3da0-41a5-ac6f-15e256f3e2e0" } }] }
Validate your ASN and get LOA documents
Before you can announce a leased subnet from your network, the ASN–subnet pair is validated and a Letter of Authorization is issued.
-
Check the ASN is clean
GET/billing/v1/common/asn/validate/{asn}Parameters · 1
Param In Description asnpath · required Autonomous System Number to validate (integer). curl -s "https://apigw.ipxo.com/billing/v1/common/asn/validate/13335" \ -H "Authorization: Bearer $ACCESS_TOKEN"
200Sample response{ "asn": 13335, "valid": true, "as_name": "CLOUDFLARENET - Cloudflare, Inc.", "uce3": false, "ofac": false, "spamhaus": false, "country": "US", "status": "active" } -
Validate the subnet–ASN pair
POST/billing/v1/{tenantUUID}/asn/validate/{asn}Checks route-origin authorization, RPKI validity, and registry records before an LOA is generated.
Parameters · 2
Param In Description asnpath · required ASN to validate the subnets against. subnetsbody Array of CIDR notations, e.g. ["68.164.7.0/24"].curl -s -X POST "https://apigw.ipxo.com/billing/v1/TENANT_UUID/asn/validate/213060" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{ "subnets": ["68.164.7.0/24"] }'200Response shape · from backend source{ "asn": 213060, "valid": true, "as_name": "…", "country": "…", "ofac": false, "spamhaus": false, "uce3": false, "status": "active", "subnets": [ { "subnet": "68.164.7.0/24", "already_added": false } ] }Unknown ASN →
404. -
List and download LOAs
GET/billing/v1/{tenantUUID}/market/ipv4/services/{serviceUUID}/loaParameters · 1
Param In Description serviceUUIDpath · required UUID of the leased Billing IPv4 service. curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/ipv4/services/SERVICE_UUID/loa" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Sample response{ "data": [{ "uuid": "a0fff148-29a1-4d52-9c2a-43a860bd9e2c", "asn": 213060, "as_name": "IPXO-Testing-ASN Internet Utilities Europe and Asia Limited", "status": "Active", "created_at": 1770211251 }], "meta": { "current_page": 1, "from": 1, "last_page": 1, "per_page": 15, "to": 1, "total": 1 } }curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/ipv4/services/SERVICE_UUID/loa/download" \ -H "Authorization: Bearer $ACCESS_TOKEN" -o loa-documents.zip200Binary
application/ziparchive of LOA PDFs. -
Revoke LOAs when re-homing (as needed)
POST/billing/v1/{tenantUUID}/market/ipv4/services/loa/revokeBulk-revokes LOAs across subnets. After revocation the previous ASN authorization is invalid — generate new LOAs before re-announcing.
curl -s -X POST "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/ipv4/services/loa/revoke" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{ "services_uuids": ["SERVICE_UUID"] }'200Empty (null) body. The body field is
services_uuids[]— the service UUIDs whose LOAs to revoke (from backend source).
Monitor, export, and terminate leases
Day-2 operations on active leases: inspect details and geodata, export for accounting, and end a lease the right way.
-
Inspect a single lease
GET/billing/v1/{tenantUUID}/market/ipv4/services/{serviceUUID}Parameters · 1
Param In Description serviceUUIDpath · required UUID of the leased Billing IPv4 service. curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/ipv4/services/SERVICE_UUID" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Sample response{ "billing_service": { "address": "68.164.7.0", "cidr": 24, "recurring_amount": 115, "status": "active", "start_date": 1769731200, "uuid": "a0f616fb-e93c-4371-b75c-c16ad8483a44", "ecommerce_subscription_uuid": "a0f61706-f2a4-45d3-8fcb-842da1541566" }, "commitment": null, "pending_commitment": null, "market_service": { "expires_at": null, "registry": "arin", "uuid": "a0222aaf-3da0-41a5-ac6f-15e256f3e2e0" }, "termination_request": null }Geolocation often differs by provider — check all six transparently:
curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/ipv4/services/SERVICE_UUID/geodata" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Sample response (excerpt){ "data": { "maxmind": { "country_code": "US", "country_name": "United States", "state": "", "city_name": "" }, "ipinfo": { "country_code": "US", "country_name": "United States", "state": "Illinois", "city_name": "Chicago" }, "ip2location": { "country_code": "US", "country_name": "United States of America", "state": "Virginia", "city_name": "McLean" }, "dbip": { "country_code": "US", "country_name": "United States", "state": "California", "city_name": "San Jose" } } } -
Export your portfolio to CSV
GET/billing/v1/{tenantUUID}/market/ipv4/csvcurl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/ipv4/csv" \ -H "Authorization: Bearer $ACCESS_TOKEN" -o leases.csv200
text/csvfile: subnet address, CIDR, status, billing amounts, service dates. -
Terminate at end of billing cycle (default)
POST/ecommerce/public/{user_id}/subscriptions/{subscription_uuid}/terminateEnd-of-cycle termination goes through the subscription, not the billing service. The lease stays active until the cycle ends, then terminates. Find the subscription first:
curl -s -X POST "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/subscriptions/search" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{ "filter": { "status": "active" }, "per_page": "100" }'curl -s -X POST "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/subscriptions/SUBSCRIPTION_UUID/terminate" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{ "type": "end_of_period", "reason": "Pricing", "details": "Cancellation reason" }'200Creates a pending termination request; cancellable via
/subscriptions/termination-requests/{uuid}/canceluntil the period ends. (The former…/services/{serviceUUID}/terminate_requestendpoint was removed from the gateway.) -
Terminate immediately (exceptional cases)
GET/billing/v1/common/termination-reasonsImmediate termination requires a valid reason UUID — fetch the list first.
curl -s "https://apigw.ipxo.com/billing/v1/common/termination-reasons" \ -H "Authorization: Bearer $ACCESS_TOKEN"
200Sample response (excerpt){ "data": [ { "uuid": "86ee68ff-bead-462f-ad51-8c38225c6f61", "title": "Unauthorized 3rd party announcement" }, { "uuid": "6a5abe4a-d8ac-4398-94c8-d94ca3c72bc3", "title": "The Subnet has been added to significant blocklist databases, such as Barracuda, Spamhaus, Spamcop, etc." }, { "uuid": "84a4e2b8-8708-4fea-9c57-1b157a121389", "title": "ROA (Route Origin Authorization) is not generated within 48 hours after the assignment date." } ] }POST/billing/v1/{tenantUUID}/market/ipv4/services/{serviceUUID}/immediate-terminationParameters · 2
Param In Description serviceUUIDpath · required UUID of the leased service. reason_uuidbody UUID of a termination reason from the list above. curl -s -X POST "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/ipv4/services/SERVICE_UUID/immediate-termination" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{ "reason_uuid": "86ee68ff-bead-462f-ad51-8c38225c6f61" }'200Returns
{ "status": "SUCCESS" }; the subnet enters quarantine (from backend source).Track quarantined subnets withGET /billing/v1/{tenantUUID}/market/ipv4/quarantine— a paginated list ({ data, meta }) of subnets in the post-termination cooling-off period.
Orders, invoices, and credit balance
Everything finance asks for: what was charged, what's outstanding, and the PDFs.
-
Check your credit balance
GET/credits/public/{user_id}/balancesParameters · 1
Param In Description filter[currency]query ISO 4217 currency code, e.g. USD,EUR.curl -s "https://apigw.ipxo.com/credits/public/TENANT_UUID/balances?filter%5Bcurrency%5D=USD" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Sample response{ "data": [{ "available_balance": 9274.14, "total_balance": 9274.14, "currency": "USD", "updated_at": "2026-03-02T05:46:24+00:00" }] } -
Review orders and transactions
GET/ecommerce/public/{user_id}/ordersParameters · 1
Param In Description filter[status]query completed,expired, orpending.curl -s "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/orders?filter%5Bstatus%5D=completed" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Sample response (excerpt){ "data": [{ "uuid": "a0f616f9-6c9c-4d08-9176-3eae6a2a1d7e", "status": "completed", "placed_at": "2026-01-30T15:47:58+00:00", "sub_total": { "currency": "USD", "amount": "119.60", "amount_minor": 11960 }, "total": { "currency": "USD", "amount": "119.60", "amount_minor": 11960 }, "remaining_total": { "currency": "USD", "amount": "0.00", "amount_minor": 0 } }] }Drill into a specific order — line items via
…/orders/{uuid}/lines(gateway fees appear as separate lines), payments via:curl -s "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/orders/ORDER_UUID/transactions" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Sample response{ "data": [{ "uuid": "a0f616f9-bc48-4dd9-be48-dd76c8a9f067", "type": "charge", "status": "completed", "gateway_driver": "stripe", "amount": { "currency": "USD", "amount": "119.60", "amount_minor": 11960 }, "reference": "pi_3SvJvPEZwbJqxJ4z1HprQUmp", "created_at": "2026-01-30T15:47:58+00:00" }], "meta": { "current_page": 1, "total": 1, "per_page": 10 } } -
Recover a failed payment
PATCH/ecommerce/public/{user_id}/orders/{publicOrder}/payment-methods/{paymentMethod_uuid}Swap the payment method on the pending order:
curl -s -X PATCH "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/orders/ORDER_UUID/payment-methods/PAYMENT_METHOD_UUID" \ -H "Authorization: Bearer $ACCESS_TOKEN"204Payment method updated on the order. No response body.
Then re-run payment:
curl -s -X POST "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/orders/ORDER_UUID/checkout" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Same shape as cart checkout —
{ "data": { "order": { uuid, status, totals… } } }plus the payment-gateway response (from backend source). -
Fetch invoices and PDFs — from both systems
GET/ecommerce/public/{user_id}/invoicesParameters · 2
Param In Description sortquery Sort field and direction, e.g. -placed_atfor newest first.filter[status]query paid,unpaid, orrefunded.curl -s "https://apigw.ipxo.com/ecommerce/public/TENANT_UUID/invoices?sort=-placed_at&filter%5Bstatus%5D=paid" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Sample response (excerpt){ "data": [{ "uuid": "a0f61705-0fad-4a80-b132-fe3554a6145a", "reference": "C4E00DCB-000001", "status": "paid", "placed_at": "2026-01-30T15:48:06+00:00", "sub_total": { "currency": "USD", "amount": "115.00", "amount_minor": 11500 }, "total": { "currency": "USD", "amount": "115.00", "amount_minor": 11500 }, "invoicable_id": "a0f616f9-6c9c-4d08-9176-3eae6a2a1d7e", "invoicable_type": "order" }] }Line items via
…/invoices/{uuid}/lines; the PDF via…/invoices/{uuid}/download. Billing-system invoices (marketplace charges) live separately:# billing-system invoices: single PDF or all-in-one export curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/invoices/INVOICE_UUID/pdf" \ -H "Authorization: Bearer $ACCESS_TOKEN" -o billing-invoice.pdf curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/invoices/export/pdf" \ -H "Authorization: Bearer $ACCESS_TOKEN" -o all-invoices.pdf
200Binary
application/pdffile(s).
List a prefix for monetization
From "is my prefix eligible?" to a verified, live marketplace listing.
-
Check the prefix is eligible
POST/billing/v1/common/market/subnetValidityParameters · 1
Param In Description prefixesbody · required Array of CIDR notations to validate, e.g. ["68.164.7.0/24"].curl -s -X POST "https://apigw.ipxo.com/billing/v1/common/market/subnetValidity" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{ "prefixes": ["68.164.7.0/24"] }'200Sample response[{ "address": "68.164.7.0", "cidr": 24, "status": true, "message": "", "minimum_split": 24, "maximum_split": 24, "registry": "arin" }] -
Understand commission before pricing
GET/billing/v1/common/pricing/commissionsMinimum commission, minimum per-IP price, and commission factor per CIDR size — price the listing above the floor.
curl -s "https://apigw.ipxo.com/billing/v1/common/pricing/commissions" \ -H "Authorization: Bearer $ACCESS_TOKEN"
200Sample response (excerpt){ "configuration": { "commission": { "24": { "min_commission": 9, "min_ip_price": 0.035, "commission_factor": 0.15 }, "23": { "min_commission": 18, "min_ip_price": 0.035, "commission_factor": 0.15 }, "16": { "min_commission": 2294, "min_ip_price": 0.035, "commission_factor": 0.15 } } } } -
Create the monetization service
POST/billing/v1/{tenantUUID}/market/servicesLists the prefix on the marketplace and triggers an ownership-verification email. Body recovered from the backend validation (AddToMarketRequest::rules), 2026-07-22:
curl -s -X POST "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/services" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{ "subnets": [{ "address": "68.164.7.0", "cidr": 24, "registry": "arin", "minimum_split": 24, "maximum_split": 24, "pricings": [{ "cidr": 24, "value": 115, "wants_to_negotiate": false }] }], "tos_accepted": true, "subnet_actions_accepted": true }'201Created — returns the service collection; verification email sent.
Body rules (from backend source): per subnet —address(IPv4),cidr8–24,registryall required; optionalhidden, split bounds 8–24, APNICmaintainer_id/maintainer_password. Per pricing —cidr+value(0 < value < 999999) required;selected_commitment_periods[]from3, 6, 12, 24, 36, 60, 120months, and it must be non-empty whenwants_to_negotiateis true (empty when false). Top-leveltos_acceptedandsubnet_actions_acceptedmust both be true. Pricing must cover every allowed split size. -
Verify ownership
GET/billing/v1/common/market_auth_verify/{token}Parameters · 1
Param In Description tokenpath · required Verification token from the ownership-confirmation email. curl -s "https://apigw.ipxo.com/billing/v1/common/market_auth_verify/VERIFICATION_TOKEN" \ -H "Authorization: Bearer $ACCESS_TOKEN"
200Service verified and activated. Body not documented in the spec.
Didn't get the email?
POST /billing/v1/{tenantUUID}/market/services/{ipmarketServiceUUID}/resend_verification(200 = resent; only valid while the service is pending verification). -
Confirm the listing is healthy
GET/billing/v1/{tenantUUID}/market/services/{ipmarketServiceUUID}/statusOne report covering operational state, ownership auth, WHOIS, BGP, DNS, IP reputation (blocklists), and the LOA-A. Note: despite the spec's description, there is no RPKI field in this response.
curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/services/MARKET_SERVICE_UUID/status" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Response shape · from backend source{ "abuse_email": "…", "registry": "arin", "status": "validity_active", "auth": { "type": "…", "status": "…", "description": "…" }, "whois": { "status": "…", "description": "…" }, "bgp": { "status": "…", "description": "…" }, "dns": { "status": "…", "description": "…" }, "iprep": { "status": "…", "description": "…" }, "loaa": { "status": "…", "description": "…" } }Top-level
statusvalues:auth_pending,auth_failed_verify(±email variants),validity_pending,validity_active,validity_invalid,validity_terminated,object_terminated.Check what lessees will see with
GET …/{ipmarketServiceUUID}/pricing(200; per-IP/per-subnet price, billing cycles, negotiability).
Manage listings and child subnets
Reprice, control which sub-allocations are visible, audit changes, and retire listings.
-
Update pricing or terms
PATCH/billing/v1/{tenantUUID}/market/services/{ipmarketServiceUUID}Partial update — every field optional (from backend source):
hidden,minimum_split/maximum_split(8–24),pricings[](include a pricing'suuidto update it; each entry needscidr+value, optionalwants_to_negotiate+selected_commitment_periods[]),maintainer_id/maintainer_password. Only allowed while the service is in auth-pending or validity states. See lessee-facing pricing viaGET …/pricing, and what active lessees currently pay viaGET …/leased.200Returns the updated service resource (from backend source).
-
Control child-subnet visibility
GET/billing/v1/{tenantUUID}/market/ipv4/child/searchParameters · 3
Param In Description addressquery · required Base IP of the parent subnet, e.g. 68.164.7.0.cidrquery · required CIDR mask of the parent subnet, e.g. 24.market_service_uuidquery · required UUID of the parent market service. curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/ipv4/child/search?address=68.164.7.0&cidr=24&market_service_uuid=MARKET_SERVICE_UUID" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Available child sub-allocations. Body shape not documented in the spec.
POST/billing/v1/{tenantUUID}/market/ipv4/child/toggleParameters · 2
Param In Description market_service_uuidbody UUID of the parent monetization service. childrenbody Array of child subnet identifiers to hide/unhide. curl -s -X POST "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/ipv4/child/toggle" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{ "market_service_uuid": "MARKET_SERVICE_UUID", "children": [ … ] }'200Visibility toggled. Body not documented in the spec.
Audit what's hidden:
GET …/market/services/{uuid}/ipv4/hidden/children?page=1&per_page=25—pageandper_pageare both required query params. -
Audit every change with event logs
GET/billing/v1/{tenantUUID}/market/services/event_logsUnified audit trail across all your listings — activations, terminations, pricing updates, lease assignments. Per-service logs at
…/market/services/{uuid}/event_logs; full portfolio export at…/market/services/csv.curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/services/event_logs" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Paginated
{ data, meta }; each entry (from backend source):label,type(pricing_updated | pricing_created | leased | released | created),datapayload,created_atunix timestamp. No actor field. -
Extend or retire a listing
DELETE/billing/v1/{tenantUUID}/market/services/{ipmarketServiceUUID}/expirationCancels a scheduled expiration so the listing keeps running.
200Expiration cancelled; service continues.
To take the prefix off the marketplace entirely,
DELETE …/market/services/{ipmarketServiceUUID}(200 = cancellation initiated) — active leases may run until their cycle ends depending on the termination policy.
Get paid: payouts, invoices, deductions
Configure where money goes, watch earnings accrue, and pull the accounting paperwork.
-
Set your payout method (once)
PUT/billing/v1/{tenantUUID}/market/payoutmethodBank transfer, PayPal, or platform credits.
GETon the same path shows the current configuration — a 404 means none is configured yet.Parameters · from backend source
Param In Description typebody · required banktransfer,paypal, orcredit.cyclebody · required Payout cycle in months: 0, 1, 3, 6, 12(0 = on demand).details.beneficiary / address / bic / iban / bank_namebody All required when type=banktransfer.details.emailbody Required when type=paypal.minimal_amountbody Floor is $1,000 for bank/PayPal, $0 for credits (enforced when cycle=0).curl -s -X PUT "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/payoutmethod" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{ "type": "paypal", "cycle": 1, "details": { "email": "[email protected]" } }'
200Returns the payout-method resource (from backend source).
-
Track earnings
GET/billing/v1/{tenantUUID}/market/payouts/stats/v2Total sales, net payout after commission, and a per-period breakdown (prefer v2 over v1). CSV twin:
GET …/stats/v2/export.curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/payouts/stats/v2" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Sample response (new tenant — empty book){ "period": { "from": null, "to": null }, "total_sales": 0, "total_net_payout": 0, "data": [] }Individual payouts with status and self-billing invoice reference:
GET …/market/payouts(paginated{ data, meta }); single payout detail at…/market/payouts/{payoutUuid}. -
Pull self-billing invoices for accounting
GET/billing/v1/{tenantUUID}/market/payouts_invoicesIPXO issues these on your behalf each payout period.
curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/payouts_invoices" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Paginated envelope
{ "data": […], "meta": { current_page, last_page, per_page, total } }.Per invoice Endpoint PDF document GET …/payouts_invoices/{uuid}/pdfPer-lease items (gross / commission / net) GET …/payouts_invoices/{uuid}/itemsAggregated totals GET …/payouts_invoices/{uuid}/statsBulk CSV of all invoices GET …/payouts_invoices/export/csvPayment receipts (issued when IPXO sends the money):
GET …/market/payment_confirmations, each with a/pdf. -
Reconcile commission deductions
GET/billing/v1/{tenantUUID}/market/deductionsMarketplace fees charged against earnings — amount, associated service, billing period.
curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/deductions" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Paginated envelope
{ "data": […], "meta": … }. Invoice PDFs at…/market/deductions/invoices/{invoiceUUID}/pdf.
Prefix inventory and metadata (NetHub)
Search your discovered prefix estate with enriched WHOIS / geo / BGP / RPKI data, and organize it with custom metadata. Path shape: /nethub-data/{tenantUUID}/prefixes/… — the gateway namespace is nethub-data (verified against the production gateway extract, 2026-08).
-
Search prefixes with field selection
POST/nethub-data/{tenantUUID}/prefixes/searchParameters · 5
Param In Description fieldsbody Data objects to include: geodata,whois,bgp,rpki,routes; dot-notation sub-fields likewhois.inetnum,routes.origin.geodatabody Filter object { field, op, vals }; ops:eq, ne, gt, gte, lt, lte, and.whoisbody Filter object { field, op, vals }, same operators.limitbody Max prefixes to return — recommended for large estates. offsetbody Prefixes to skip (pagination). curl -s -X POST "https://apigw.ipxo.com/nethub-data/TENANT_UUID/prefixes/search" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{ "fields": ["geodata", "whois.inetnum", "whois.organisation", "whois.country"], "geodata": { "field": "countryCode", "op": "eq", "vals": ["US"] }, "limit": 50, "offset": 0 }'200Sample response (excerpt){ "data": [{ "notation": "185.139.0.0/22", "maskSize": 22, "internalMetadata": { "master": true, "holder": { "tenantUUID": "c4a84238-3a89-43f0-8a83-8d5edc9c8c65", "organisation": "ORG-CAF4-RIPE" } }, "geodata": [ { "provider": "dbip", "countryCode": "DE", "cityName": "Frankfurt am Main" }, { "provider": "maxmind", "countryCode": "DE", "cityName": "Frankfurt am Main" } ], "whois": { "inetnum": "185.139.0.0/22", "registrar": "ripencc", "netname": "AE-CYBERASSETS-20160216", "country": "AE", "organisation": "ORG-CAF4-RIPE" } }], "metadata": { "limit": 50, "offset": 0 } } -
Tag a single prefix
PATCH/nethub-data/{tenantUUID}/prefixes/{notation}/metadataParameters · 2
Param In Description notationpath · required CIDR notation with the slash URL-encoded: 192.168.1.0/24→192.168.1.0%2F24.(free-form) body Any key-value pairs to set on the prefix holder — labels, project IDs, regions. curl -s -X PATCH "https://apigw.ipxo.com/nethub-data/TENANT_UUID/prefixes/185.139.0.0%2F22/metadata" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{ "projectID": "proj-12345", "label": "CDN Edge Range", "region": "EU-WEST" }'200Metadata set on the prefix holder. No response body documented.
-
Bulk-tag by organisation, and manage list-valued tags
PATCH/nethub-data/{tenantUUID}/prefixes/metadataParameters · 2 (array items)
Param In Description organisationbody RIR organisation handle identifying the holder, e.g. ORG-CAF4-RIPE.metadatabody Key-value pairs to set on that holder. Request body is an array of these entries. curl -s -X PATCH "https://apigw.ipxo.com/nethub-data/TENANT_UUID/prefixes/metadata" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '[{ "organisation": "ORG-CAF4-RIPE", "metadata": { "projectID": "proj-12345", "label": "Production Ranges" } }]'200Metadata set on the specified holders. No response body documented.
For multi-valued fields (tags, contacts), use the
…/metadata/arrayendpoints — POST appends (field,value), PATCH replaces by value (old_value→new_value), DELETE removes:curl -s -X POST "https://apigw.ipxo.com/nethub-data/TENANT_UUID/prefixes/metadata/array" \ -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '[{ "organisation": "ORG-CAF4-RIPE", "field": "tags", "value": "production" }]'200Elements appended to the metadata arrays. Single-prefix variants exist at
…/prefixes/{notation}/metadata/array. -
Track bulk jobs and cloud integrations
GET/billing/v1/{tenantUUID}/batchesBulk imports and mass updates run asynchronously as batches with status and progress.
200Paginated envelope
{ "data": […], "meta": … }of batch operations.AWS BYOIP connected accounts (for provisioning leased subnets into EC2/ELB):
GET /billing/v1/{tenantUUID}/integrations/aws/connected-accounts→ 200 with{ "data": […] }, empty if none configured.
Reputation and listing health
Watch blocklists before they become a support ticket, and read the market before you price.
-
Review reputation scan history
GET/billing/v1/{tenantUUID}/market/services/{ipmarketServiceUUID}/reputationsScan history against Spamhaus, Barracuda, and other blocklists / abuse databases — the deliverability health signal for monetized space.
curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/market/services/MARKET_SERVICE_UUID/reputations" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Response shape · from backend source{ "data": [ { "id": "…", "ip": "…", "ip_int": …, "country_code": "…", "detection_rate": …, "detections": …, "detections_engine_list": [ … ], "engines_count": …, "is_listed": false, "is_proxy": false, "is_tor": false, "is_vpn": false, "isp": "…", "session_id": "…", "created": 1769731200 } ], "meta": { … } } -
Diagnose announcement issues
GET/billing/v1/{tenantUUID}/market/services/{ipmarketServiceUUID}/statusThe same status report used at listing time doubles as the diagnostic when BGP, WHOIS, DNS, or reputation drift out of shape.
200Shape shown under List a prefix step 5 —
auth / whois / bgp / dns / iprep / loaasub-objects; no RPKI field (from backend source). -
Read market supply and pricing
GET/billing/v1/common/market/subnetUsageFree vs in-use counts and min/max/avg per-IP pricing by mask size — market intelligence for pricing decisions.
curl -s "https://apigw.ipxo.com/billing/v1/common/market/subnetUsage" \ -H "Authorization: Bearer $ACCESS_TOKEN"
200Sample response (excerpt)[ { "mask": 24, "free": 15430, "in_use": 1250, "price_min": 0.15, "price_max": 2.50, "price_avg": 0.45, "period": "2025-07-01 00:00:00" } ]Supported registries with their UUIDs (used in search results):
GET /billing/v1/common/market/registrars→ 200, e.g.[{ "uuid": "6220a691…", "name": "arin" }, { "name": "ripencc" }, …].
Tenant setup and reference data
Create and maintain the company account behind every other call.
-
Create and inspect the tenant
POST/billing/v1Creates the tenant and returns the UUID used in every subsequent call. Required fields (from backend source):
title,email,address1,city,country(alpha-2),postcode,state,abuse_email,industry_uuid, andoptions.website(https URL). Optional:company_size,business_since,vat_number,options.social_network[], prorata settings.201Created — returns the tenant resource including its
uuid(from backend source).GET/billing/v1/{tenantUUID}curl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Sample response (excerpt){ "uuid": "a0f5bdf6-499d-4679-9831-a9677abeed5c", "title": "Acme Corp", "email": "[email protected]", "address1": "123 Main St", "city": "New York", "postcode": "10001", "country": "US", "state": "New York", "status": "active", "abuse_email": "[email protected]", "industry": { "uuid": "cac34d86-00c5-11ec-87f1-cc8741ada327", "name": "Cloud Provider" }, "credit": { "amount": 9274.14, "auto_payment": true }, "flags": [ { "slug": "uses_ecommerce_for_market" }, { "slug": "is_lessee" } ], "email_verified": true, "abuse_email_verified": true }Update profile fields with
PATCH /billing/v1/{tenantUUID}— only provided fields change (200 on success). -
Get the at-a-glance numbers
GET/billing/v1/{tenantUUID}/detailscurl -s "https://apigw.ipxo.com/billing/v1/TENANT_UUID/details" \ -H "Authorization: Bearer $ACCESS_TOKEN"200Sample response{ "monetizing_ips_count": 0, "renting_ips_count": 768, "code": null } -
Reference data for forms and validation
GET/billing/v1/common/countriesCountries with phone codes, tenant availability, and OFAC flags (Billing system, paginated).
curl -s "https://apigw.ipxo.com/billing/v1/common/countries" \ -H "Authorization: Bearer $ACCESS_TOKEN"
200Sample response (excerpt){ "data": [{ "uuid": "75645c44-0554-4627-a032-e58508c5163b", "alpha_2_code": "AL", "alpha_3_code": "ALB", "name": "Albania", "phone_code": "+355", "tenant_availability": 1, "ofac_listed": 0 }], "meta": { "current_page": 1, "last_page": 17, "per_page": 15, "total": 251 } }For address forms, Ecommerce has its own pair:
GET /ecommerce/public/common/countries(name + alpha-2 code) andGET /ecommerce/public/common/countries/{country_code}/provinces(country_codepath, required). Industry list for registration:GET /billing/v1/common/industries→{ "data": [{ "uuid", "name": "Cloud Provider" }, …] }.