How to Track ASNs and RIRs in Your Inventory
The two records every network needs, the fields worth storing on each ASN, how to classify public and private numbers, and an audit pipeline you can re-run every quarter from the API.

On this page
- At a Glance: Where ASN Records Live
- The Two Records You Actually Need
- Fields Worth Storing on Every ASN
- Classify Each Number Before You Store It
- Load What You Already Have
- Read the Records Back With a Fixed Shape
- Keep the Registry Side Current
- Cross-Check Against Public Registries
- A Quarterly Audit You Can Re-run
An autonomous system number is one of the few identifiers your network keeps for its entire life. It shows up in a BGP configuration, in a registry record, in an RPKI authorization, and in the peering agreement that admits you to an exchange. Yet it is also one of the least tracked, because a bare number looks like something a router knows and a spreadsheet can note in a spare column.
That is where the trouble starts. The number alone does not tell the next engineer which registry issued it, which sites announce it, which providers carry it, or whether it is even public. This is the tracking side of the same problem: the two records to keep, the fields worth storing, and a quarterly audit you can run from the API and diff against last quarter’s output.
At a Glance: Where ASN Records Live
| Obelinf | Spreadsheet | RIR portal only | |
|---|---|---|---|
| Registry link | ASN references the RIR record | A text column, often blank | One portal per registry |
| Public or private | Classified automatically | Manual, error prone | Visible only for public numbers |
| Site and provider links | Attached records, searchable | Notes that go stale | Absent |
| Cross registry view | One query covers every ASN | One file if maintained | One login per registry |
| Change history | Recorded per change | Manual or none | Registry side only |
| Audit export | API call with a fixed shape | Copy and paste | Manual screenshot |
The Two Records You Actually Need
Tracking starts with a small model, not a big one. A registry record and an ASN record are enough to answer every question a future engineer will ask, as long as the link between them exists and the ASN points at the things it touches.
The registry record is where the relationship to the authority lives. It carries a name, a short slug, an optional flag for non registry pseudo entries such as private address space, and a description that should hold the account number or sponsoring LIR. Registry slugs are unique inside an organization, so two teams can both keep a record called “legacy” without colliding.
The ASN record is the resource. It carries the number, a human readable name, a lifecycle status, an optional link to the registry that issued it, and a description. Everything else that matters is a relationship outward, to the sites that announce the number and the providers that carry it.
Fields Worth Storing on Every ASN
Keep the field set small enough that it actually gets filled in, and pick fields whose source you can name. Every value below comes from a person, a contract, or a registry, which is what makes the record debuggable later.
| Field | API name | Example | Source |
|---|---|---|---|
| The number | asn |
393216 |
Registry assignment |
| Display form | asdot |
6.0 for 393216 |
Derived from the number |
| Class | class |
public, private-16, private-32, reserved |
Derived from the number |
| Name | name |
ACME NETWORKS | Registry holder record |
| Lifecycle | status |
active |
Your team |
| Registry | rir_id |
RIPE NCC | Registry assignment |
| Registry name | rir_name |
RIPE NCC | Resolved from the record |
| Notes | description |
Sponsoring LIR, account reference | Contract or registry |
| Sites | sites |
NYC, DC1 | Network design |
| Providers | providers |
Example Transit | Contract |
Status and class are the two fields teams forget, and both carry weight. Status is how a number gets decommissioned without deleting a record that a changelog entry still references. Class is what stops a private number from being announced, and it is cheap to compute rather than type.
Classify Each Number Before You Store It
The public internet only accepts a subset of the AS number space, and mixing the categories is a common cause of a filtered announcement. Classify every number and store the result, so a private number is never mistaken for a public one during a configuration change.
Classify in one pass and store the answer. This is the same logic any tool should apply, and it makes the audit trivial because the class is already on the record.
# Classify a single number the same way a tracking tool should
asn=64520
if [ "$asn" -ge 64512 ] && [ "$asn" -le 65534 ]; then echo "private-16"
elif [ "$asn" -ge 4200000000 ] && [ "$asn" -le 4294967294 ]; then echo "private-32"
elif [ "$asn" -eq 0 ] || [ "$asn" -eq 23456 ] || [ "$asn" -eq 4294967295 ] \
|| { [ "$asn" -ge 64496 ] && [ "$asn" -le 64511 ]; } \
|| { [ "$asn" -ge 65536 ] && [ "$asn" -le 131071 ]; }; then echo "reserved"
else echo "public"
fi
Load What You Already Have
Start from the records you already hold rather than a blank list. The registry records rarely change, so they are the easiest thing to model first, and every ASN then has somewhere to point in your IP address management hierarchy.
export OBELINF_API_KEY="your_read_write_key"
export OBELINF_ORG="acme-netops"
BASE="https://api.obelinf.com/${OBELINF_ORG}"
# Registry records first
curl --fail --silent --show-error -H "Authorization: Bearer ${OBELINF_API_KEY}" \
"${BASE}/rirs?all=true&order=asc" \
| jq -r '.rirs[] | [.id, .name, .slug, (.is_private|tostring)] | @tsv'
Create any registry you are missing, then create the ASN with the registry attached. A registry record can be created for a pseudo authority too, which is useful for private space that never had an issuing body.
curl --fail --silent --show-error -X POST \
-H "Authorization: Bearer ${OBELINF_API_KEY}" \
-H "Content-Type: application/json" \
"${BASE}/rirs" \
-d '{"name":"RFC 6996 Private","slug":"private-rfc6996","is_private":true,"description":"Private ASN ranges for internal use"}'
For public numbers, the registry will fill in the holder name for you. The lookup endpoint resolves a public ASN through RDAP and returns the class alongside it, and it deliberately returns an empty name for private and reserved numbers instead of making an external request.
curl --fail --silent --show-error -H "Authorization: Bearer ${OBELINF_API_KEY}" \
"${BASE}/asns/registry-lookup?asn=3320" \
| jq -r '[.asn, .class, (.name // "no name"), (.rir // "no rir")] | @tsv'
3320 public DTAG RIPE NCC
That single call gives you the three values that are otherwise typed by hand: the class, the registered name, and the registry. Confirm the name against your own records before you accept it, because the holder string is whatever the registry publishes, and a sponsoring LIR can appear instead of the operating company.
Read the Records Back With a Fixed Shape
The value of an inventory is not the storage, it is the export. Define one output shape now, keep it identical between runs, and every future audit becomes a comparison instead of a data gathering exercise. The all=true flag raises the page size to 1000, so page with offset if you hold more ASNs than that.
mkdir -p "audit/$(date +%F)"
curl --fail --silent --show-error -H "Authorization: Bearer ${OBELINF_API_KEY}" \
"${BASE}/asns?all=true&order=asc" \
| jq -r '.asns[] | [.asn, .asdot, .class, .name, (.rir_name // "-"), .status] | @tsv' \
| sort > "audit/$(date +%F)/asns.tsv"
column -t -s $'\t' "audit/$(date +%F)/asns.tsv"
3320 3320 public DTAG RIPE NCC active
64512 64512 private-16 Core iBGP - active
393216 6.0 public ACME NETWORKS RIPE NCC active
65000 65000 private-16 Lab - deprecated
The asdot column is where a 32 bit number shows itself. A 16 bit number reads the same in both columns, while 393216 in the first column appears as 6.0 in the second. Seeing both forms in the export is what stops a duplicate record from being created for a number that already exists under the other notation. The - in the registry column is the field to act on, because an ASN with no registry reference cannot be reconciled against anything.
The list endpoint searches ASNs by name and by number, so a partial digit finds the record without a full scan. Registry records search on the name prefix, which is faster but narrower, so search for a full name rather than a fragment.
Keep the Registry Side Current
Registry records change more slowly than ASNs, but they fail in a worse way when they are wrong, because the ASN record inherits the error. The account reference, the sponsoring LIR, and the abuse contact all belong in the registry description, and the registry detail endpoint tells you how many ASNs depend on it.
curl --fail --silent --show-error -H "Authorization: Bearer ${OBELINF_API_KEY}" \
"${BASE}/rirs/${RIR_ID}" \
| jq -r '[.rir.name, (.rir.asn_count|tostring)] | @tsv'
That asn_count is a dependency check, and the same count prevents a careless deletion. Deleting a registry that still has ASNs attached is refused with a conflict that names the count: Cannot delete this RIR because it is referenced by 3 ASN(s). Remove or reassign them first. Treat that refusal as a prompt, not an obstacle, because a registry deleted while numbers still point at it is a gap in the audit trail that is expensive to rebuild.
Cross-Check Against Public Registries
The inventory is the reference, but the registry is the authority, and the two drift apart during a provider migration. Run the external queries as a reconciliation step rather than as the source of truth. The routing registry answers which prefixes a number is authorized to originate.
whois -h whois.radb.net -- "-i origin AS393216" | grep -E '^(route|route6):'
route: 203.0.113.0/24
route6: 2001:db8:100::/48
RDAP answers who the number belongs to and which registry issued it, in a form a script can read. The port43 value is the registry host, which is the field to compare against the rir_name you stored.
awk -F'\t' '$3=="public"{print $1}' "audit/$(date +%F)/asns.tsv" \
| while read -r asn; do
holder=$(curl --fail --silent --show-error "https://rdap.org/autnum/${asn}" 2>/dev/null \
| jq -r '[.handle, (.name // "none"), (.port43 // "none")] | @tsv')
printf '%s\t%s\n' "$asn" "$holder"
done | sort > "audit/$(date +%F)/rdap.tsv"
column -t -s $'\t' "audit/$(date +%F)/rdap.tsv"
3320 AS3320 DTAG whois.ripe.net
393216 AS393216 ACME NETWORKS whois.ripe.net
A holder of none on a number you classed as public is the signal that the assignment is incomplete, because a public number with no registered holder will be treated as unverified by peers that filter on registry data.
A Quarterly Audit You Can Re-run
The whole point of a fixed output shape is that the next run compares cleanly against the last. Keep the dated directory, and the audit collapses into a diff.
comm -3 "audit/2026-07-18/asns.tsv" "audit/2026-10-18/asns.tsv"
393216 6.0 public ACME NETWORKS RIPE NCC active
393216 6.0 public ACME NETWORKS RIPE NCC deprecated
393217 6.1 public ACME NETWORKS RIPE NCC active
A line without a leading tab exists only in the previous run, a line with one exists only in the current run, and a record that changed in place appears twice, once on each side. Two lines for the same number in different notations is the duplicate that the audit exists to find.
Layer the remaining checks on the same file. Numbers with no registry, public numbers with no RDAP holder, and private numbers that appear in a captured configuration are all one line each.
echo "== ASNs with no registry =="
awk -F'\t' '$5=="-"{print $1, $4}' "audit/$(date +%F)/asns.tsv"
echo "== Private numbers that should never be announced =="
awk -F'\t' '$3!="public"{print $1, $3, $4}' "audit/$(date +%F)/asns.tsv"
The first concrete step is the export, not the cleanup. Run the two API calls today, save the files under a dated directory, and commit them next to whatever else your team keeps in version control. Once one run exists, the next one is a diff, and the audit turns from a project into a habit.
Frequently Asked Questions
What is the difference between an ASN and a RIR?
How should I store private ASN ranges?
Why does an ASN show two notations?
How do I keep ASN records current as providers change?
Can I track ASNs and RIRs with Obelinf?
Stop reaching for a spreadsheet
Obelinf keeps every subnet, device, circuit, and rack in one live source of truth, with audit logs and a topology view. Free for personal use.
Related Articles

ASN Planning for Multi-Site Networks
How to decide between one ASN and many, allocate prefixes that summarize cleanly, build the internal control plane, and verify a site's announcements before it leaks a route.
Read more
How to Register an ASN: RIR Application Walkthrough
A step by step ASN application walkthrough for ARIN, RIPE NCC, APNIC, LACNIC, and AFRINIC: the dossier to build, the fees and turnaround, and the commands that prove the assignment is live.
Read more
Network Discovery vs. IPAM vs. Monitoring
Obelinf's take on network discovery versus IPAM versus monitoring: what each discipline does, where they overlap, and why all three need one source of truth to stay accurate.
Read more