Package: py-dactyl
pydactylAn easy to use Python wrapper for the Pterodactyl Panel API.State of the projectSupport for the Pterodactyl 1.x API is complete.
The 2.0 Pydactyl release was created to standardize how includes and params
are passed.  As a result some endpoints (namely nests)will breakwhen
upgrading from Pydactyl 1.x to 2.0.Pull Requests are being accepted and new endpoints will continue to be added.If you encounter problems, find APIs that haven't been implemented, or have a
feature request please file aGithub issue.DocumentationGenerated documentation can be found athttps://pydactyl.readthedocs.io/.InstallingTo install with pip:pipinstallpy-dactylIf you get an error sayingImportError: cannot import name  'PterodactylClient' from 'pydactyl'this probably means you installed the
wrong package from pip.Getting StartedPterodactyl has two different types of API keys: Client (also known as
Account) and Application.Any user can generate an Account API key to
control their own servers.  The Account API key for an Administrator user will
be able to access any server's Client API.Application API keys can only be generated by administrators.  These keys can be used to create, modify, and delete servers, among other things.  They have access to any server on the panel and can be destructive, so use with care.Exploring the APIIn addition to the documentation you can explore the interface in an
interactive Python interpreter using built-ins likedir()and the__doc__attribute as shown below.frompydactylimportPterodactylClientapi=PterodactylClient('debug','anything')[iforiindir(api.client.servers)ifnoti.startswith('_')]# ['account', 'backups', 'databases', 'files', 'get_server', 'get_server_utilization', 'list_permissions', 'list_servers', 'network', 'schedules', 'send_console_command', 'send_power_action', 'servers', 'settings', 'startup', 'users'][iforiindir(api.client.servers.settings)ifnoti.startswith('_')]# ['reinstall_server', 'rename_server']print(api.client.servers.settings.rename_server.__doc__)#Renames the server.#        Args:#            server_id(str): Server identifier (abbreviated UUID)#            name(str): New name for the serverClient APIThe Client API or Account API is accessed by users of the Pterodactyl panel.
Below is the layout of the Client API namespace.api.client.accountapi.client.serversapi.client.servers.backupsapi.client.servers.databasesapi.client.servers.filesapi.client.servers.networkapi.client.servers.schedulesapi.client.servers.settingsapi.client.servers.startupapi.client.servers.usersA full list of methods available can be found in thedocumentation.Below are examples of how you might get information about your servers.frompydactylimportPterodactylClient# Create a client to connect to the panel and authenticate with your API key.api=PterodactylClient('https://panel.mydomain.com','MySuperSecretApiKey')# Get a list of all servers the user has access tomy_servers=api.client.servers.list_servers()# Get the unique identifier for the first server.srv_id=my_servers[0]['attributes']['identifier']# Check the utilization of the serversrv_utilization=api.client.servers.get_server_utilization(srv_id)print(srv_utilization)# Turn the server on.api.client.servers.send_power_action(srv_id,'start')Application APIAs of Pterodactyl 1.8.0 Application API keys are deprecated and client API keys should now be used exclusively.The Application API is the administrative API of the Pterodactyl panel.
Below is the layout of the Application API namespace.api.locationsapi.nestsapi.nodesapi.serversapi.userBelow are examples of how you might use this API.frompydactylimportPterodactylClient# Create a client to connect to the panel and authenticate with your API key.api=PterodactylClient('https://panel.mydomain.com','MySuperSecretApiKey')# Create a server.  Customize the Nest and Egg IDs to match the IDs in your panel.# This server is created with a limit of 8000 MB of memory, no access to swap, unlimited disk space, in location_id 1.api.servers.create_server(name='My Paper Server',user_id=1,nest_id=1,egg_id=3,memory_limit=8000,swap_limit=0,backup_limit=0,disk_limit=0,location_ids=[1])<Response[201]>A 201 response indicates success, however if there is a problem with the request
Pydactyl will raise an exception with additional details. When updating the
location_ids field to an invalid location it displays an error:api.servers.create_server(name='My Paper Server',user_id=1,nest_id=1,egg_id=3,memory_limit=8000,swap_limit=0,disk_limit=0,location_ids=[199])Traceback(mostrecentcalllast):File"<input>",line6,in<module>File"D:\code\pydactyl\pydactyl\api\servers.py",line268,increate_servermode='POST',data=data,json=False)File"D:\code\pydactyl\pydactyl\api\base.py",line98,in_api_request'code'],errors['detail'])pydactyl.exceptions.PterodactylApiError:BadAPIRequest(400)-NoViableNodeException-Nonodessatisfyingtherequirementsspecifiedforautomaticdeploymentcouldbefound.You can use the User class to add, modify, and delete panel users.# Create a new userresult=api.user.create_user('test_user','test@gmail.com','Test','Name')# Get the ID of the created useruser_id=result['attributes']['id']# Get the user info, also returned by create_user()api.user.get_user_info(user_id){'object':'user','attributes':{'id':14,'external_id':None,....}}# Delete the userapi.user.delete_user(user_id=14)IncludesPterodactyl API endpoints have different sets of includes you can pass to alter
the response.  Using includes will cause additional information to show up
in the relationships field of the response data.  Some endpoints have no
includes and some have many.Pydactyl docstrings include examples of
valid includes for each endpoint, but they arenot an exhaustive list.server_includes = [
    'allocations', 'user', 'subusers', 'pack', 'nest', 'egg', 'variables',
    'location', 'node', 'databases']As an example the application server details endpoint has 10 potential
