-
Notifications
You must be signed in to change notification settings - Fork 1
add example for generating an API key with the Python Client #48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,43 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import civis | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from pathlib import Path | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from datetime import datetime | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 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. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 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. |
Copilot
AI
Apr 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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}" |
Copilot
AI
Apr 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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" |
Copilot
AI
Apr 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Copilot
AI
Apr 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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) |
Copilot
AI
Apr 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spelling: "programatically" should be "programmatically" in the header comment.