Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/ironfang:ironfang-security-domains-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Ironfang Security Domains API
version: 0.1.0
summary: External Security Check - verify a domain, run a low-impact external assessment, fix and recheck findings.
description: 'Ironfang Security helps an organisation understand what it exposes to
the internet, fix what matters and keep evidence that it did.'
contact:
name: Ironfang
email: hello@ironfang.uk
url: https://ironfang.com/contact
termsOfService: https://ironfang.com/legal/terms
license:
name: Proprietary - use governed by the Ironfang terms of service
url: https://ironfang.com/legal/terms
servers:
- url: https://api.ironfang.com/security
security:
- bearerAuth: []
tags:
- name: Domains
description: Domains the organisation has added, their ownership verification and authorisation.
paths:
/v1/domains:
get:
tags:
- Domains
operationId: listDomains
summary: List domains
responses:
'200':
description: The organisation's domains, oldest first.
content:
application/json:
schema:
type: object
required:
- items
properties:
items:
type: array
items:
$ref: '#/components/schemas/DomainSummary'
default:
$ref: '#/components/responses/Problem'
post:
tags:
- Domains
operationId: addDomain
summary: Add a domain
description: Adds a domain and issues a DNS TXT verification challenge. Accepts what a person would type (a URL or a name with a trailing dot) and normalises it. Refuses IP addresses, public suffixes and reserved names. Adding a domain that was removed earlier restores it.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AddDomainRequest'
responses:
'201':
description: The domain, with its verification challenge.
content:
application/json:
schema:
$ref: '#/components/schemas/Domain'
'400':
$ref: '#/components/responses/Problem'
'409':
$ref: '#/components/responses/Problem'
'422':
$ref: '#/components/responses/Problem'
default:
$ref: '#/components/responses/Problem'
/v1/domains/{domainId}:
parameters:
- $ref: '#/components/parameters/DomainId'
get:
tags:
- Domains
operationId: getDomain
summary: Get a domain
responses:
'200':
description: The domain.
content:
application/json:
schema:
$ref: '#/components/schemas/Domain'
'404':
$ref: '#/components/responses/Problem'
default:
$ref: '#/components/responses/Problem'
delete:
tags:
- Domains
operationId: removeDomain
summary: Remove a domain
description: Stops all checks of the domain and removes it from the list. Its scan history, findings and evidence are kept for the audit trail.
responses:
'204':
description: Removed.
'404':
$ref: '#/components/responses/Problem'
default:
$ref: '#/components/responses/Problem'
/v1/domains/{domainId}/verification/check:
parameters:
- $ref: '#/components/parameters/DomainId'
post:
tags:
- Domains
operationId: checkVerification
summary: Check the verification record now
description: Looks up the TXT record immediately rather than waiting for the automatic recheck. Limited to one check every few seconds per domain.
responses:
'200':
description: The domain after the check.
content:
application/json:
schema:
$ref: '#/components/schemas/Domain'
'404':
$ref: '#/components/responses/Problem'
'409':
$ref: '#/components/responses/Problem'
'429':
$ref: '#/components/responses/Problem'
default:
$ref: '#/components/responses/Problem'
/v1/domains/{domainId}/verification/renew:
parameters:
- $ref: '#/components/parameters/DomainId'
post:
tags:
- Domains
operationId: renewVerification
summary: Issue a new verification token
description: Replaces an expired or failed challenge with a new token. Refused while the domain is verified.
responses:
'200':
description: The domain with its new challenge.
content:
application/json:
schema:
$ref: '#/components/schemas/Domain'
'404':
$ref: '#/components/responses/Problem'
'409':
$ref: '#/components/responses/Problem'
default:
$ref: '#/components/responses/Problem'
/v1/domains/{domainId}/authorisation:
parameters:
- $ref: '#/components/parameters/DomainId'
post:
tags:
- Domains
operationId: authoriseDomain
summary: Confirm authorisation to assess
description: Records that the acting user confirmed the current scan policy's statement for this verified domain. The record is immutable and names the policy and statement versions. A new policy version requires a new confirmation.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AuthoriseRequest'
responses:
'201':
description: The domain with its authorisation.
content:
application/json:
schema:
$ref: '#/components/schemas/Domain'
'404':
$ref: '#/components/responses/Problem'
'409':
$ref: '#/components/responses/Problem'
'422':
$ref: '#/components/responses/Problem'
default:
$ref: '#/components/responses/Problem'
/v1/domains/{domainId}/discoveries:
parameters:
- $ref: '#/components/parameters/DomainId'
get:
tags:
- Domains
operationId: listDiscoveries
summary: Names discovered for a domain
description: Names found in certificate transparency logs. They are listed for review only and are not scanned.
responses:
'200':
description: Discoveries, alphabetically.
content:
application/json:
schema:
type: object
required:
- items
properties:
items:
type: array
items:
$ref: '#/components/schemas/Discovery'
'404':
$ref: '#/components/responses/Problem'
default:
$ref: '#/components/responses/Problem'
components:
schemas:
ScanSummary:
type: object
required:
- id
- domain_id
- domain
- kind
- status
- requested_at
- progress
- counts
properties:
id:
type: string
format: uuid
domain_id:
type: string
format: uuid
domain:
type: string
kind:
$ref: '#/components/schemas/ScanKind'
status:
$ref: '#/components/schemas/ScanStatus'
requested_at:
type: string
format: date-time
started_at:
type: string
format: date-time
finished_at:
type: string
format: date-time
duration_ms:
type: integer
progress:
type: object
required:
- total
- completed
properties:
total:
type: integer
completed:
type: integer
counts:
$ref: '#/components/schemas/ScanCounts'
changes:
$ref: '#/components/schemas/ScanChanges'
recheck_finding_id:
type: string
format: uuid
status_reason:
type: string
description: Why a scan was cancelled, stopped or failed.
Verification:
type: object
required:
- status
- method
- record
- checks
properties:
status:
$ref: '#/components/schemas/VerificationStatus'
method:
type: string
enum:
- dns_txt
record:
$ref: '#/components/schemas/VerificationRecord'
expires_at:
type: string
format: date-time
last_checked_at:
type: string
format: date-time
next_check_at:
type: string
format: date-time
manual_check_available_at:
type: string
format: date-time
verified_at:
type: string
format: date-time
checks:
type: integer
description: How many times the record has been looked up.
failure_reason:
type: string
observed_values:
type: array
description: TXT values seen at the record name on the last lookup, to help troubleshooting.
items:
type: string
dns_provider:
$ref: '#/components/schemas/DnsProvider'
SeverityCounts:
type: object
required:
- critical
- high
- medium
- low
- info
properties:
critical:
type: integer
high:
type: integer
medium:
type: integer
low:
type: integer
info:
type: integer
DnsProvider:
type: object
required:
- id
- name
properties:
id:
type: string
description: e.g. cloudflare, route53, godaddy, namecheap, azure, google, other
name:
type: string
help_url:
type: string
format: uri
Discovery:
type: object
required:
- id
- name
- source
- first_seen_at
- last_seen_at
- in_scope
properties:
id:
type: string
format: uuid
name:
type: string
source:
type: string
enum:
- certificate_transparency
first_seen_at:
type: string
format: date-time
last_seen_at:
type: string
format: date-time
in_scope:
type: boolean
description: Always false in V1; discoveries are never scanned automatically.
ScanChanges:
type: object
required:
- new
- fixed
- reopened
properties:
new:
type: integer
fixed:
type: integer
reopened:
type: integer
AuthoriseRequest:
type: object
required:
- policy_version
- statement_version
- confirm
properties:
policy_version:
type: string
statement_version:
type: string
confirm:
type: boolean
const: true
ScanBlockedReason:
type: string
description: Why a scan cannot start now.
enum:
- verification_required
- authorisation_required
- policy_outdated
- scan_in_progress
- scan_cooldown
- daily_limit_reached
- organisation_suspended
- scans_paused
- security_disabled
AddDomainRequest:
type: object
required:
- domain
properties:
domain:
type: string
maxLength: 300
examples:
- example.co.uk
VerificationRecord:
type: object
required:
- type
- name
- host_label
- value
properties:
type:
type: string
enum:
- TXT
name:
type: string
description: Fully qualified record name.
host_label:
type: string
description: The name relative to the domain, for providers that append the domain.
value:
type: string
Domain:
allOf:
- $ref: '#/components/schemas/DomainSummary'
- type: object
required:
- verification
- discoveries
properties:
verification:
$ref: '#/components/schemas/Verification'
authorisation:
$ref: '#/components/schemas/Authorisation'
discoveries:
type: integer
description: Number of discovered names.
VerificationStatus:
type: string
enum:
- waiting
- checking
- verified
- failed
- expired
- lapsed
ScanStatus:
type: string
enum:
- queued
- running
- completed
- partial
- failed
- cancelled
- killed
Problem:
type: object
required:
- error
- request_id
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
description: 'Stable error code. Among them: `unauthorized`, `forbidden`,
`not_found`, `validation_failed`, `domain_invalid`,
`domain_exists`, `domain_limit_reached`,
`verification_pending_limit`, `verification_required`,
`already_verified`, `authorisation_required`,
`policy_outdated`, `scan_in_progress`, `scan_cooldown`,
`daily_limit_reached`, `domain_rate_limited`, `scan_not_active`,
`recheck_unavailable`, `recheck_cooldown`, `check_rate_limited`,
`organisation_suspended`, `scans_paused`, `security_disabled`,
`verification_expired`, `verification_unavailable`,
`verification_pending_limit`, `finding_fixed`, `internal`.
From the Ironfang API in front of the service:
`api_keys_not_supported`, `permissions_unavailable`,
`body_too_large`, `invalid_body`, `invalid_tenant`,
`security_unavailable`, `security_timeout`.
'
message:
type: string
docs:
type: string
format: uri
retry_after_seconds:
type: integer
description: Set on cooldowns and rate limits.
request_id:
type: string
DomainSummary:
type: object
required:
- id
- name
- display_name
- verification_status
- authorised
- can_scan
- open_findings
- created_at
properties:
id:
type: string
format: uuid
name:
type: string
description: ASCII (punycode) name.
display_name:
type: string
verification_status:
$ref: '#/components/schemas/VerificationStatus'
authorised:
type: boolean
can_scan:
type: boolean
scan_blocked_reason:
$ref: '#/components/schemas/ScanBlockedReason'
next_scan_at:
type: string
format: date-time
description: When the cooldown ends.
latest_scan:
$ref: '#/components/schemas/ScanSummary'
open_findings:
$ref: '#/components/schemas/SeverityCounts'
created_at:
type: string
format: date-time
ScanKind:
type: string
enum:
- full
- recheck
ScanCounts:
type: object
required:
- critical
- high
- medium
- low
- info
- passed
- confirmed
- unverified
- errors
properties:
critical:
type: integer
high:
type: integer
medium:
type: integer
low:
type: integer
info:
type: integer
passed:
type: integer
description: Checks that observed a control working.
confirmed:
type: integer
description: Findings with confirmed or high confidence.
unverified:
type: integer
description: Findings with medium or low confidence.
errors:
type: integer
description: Checks that could not complete.
Authorisation:
type: object
required:
- id
- policy_version
- statement
- statement_version
- accepted_at
- accepted_by
- current
properties:
id:
type: string
format: uuid
policy_version:
type: string
statement:
type: string
statement_version:
type: string
accepted_at:
type: string
format: date-time
accepted_by:
$ref: '#/components/schemas/Person'
current:
type: boolean
description: False when the policy has changed and must be confirmed again.
Person:
type: object
required:
- label
properties:
label:
type: string
responses:
Problem:
description: An error.
content:
application/json:
schema:
$ref: '#/components/schemas/Problem'
parameters:
DomainId:
name: domainId
in: path
required: true
schema:
type: string
format: uuid
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: Warden JWT
description: 'A Warden user token. Each route also requires a tenant permission in
the acting tenant (`X-Ironfang-Tenant`), resolved live from Warden:
reads need `security.read`; everything that changes state needs
`security.write`. A missing permission is 403; a permission lookup
failure is 503. Platform API keys are not accepted yet.
'
externalDocs:
description: Ironfang Security documentation
url: https://ironfang.com/security/docs