includes according to the API docs.  Note that the API docs are not always
accurate either!Most endpoints that generate lists will have optional includes that can be
passed as lists or tuples.api.nodes.list_nodes(includes=('allocations','location'))api.servers.get_server_info(server_id=53,includes=['user','subusers','location'])ParamsMost endpoints with includes will also have aparamsparameter.  This can
be used to pass additional parameters.  Many endpoint specificparamsare
already supported by Pydactyl, however some additional params apply
universally likeper_page.api.nodes.list_nodes(params={'per_page':9001})api.servers.list_servers(params={'per_page':9001})api.users.list_users(params={'per_page':9001})PterodactylClientEach of the classes in pydactyl could be imported independently, but the
PterodactylClient classpydactyl/api_client.pyprovides a simplified interface that imports libraries for you and provides
some convenience features like retries and debug logging.RetriesInstances ofPterodactylClientwill automatically
retry calls that fail with a 429 status code indicating that the request was
rate-limited by Pterodactyl.By default it uses a backoff_factor of 1 with 3 retries. You can configure the
number of retries and backoff_factor when instantiating a client.PterodactylClient('panel','key',backoff_factor=2,retries=10)Details on backoff_factor and retires can be found in theurllib3.util.Retry documentation.If your server is overloaded or intermittently unavailable you may want to retry
on other status codes as well. To do this you can pass in a list of integer HTTP
status codes.PterodactylClient('foo','bar',extra_retry_codes=[502,504])Debug loggingMost errors from pydactyl will present as exceptions and there is no logging
by default, however sometimes additional logging is helpful.  You can get
request logging by passingdebug=Trueto PterodactylClient.app_api=PterodactylClient('https://why','broken',debug=True)app_api.servers.list_servers(includes=('egg','nest'))DEBUG:urllib3.connectionpool:StartingnewHTTPSconnection(1):why:443DEBUG:urllib3.connectionpool:https://why:443"GET /api/application/servers?include=egg%2Cnest HTTP/1.1"200NonePaginated ResponsesPydactyl API responses return
aPaginatedResponse objectthat can be iterated over
to automatically fetch additional pages as required. This is currently
implemented on many endpoints which frequently return multi-page responses,
but not all.# Create a list of all portsallocs=api.nodes.list_node_allocations(node_id)ports=[]forpageinallocs:foriteminpage:ports.append(item['attributes']['port'])len(ports)151collect()Thecollect()method will fetch the data from all pages of a
PaginatedResponse. This allows you to easily fetch all results when you want all
the data without having to iterate over the pages.The above example to get a list of ports now looks like:# Create a list of all portsallocs=api.nodes.list_node_allocations(node_id)ports=allocs.collect()len(ports)151