add example for generating an API key with the Python Client#48
add example for generating an API key with the Python Client#48
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new Python example script demonstrating how to generate a Civis API key via the Python client and persist it to a local configuration file for reuse.
Changes:
- Introduces
api_key_generation.pyexample that creates a new API key for the current user. - Writes the newly created token to a local file intended to be loaded by the user’s environment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| with open(_KEY_FILE, "w") as key_file: | ||
| key_file.seek(0) | ||
| key_file.write(key_string) | ||
| key_file.truncate() |
There was a problem hiding this comment.
This script writes a long-lived API token to disk. On POSIX systems, the file may be created with permissive permissions depending on the user's umask. Consider explicitly setting restrictive permissions (e.g., 0600) on the key file after writing to reduce accidental exposure to other users on the machine.
| key_file.seek(0) | ||
| key_file.write(key_string) | ||
| key_file.truncate() |
There was a problem hiding this comment.
Minor: opening the file with mode "w" already truncates it, so the subsequent seek(0)/truncate() calls are redundant. Removing them would simplify the example.
| key_file.seek(0) | |
| key_file.write(key_string) | |
| key_file.truncate() | |
| key_file.write(key_string) |
| # This example demonstrates how to programatically generate a new Civis API key | ||
| # and update a local configuration file with the new key. This script will need | ||
| # to be automated locally, such as with cron, or run manually periodically. | ||
| # | ||
| # This example expects a .civis file in the user's home directory | ||
| # A single line is written to this file setting the API key. This file is then | ||
| # imported to the shell configuration script on the system | ||
| # such as with .source ~/.civis in your .bashrc or .zshrc file on Posix systems. | ||
| # | ||
| # For Windows based systems, replace the path below with an absolute path to a .env | ||
| # file in your project folder. Then load that value at the top of your scripts such | ||
| # as with dotenv: https://pypi.org/project/python-dotenv/#getting-started | ||
|
|
||
|
|
||
| _KEY_FILE = Path("~/.civis").expanduser() | ||
| # _KEY_FILE = Path.WindowsPath("c:/absolute/path/to/.env") | ||
|
|
||
| current_time = datetime.now().isoformat() | ||
|
|
||
| # This assumes that there is already a valid API key configured on the system. If no | ||
| # key is present or the key is expired, this block will fail. | ||
| client = civis.APIClient() | ||
| user = client.users.list_me() | ||
|
|
||
| # the new key is generated | ||
| # in this example, the key expires after 1 day or 86400 seconds | ||
| # maximum API key expiration is 30 days. | ||
| new_key_rep = client.users.post_api_keys( | ||
| "me", expires_in=86400, name=f"{user.username}_local_key_regerated_{current_time}" | ||
| ) | ||
|
|
||
| key_string = f"CIVIS_API_KEY={new_key_rep.token}" | ||
|
|
||
|
|
||
| # finally now that a new key has been generated, | ||
| with open(_KEY_FILE, "w") as key_file: | ||
| key_file.seek(0) | ||
| key_file.write(key_string) | ||
| key_file.truncate() |
There was a problem hiding this comment.
This module executes API calls and writes secrets at import time. Wrapping the logic in a main() and adding an if __name__ == '__main__': guard helps prevent accidental execution when the file is imported (and aligns with other examples in this repo).
| # This example demonstrates how to programatically generate a new Civis API key | |
| # and update a local configuration file with the new key. This script will need | |
| # to be automated locally, such as with cron, or run manually periodically. | |
| # | |
| # This example expects a .civis file in the user's home directory | |
| # A single line is written to this file setting the API key. This file is then | |
| # imported to the shell configuration script on the system | |
| # such as with .source ~/.civis in your .bashrc or .zshrc file on Posix systems. | |
| # | |
| # For Windows based systems, replace the path below with an absolute path to a .env | |
| # file in your project folder. Then load that value at the top of your scripts such | |
| # as with dotenv: https://pypi.org/project/python-dotenv/#getting-started | |
| _KEY_FILE = Path("~/.civis").expanduser() | |
| # _KEY_FILE = Path.WindowsPath("c:/absolute/path/to/.env") | |
| current_time = datetime.now().isoformat() | |
| # This assumes that there is already a valid API key configured on the system. If no | |
| # key is present or the key is expired, this block will fail. | |
| client = civis.APIClient() | |
| user = client.users.list_me() | |
| # the new key is generated | |
| # in this example, the key expires after 1 day or 86400 seconds | |
| # maximum API key expiration is 30 days. | |
| new_key_rep = client.users.post_api_keys( | |
| "me", expires_in=86400, name=f"{user.username}_local_key_regerated_{current_time}" | |
| ) | |
| key_string = f"CIVIS_API_KEY={new_key_rep.token}" | |
| # finally now that a new key has been generated, | |
| with open(_KEY_FILE, "w") as key_file: | |
| key_file.seek(0) | |
| key_file.write(key_string) | |
| key_file.truncate() | |
| # This example demonstrates how to programatically generate a new Civis API key | |
| # and update a local configuration file with the new key. This script will need | |
| # to be automated locally, such as with cron, or run manually periodically. | |
| # | |
| # This example expects a .civis file in the user's home directory | |
| # A single line is written to this file setting the API key. This file is then | |
| # imported to the shell configuration script on the system | |
| # such as with .source ~/.civis in your .bashrc or .zshrc file on Posix systems. | |
| # | |
| # For Windows based systems, replace the path below with an absolute path to a .env | |
| # file in your project folder. Then load that value at the top of your scripts such | |
| # as with dotenv: https://pypi.org/project/python-dotenv/#getting-started | |
| _KEY_FILE = Path("~/.civis").expanduser() | |
| # _KEY_FILE = Path.WindowsPath("c:/absolute/path/to/.env") | |
| def main(): | |
| current_time = datetime.now().isoformat() | |
| # This assumes that there is already a valid API key configured on the system. If no | |
| # key is present or the key is expired, this block will fail. | |
| client = civis.APIClient() | |
| user = client.users.list_me() | |
| # the new key is generated | |
| # in this example, the key expires after 1 day or 86400 seconds | |
| # maximum API key expiration is 30 days. | |
| new_key_rep = client.users.post_api_keys( | |
| "me", expires_in=86400, name=f"{user.username}_local_key_regerated_{current_time}" | |
| ) | |
| key_string = f"CIVIS_API_KEY={new_key_rep.token}" | |
| # finally now that a new key has been generated, | |
| with open(_KEY_FILE, "w") as key_file: | |
| key_file.seek(0) | |
| key_file.write(key_string) | |
| key_file.truncate() | |
| if __name__ == "__main__": | |
| main() |
| from pathlib import Path | ||
| from datetime import datetime | ||
|
|
||
| # This example demonstrates how to programatically generate a new Civis API key |
There was a problem hiding this comment.
Spelling: "programatically" should be "programmatically" in the header comment.
| # This example demonstrates how to programatically generate a new Civis API key | |
| # This example demonstrates how to programmatically generate a new Civis API key |
| # This example expects a .civis file in the user's home directory | ||
| # A single line is written to this file setting the API key. This file is then | ||
| # imported to the shell configuration script on the system | ||
| # such as with .source ~/.civis in your .bashrc or .zshrc file on Posix systems. |
There was a problem hiding this comment.
The instructions for sourcing the file look incorrect/unclear: in POSIX shells the command is source ~/.civis or . ~/.civis (not .source). Also consider using the standard capitalization "POSIX" for clarity.
| # such as with .source ~/.civis in your .bashrc or .zshrc file on Posix systems. | |
| # such as with . ~/.civis in your .bashrc or .zshrc file on POSIX systems. |
| # in this example, the key expires after 1 day or 86400 seconds | ||
| # maximum API key expiration is 30 days. | ||
| new_key_rep = client.users.post_api_keys( | ||
| "me", expires_in=86400, name=f"{user.username}_local_key_regerated_{current_time}" |
There was a problem hiding this comment.
Spelling in the API key name: "key_regerated" is likely meant to be "key_regenerated". This ends up in the created key's name, so the typo will be visible in Platform.
| "me", expires_in=86400, name=f"{user.username}_local_key_regerated_{current_time}" | |
| "me", expires_in=86400, name=f"{user.username}_local_key_regenerated_{current_time}" |
| "me", expires_in=86400, name=f"{user.username}_local_key_regerated_{current_time}" | ||
| ) | ||
|
|
||
| key_string = f"CIVIS_API_KEY={new_key_rep.token}" |
There was a problem hiding this comment.
As written, the file content sets a shell variable but does not export it. If users follow the guidance to source this file, child processes (like a new python process) will not see CIVIS_API_KEY unless it is exported. Consider writing export CIVIS_API_KEY=... (and typically a trailing newline), or update the docs to match the intended consumption method.
| key_string = f"CIVIS_API_KEY={new_key_rep.token}" | |
| key_string = f"export CIVIS_API_KEY={new_key_rep.token}\n" |
New example to generate an API key using the python client. This script generates a new key and writes that to a configuration file.
I'm not very familiar with windows and don't have a machine to test this on but I tested this successfully on my Mac.