Skip to content

Instantly share code, notes, and snippets.

@demming
Created November 3, 2022 08:27
Show Gist options
  • Save demming/84e3c17ba695e69b10052fa892eae7ea to your computer and use it in GitHub Desktop.
Save demming/84e3c17ba695e69b10052fa892eae7ea to your computer and use it in GitHub Desktop.
An unofficial Porkbun.com OpenAPI description for the Porkbun API, see <https://porkbun.com/api/json/v3/documentation>. Among other things, it can be used - as a foundation to implement a dynamic DNS service, - for managing DNS records, - keeping track on domain pricing, or - for controlling your domains registered with Porkbun domains. As per u…
openapi: 3.0.3
info:
title: Porkbun.com OpenAPI Description
description: |
An unofficial Porkbun.com OpenAPI description for the Porkbun API, see <https://porkbun.com/api/json/v3/documentation>.
Among other things, it can be used
- as a foundation to implement a dynamic DNS service,
- for managing DNS records,
- keeping track on domain pricing, or
- for controlling your domains registered with Porkbun domains.
As per upstream description <https://porkbun.com/api/json/v3/documentation>, the following features are officially supported and are reproduced in the OpenAPI description:
1. domain pricing,
2. authorized CRUD for DNS records,
3. retrieval of the SSL bundle for a given domain.
## Disclaimer
If you decide to use the CRUD commands, then do so with caution! They can wreak havoc to the DNS records of your domains! You can use them at your own risk. It is due diligence to back up your DNS records on a regular basis just like protecting your access tokens and passwords.
## License: MIT <https://opensource.org/licenses/MIT>
Copyright 2022 Nick Demming <https://github.com/demming>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
license:
name: MIT
url: https://opensource.org/licenses/MIT
version: 0.1.2
servers:
- url: https://porkbun.com/api/json/v3
description: Main API root endpoint
- url: https://api-ipv4.porkbun.com/api/json/v3
description: Alternative IPv4-only endpoint
paths:
/pricing/get:
post: # get also works here
operationId: getPricing
summary: Domain Pricing
description: Check default domain pricing information for all supported TLDs. This command does not require authentication.
responses:
'200':
description: Status and current prices per domain in a JSON map.
content:
application/json:
schema:
$ref: "#/components/schemas/ResponsePricing"
# $ref: '#/components/responses/ResponsePricing'
/ping:
post:
operationId: ping
summary: Authentication
description: |
Authentication is done by passing an API key and secret API key in the JSON content posted to the URI endpoint.
All API calls must include valid API keys.
You can create API keys at [porkbun.com/account/api](https://porkbun.com/account/api).
You can test communication with the API using the ping endpoint.
The ping endpoint will also return your IP address, this can be handy when building dynamic DNS clients.
[Get API Key](https://porkbun.com/account/api)
# NOTE: Porkbun puts the API auth keys into the request body.
# security:
# - ApiKey: []
# PrivateApiKey: []
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
# And so we need to add these two properties to each request type except Pricing.
secretapikey:
type: string
description: Your secret API key.
apikey:
type: string
description: Your API key.
responses:
'200':
description: Authenticated ping request was successful
# $ref: '#/components/responses/ResponsePing'
content:
application/json:
schema:
$ref: "#/components/schemas/SuccessPing"
# TODO: map anything else to Error:
# NOTE: Unauthorized should be 401 but Porkbun don't do that.
'400':
description: Error Response
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
# TODO: Refactor, need a separate yaml file for each request, lest it gets unwieldy.
/dns/create/{domainName}:
post:
operationId: createRecord
summary: DNS Create Record
description: Create a DNS record.
# security:
# - ApiKey: []
# SecretApiKey: []
parameters:
- in: path
name: domainName
schema:
type: string
required: true
description: The domain name for which the DNS record should be created.
# TODO: TESTME: NOTE: It appears that here the type should agree with the type of the record given the record ID...
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- secretapikey
- apikey
- type
- content
properties:
secretapikey:
type: string
description: Your secret API key.
apikey:
type: string
description: Your API key.
name:
type: string
description: "The subdomain for the record being created, not including the domain itself. Leave blank to create a record on the root domain. Use `*` to create a wildcard record."
type:
# TESTME:
oneOf:
- $ref: "#/components/schemas/RecordType"
description: "The type of record being created. Valid types are: A, MX, CNAME, ALIAS, TXT, NS, AAAA, SRV, TLSA, CAA"
content:
type: string
description: The answer content for the record. Please see the DNS management popup from the domain management console for proper formatting of each record type.
ttl:
oneOf:
- type: string
- type: integer
description: The time to live in seconds for the record. The minimum and the default is 300 seconds.
prio:
oneOf:
- type: string
- type: integer
description: The priority of the record for those that support it.
responses:
'200':
# $ref: '#/components/responses/ResponseCreate'
description: DNS record was successfully created.
content:
application/json:
schema:
type: object
properties:
status:
type: string
enum: [SUCCESS]
description: A status indicating whether or not the command was successfuly processed.
id:
oneOf:
- type: integer
- type: string
description: The ID of the record created.
'400':
description: Error Response
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/dns/edit/{domainName}/{id}:
post:
operationId: editRecordById
summary: DNS Edit Record by Domain and ID
description: Edit a DNS record by record ID.
# security:
# - ApiKey: []
# SecretApiKey: []
parameters:
- in: path
name: domainName
schema:
type: string
required: true
description: The domain name for which the DNS record should be created.
- in: path
name: id
schema:
oneOf: # In fact, it's an integer.
- type: string
- type: integer
required: true
description: The DNS record ID that should correspond to the given `domainName` value that should be modified.
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- secretapikey
- apikey
- type
- content
properties:
secretapikey:
type: string
description: Your secret API key.
apikey:
type: string
description: Your API key.
name:
type: string
description: "The subdomain for the record being created, not including the domain itself. Leave blank to create a record on the root domain. Use `*` to create a wildcard record."
type:
# TESTME:
oneOf:
- $ref: "#/components/schemas/RecordType"
description: "The type of record being created. Valid types are: A, MX, CNAME, ALIAS, TXT, NS, AAAA, SRV, TLSA, CAA"
content:
type: string
description: The answer content for the record. Please see the DNS management popup from the domain management console for proper formatting of each record type.
ttl:
oneOf:
- type: string
- type: integer
description: The time to live in seconds for the record. The minimum and the default is 300 seconds.
prio:
oneOf:
- type: string
- type: integer
description: The priority of the record for those that support it.
responses:
'200':
# $ref: '#/components/responses/ResponseCreate'
description: DNS record was successfully modified.
content:
application/json:
schema:
type: object
properties:
status:
type: string
description: A status indicating whether or not the command was successfully processed.
'400':
description: Error Response
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
# TESTME: Perhaps Porbun mean that there's a second path without the subdomain param.
# Either way, this param seems to be mandatory anyway...
# So let's run a request at the path without it and see if it fails.
/dns/editByNameType/{domainName}/{recordType}/{subdomain}:
post:
operationId: editRecordByNameTypeSubdomain
summary: DNS Edit Record by Domain, Subdomain and Type
description: Edit all records for the domain that match a particular subdomain and type.
# security:
# - ApiKey: []
# SecretApiKey: []
parameters:
- in: path
name: domainName
schema:
type: string
required: true
description: The domain name for which the DNS record should be created.
- in: path
name: recordType
schema:
# type: string
$ref: "#/components/schemas/RecordType"
required: true
description: The DNS record ID that should correspond to the given `domainName` value that should be modified.
- in: path
name: subdomain
schema:
type: string
required: true # TESTME: I believe this param is mandatory... In addition, path params are all required by the spec!
description: "The optional subdomain. Warning: TODO matching nothing or *"
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- secretapikey
- apikey
- content
properties:
secretapikey:
type: string
description: Your secret API key.
apikey:
type: string
description: Your API key.
content:
type: string
description: The answer content for the record. Please see the DNS management popup from the domain management console for proper formatting of each record type.
ttl:
oneOf:
- type: string
- type: integer
description: The time to live in seconds for the record. The minimum and the default is 300 seconds.
prio:
oneOf:
- type: string
- type: integer
description: The priority of the record for those that support it.
responses:
'200':
# $ref: '#/components/responses/ResponseCreate'
description: DNS record was successfully modified.
content:
application/json:
schema:
$ref: "#/components/schemas/Success"
'400':
description: Error Response
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/dns/editByNameType/{domainName}/{recordType}:
post:
operationId: editRecordByNameType
summary: DNS Edit Record by Domain and ype
description: Edit all records for the domain that match a particular type.
# security:
# - ApiKey: []
# SecretApiKey: []
parameters:
- in: path
name: domainName
schema:
type: string
required: true
description: The domain name for which the DNS record should be created.
- in: path
name: recordType
schema:
# type: string
$ref: "#/components/schemas/RecordType"
required: true
description: The DNS record ID that should correspond to the given `domainName` value that should be modified.
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- secretapikey
- apikey
- content
properties:
secretapikey:
type: string
description: Your secret API key.
apikey:
type: string
description: Your API key.
content:
type: string
description: The answer content for the record. Please see the DNS management popup from the domain management console for proper formatting of each record type.
ttl:
oneOf:
- type: string
- type: integer
description: The time to live in seconds for the record. The minimum and the default is 300 seconds.
prio:
oneOf:
- type: string
- type: integer
description: The priority of the record for those that support it.
responses:
'200':
# $ref: '#/components/responses/ResponseCreate'
description: DNS record was successfully modified.
content:
application/json:
schema:
$ref: "#/components/schemas/Success"
'400':
description: Error Response
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/dns/delete/{domainName}/{id}:
post:
operationId: deleteRecordById
summary: DNS Delete Record by Domain and ID
description: Delete a specific DNS record by record ID.
# security:
# - ApiKey: []
# SecretApiKey: []
parameters:
- in: path
name: domainName
schema:
type: string
required: true
description: The domain name for which the DNS record should be created.
- in: path
name: id
schema:
oneOf: # In fact, it's an integer.
- type: string
- type: integer
required: true
description: The DNS record ID that should correspond to the given `domainName` value that should be modified.
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- secretapikey
- apikey
properties:
secretapikey:
type: string
description: Your secret API key.
apikey:
type: string
description: Your API key.
responses:
'200':
# $ref: '#/components/responses/ResponseCreate'
description: DNS record was successfully deleted.
content:
application/json:
schema:
$ref: "#/components/schemas/Success"
'400':
description: Error Response
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/dns/deleteByNameType/{domainName}/{recordType}/{subdomain}:
post:
operationId: deleteRecordByNameTypeSubdomain
summary: DNS Delete Record by Domain, Subdomain and Type
description: Delete all records for the domain that match a particular subdomain and type.
# security:
# - ApiKey: []
# SecretApiKey: []
parameters:
- in: path
name: domainName
schema:
type: string
required: true
description: The domain name for which the DNS record should be created.
- in: path
name: recordType
schema:
# type: string
$ref: "#/components/schemas/RecordType"
required: true
description: The DNS record ID that should correspond to the given `domainName` value that should be modified.
- in: path
name: subdomain
schema:
# TODO: Perhaps represent this by a nullable string schema?
type: string
required: true # TESTME: I believe this param is mandatory by design... In addition, path params are all required by the spec!
description: "The optional subdomain. Warning: TODO matching nothing or *"
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- secretapikey
- apikey
- content
properties:
secretapikey:
type: string
description: Your secret API key.
apikey:
type: string
description: Your API key.
responses:
'200':
description: DNS record was successfully deleted.
content:
application/json:
schema:
$ref: "#/components/schemas/Success"
'400':
description: Error Response
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/dns/deleteByNameType/{domainName}/{recordType}:
post:
operationId: deleteRecordByNameType
summary: DNS Delete Record by Domain, Subdomain and Type
description: Delete all records for the domain that match a particular type.
# security:
# - ApiKey: []
# SecretApiKey: []
parameters:
- in: path
name: domainName
schema:
type: string
required: true
description: The domain name for which the DNS record should be created.
- in: path
name: recordType
schema:
# type: string
$ref: "#/components/schemas/RecordType"
required: true
description: The DNS record ID that should correspond to the given `domainName` value that should be modified.
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- secretapikey
- apikey
- content
properties:
secretapikey:
type: string
description: Your secret API key.
apikey:
type: string
description: Your API key.
responses:
'200':
description: DNS record was successfully deleted.
content:
application/json:
schema:
$ref: "#/components/schemas/Success"
'400':
description: Error Response
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/dns/retrieve/{domainName}:
post:
operationId: retrieveRecordsAll
summary: DNS Retrieve Record by Domain # NOTE: The "or" now here in official text --- in contrast to "and" elsewhere.
description: Retrieve all editable DNS records associated with a domain or a single record.
# security:
# - ApiKey: []
# SecretApiKey: []
parameters:
- in: path
name: domainName
schema:
type: string
required: true
description: The domain name for which the DNS record should be created.
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- secretapikey
- apikey
properties:
secretapikey:
type: string
description: Your secret API key.
apikey:
type: string
description: Your API key.
responses:
'200':
# $ref: '#/components/responses/ResponseCreate'
description: DNS record was successfully modified.
content:
application/json:
schema:
# TODO: Refer
$ref: "#/components/schemas/RecordRetrievalSuccessful"
'400':
description: Error Response
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/dns/retrieve/{domainName}/{id}:
post:
operationId: retrieveRecordsById
summary: DNS Retrieve Record by Domain and ID # NOTE: The "or" now here in contrast to "and" elsewhere.
description: Retrieve all editable DNS records associated with a domain or a single record for a particular record ID.
# security:
# - ApiKey: []
# SecretApiKey: []
parameters:
- in: path
name: domainName
schema:
type: string
required: true
description: The domain name for which the DNS record should be created.
- in: path
name: id
schema:
oneOf: # In fact, it's an integer.
- type: string
- type: integer
required: true
description: The DNS record ID that should correspond to the given `domainName` value that should be modified.
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- secretapikey
- apikey
properties:
secretapikey:
type: string
description: Your secret API key.
apikey:
type: string
description: Your API key.
responses:
'200':
description: DNS record was successfully retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/RecordRetrievalSuccessful"
'400':
description: Error Response
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/dns/retrieveByNameType/{domainName}/{recordType}/{subdomain}:
post:
operationId: deleteRecordsByNameTypeSubdomain
summary: DNS Delete Record by Domain, Subdomain and Type
description: Delete all records for the domain that match a particular subdomain and type.
# security:
# - ApiKey: []
# SecretApiKey: []
parameters:
- in: path
name: domainName
schema:
type: string
required: true
description: The domain name for which the DNS record should be created.
- in: path
name: recordType
schema:
# type: string
$ref: "#/components/schemas/RecordType"
required: true
description: The DNS record ID that should correspond to the given `domainName` value that should be modified.
- in: path
name: subdomain
schema:
# TODO: Perhaps represent this by a nullable string schema? Or as a distinct path.
type: string
required: true # TESTME: I believe this param is mandatory by design... In addition, path params are all required by the spec!
description: "The optional subdomain. Warning: TODO matching nothing or *"
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- secretapikey
- apikey
- content
properties:
secretapikey:
type: string
description: Your secret API key.
apikey:
type: string
description: Your API key.
responses:
'200':
description: DNS record was successfully retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/Success"
'400':
description: Error Response
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/dns/retrieveByNameType/{domainName}/{recordType}:
post:
operationId: deleteRecordsByNameType
summary: DNS Delete Record by Domain and Type
description: Delete all records for the domain that match a particular type.
# security:
# - ApiKey: []
# SecretApiKey: []
parameters:
- in: path
name: domainName
schema:
type: string
required: true
description: The domain name for which the DNS record should be created.
- in: path
name: recordType
schema:
# type: string
$ref: "#/components/schemas/RecordType"
required: true
description: The DNS record ID that should correspond to the given `domainName` value that should be modified.
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- secretapikey
- apikey
- content
properties:
secretapikey:
type: string
description: Your secret API key.
apikey:
type: string
description: Your API key.
responses:
'200':
description: DNS record was successfully retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/Success"
'400':
description: Error Response
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/ssl/retrieve/{domainName}:
post:
operationId: retrieveSslBundleByDomain
summary: SSL Retrieve Bundle by Domain
description: Retrieve the SSL certificate bundle for the domain.
# security:
# - ApiKey: []
# SecretApiKey: []
parameters:
- in: path
name: domainName
schema:
type: string
required: true
description: The domain name for which the DNS record should be created.
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- secretapikey
- apikey
properties:
secretapikey:
type: string
description: Your secret API key.
apikey:
type: string
description: Your API key.
responses:
'200':
# $ref: '#/components/responses/ResponseCreate'
description: DNS record was successfully modified.
content:
application/json:
schema:
# TODO: Refer
$ref: "#/components/schemas/SslBunndleRetrievalSuccessful"
'400':
description: Error Response
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
securitySchemes:
# NOTE: This won't work with Porkbun API, since they put the keys in the request body.
ApiKey:
type: apiKey
in: query
name: apikey
SecretApiKey:
type: apiKey
in: query
name: secretapikey
# responses:
# # ResponsePricing:
# # description: ...
# # schema:
# # $ref: "#a/components/schemas/ResponsePricing"
# ResponseCreate:
# description: OK
# ResponsePing:
# description: |
# Authentication
# Authentication is done by passing an API key and secret API key in the JSON content posted to the URI endpoint. All API calls must include valid API keys. You can create API keys at porkbun.com/account/api. You can test communication with the API using the ping endpoint. The ping endpoint will also return your IP address, this can be handy when building dynamic DNS clients.
# ResponseError:
# description: Something went wrong...
# schema:
# $ref: "#/components/schemas/Error"
schemas:
RecordType:
description: An enum of admissible DNS record types.
type: string
enum: [A, MX, CNAME, ALIAS, TXT, NS, AAAA, SRV, TLSA, CAA]
SuccessPing:
type: object
properties:
status:
description: A status indicating whether or not the command was successfully processed.
type: string
enum: [SUCCESS]
yourIp:
description: The IP address of the client application.
type: string
Success:
type: object
properties:
status:
type: string
enum: [SUCCESS]
description: A status indicating whether or not the command was successfully processed.
Error:
properties:
status:
description: A status indicating whether or not the command was successfully processed.
type: string
enum: [ERROR]
message:
description: The error message.
type: string
ResponsePricing:
properties:
status:
type: string
description: A status indicating whether or not the command was successfully processed.
pricing:
type: object # FIXME: or the empty array as per origin!
description: Objects with default pricing for the registration, renewal and transfer of each supported TLD.
additionalProperties:
$ref: "#/components/schemas/ResponsePricingTLD"
# example:
# status: "SUCCESS"
# pricing:
# eu:
# registration: "5.16"
# renewal: "4.87"
# transfer: "5.16"
# coupons:
# registration:
# code: "AWESOMENESS"
# max_per_user: 1
# first_year_only: "yes"
# type: "amount"
# amount: 1
# job:
# registration: "32.23"
# renewal: "32.23"
# transfer: "32.23"
# coupons: []
ResponsePricingTLD:
properties:
registration:
type: string # number
renewal:
type: string # number
transfer:
type: string # number
coupons:
oneOf:
# FIXME: Either this or the empty array [].
- type: object
additionalProperties:
$ref: "#/components/schemas/ResponsePricingTLDCoupons"
- type: array
items: {}
example:
registration: "5.55"
renewal: "4.19"
transfer: "4.11"
coupons:
registration:
code: "AWESOMENESS"
max_per_user: 1
first_year_only: "yes"
type: "amount"
amount: 1
ResponsePricingTLDCoupons:
properties:
code:
type: string
max_per_user:
type: integer
first_year_only:
type: string # boolean yes|no
enum: [yes, no]
type:
type: string
enum: [amount] # TODO
amount:
type: integer
example:
code: "AWESOMENESS"
max_per_user: 1
first_year_only: "yes"
type: "amount"
amount: 1
RecordRetrievalSuccessful:
properties:
status:
type: string
enum: [SUCCESS]
description: A status indicating whether or not the command was successfully processed.
records:
description: An array of DNS records.
# TODO: array of: TESTME
type: array
items:
$ref: "#/components/schemas/RecordRetrievalSuccessfulRecords"
RecordRetrievalSuccessfulRecords:
properties:
id:
type: string
example: "106926659"
name:
type: string
example: "www.borseth.ink"
type:
# TESTME:
oneOf:
- $ref: "#/components/schemas/RecordType"
content:
type: string
example: "1.1.1.1"
ttl:
oneOf:
- type: integer
example: 300
- type: string
example: "300"
prio:
oneOf:
- type: integer
example: 0
- type: string
example: "0"
notes:
type: string
SslBunndleRetrievalSuccessful:
description: SSL bundle was retrieved successfully.
properties:
status:
description: A status indicating whether or not the command was successfuly processed.
type: string
enum: [SUCCESS]
example: "SUCCESS"
intermediatecertificate:
description: The intermediate certificate.
type: string
example: "----BEGIN CERTIFICATE-----\n...-----END CERTIFICATE-----\n"
certificatechain:
description: The complete certificate chain.
type: string
example: "----BEGIN CERTIFICATE-----\n...-----END CERTIFICATE-----\n\n----BEGIN CERTIFICATE-----\n...-----END CERTIFICATE-----\n\n----BEGIN CERTIFICATE-----\n...-----END CERTIFICATE-----\n"
privatekey:
description: The private key.
type: string
example: "-----BEGIN PRIVATE KEY-----\n...-----END PRIVATE KEY-----\n"
publickey:
description: The public key.
type: string
example: "-----BEGIN PUBLIC KEY-----\n...-----END PUBLIC KEY-----\n"
@demming
Copy link
Author

demming commented Nov 3, 2022

This is an initial version that seems to work, hence semantic version 0.1.2. I'm not releasing this description for general availability yet, would like to do so after thorough testing and validation in a couple of apps. Suggestions and pull requests are as always greatly appreciated.

This OpenAPI descriptions should be kept up-to-date with the upstream description at https://porkbun.com/api/json/v3/documentation, which may change too and is marked as "Version 3 - Beta" at the time of writing,
image

I think a good idea is to align the semantic versioning with Porkbun's upstream API version number. It remains unclear, however, whether upstream "Beta" entails major version 0. It appears least confusing to let major version of this description follow the upstream version number, that is, to make it 3.y.z for the present description here, and the minor digits 3.0.z or 3.1.z refer to upstream "Beta" keeping the "patch" digits to this OpenAPI description. The semantic scheme would thus look like

major.           .  minor                           . patch
upstream-version . alpha[0]/beta[1]/final[3]/?[...] . this-openapi-description-version

My use-cases for this description circulate primarily around dynamic DNS (DDNS) for development and production domains, integrated with @traefik and @kubernetes, @cloudflare and @letsencrypt.

Note that @porkbundomains provide basic DDNS client implementations (Python and Java). And I'm going to publish ones I've come up with, written in Go and Scala, with proper typing and validation; and for more reliable systems, a client written in Haskell is in the making; I'll put links here in the comments once I release my client apps. As an extra bonus I've got proper DevOps-ready descriptions, which I will share a bit later, too.

Note that there is a variety of enterprise-ready DDNS solutions out there but hosting your own is easy and gives you full control when you need it. Yet another tool in your DevOps toolkit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment