asa-api-client 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- asa_api_client-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +80 -0
- asa_api_client-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- asa_api_client-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +37 -0
- asa_api_client-0.1.0/.github/dependabot.yml +24 -0
- asa_api_client-0.1.0/.github/workflows/ci.yml +46 -0
- asa_api_client-0.1.0/.github/workflows/docs.yml +54 -0
- asa_api_client-0.1.0/.github/workflows/publish.yml +29 -0
- asa_api_client-0.1.0/.gitignore +57 -0
- asa_api_client-0.1.0/LICENSE +21 -0
- asa_api_client-0.1.0/PKG-INFO +236 -0
- asa_api_client-0.1.0/README.md +193 -0
- asa_api_client-0.1.0/asa_api_client/__init__.py +50 -0
- asa_api_client-0.1.0/asa_api_client/auth.py +462 -0
- asa_api_client-0.1.0/asa_api_client/client.py +332 -0
- asa_api_client-0.1.0/asa_api_client/exceptions.py +221 -0
- asa_api_client-0.1.0/asa_api_client/logging.py +128 -0
- asa_api_client-0.1.0/asa_api_client/models/__init__.py +106 -0
- asa_api_client-0.1.0/asa_api_client/models/ad_groups.py +301 -0
- asa_api_client-0.1.0/asa_api_client/models/base.py +345 -0
- asa_api_client-0.1.0/asa_api_client/models/campaigns.py +255 -0
- asa_api_client-0.1.0/asa_api_client/models/keywords.py +196 -0
- asa_api_client-0.1.0/asa_api_client/models/reports.py +359 -0
- asa_api_client-0.1.0/asa_api_client/resources/__init__.py +19 -0
- asa_api_client-0.1.0/asa_api_client/resources/ad_groups.py +152 -0
- asa_api_client-0.1.0/asa_api_client/resources/base.py +593 -0
- asa_api_client-0.1.0/asa_api_client/resources/campaigns.py +158 -0
- asa_api_client-0.1.0/asa_api_client/resources/keywords.py +269 -0
- asa_api_client-0.1.0/asa_api_client/resources/reports.py +504 -0
- asa_api_client-0.1.0/asa_api_client/settings.py +126 -0
- asa_api_client-0.1.0/asa_api_client/utils/__init__.py +1 -0
- asa_api_client-0.1.0/docs/CNAME +1 -0
- asa_api_client-0.1.0/docs/api/client.md +10 -0
- asa_api_client-0.1.0/docs/api/exceptions.md +90 -0
- asa_api_client-0.1.0/docs/api/models.md +54 -0
- asa_api_client-0.1.0/docs/getting-started/authentication.md +75 -0
- asa_api_client-0.1.0/docs/getting-started/installation.md +45 -0
- asa_api_client-0.1.0/docs/getting-started/quickstart.md +86 -0
- asa_api_client-0.1.0/docs/guide/ad-groups.md +57 -0
- asa_api_client-0.1.0/docs/guide/async.md +80 -0
- asa_api_client-0.1.0/docs/guide/campaigns.md +79 -0
- asa_api_client-0.1.0/docs/guide/keywords.md +70 -0
- asa_api_client-0.1.0/docs/guide/reports.md +87 -0
- asa_api_client-0.1.0/docs/index.md +45 -0
- asa_api_client-0.1.0/mkdocs.yml +71 -0
- asa_api_client-0.1.0/pyproject.toml +133 -0
- asa_api_client-0.1.0/tests/__init__.py +1 -0
- asa_api_client-0.1.0/tests/unit/__init__.py +1 -0
- asa_api_client-0.1.0/tests/unit/test_models.py +93 -0
- asa_api_client-0.1.0/uv.lock +1295 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
name: Bug Report
|
|
2
|
+
description: Report a bug or unexpected behavior
|
|
3
|
+
labels: ["type: bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for taking the time to report a bug! Please fill out the form below.
|
|
9
|
+
|
|
10
|
+
- type: textarea
|
|
11
|
+
id: description
|
|
12
|
+
attributes:
|
|
13
|
+
label: Description
|
|
14
|
+
description: A clear and concise description of what the bug is.
|
|
15
|
+
placeholder: Describe the bug...
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: reproduction
|
|
21
|
+
attributes:
|
|
22
|
+
label: Steps to Reproduce
|
|
23
|
+
description: Steps to reproduce the behavior.
|
|
24
|
+
placeholder: |
|
|
25
|
+
1. Create a client with...
|
|
26
|
+
2. Call method...
|
|
27
|
+
3. See error...
|
|
28
|
+
validations:
|
|
29
|
+
required: true
|
|
30
|
+
|
|
31
|
+
- type: textarea
|
|
32
|
+
id: expected
|
|
33
|
+
attributes:
|
|
34
|
+
label: Expected Behavior
|
|
35
|
+
description: What you expected to happen.
|
|
36
|
+
validations:
|
|
37
|
+
required: true
|
|
38
|
+
|
|
39
|
+
- type: textarea
|
|
40
|
+
id: actual
|
|
41
|
+
attributes:
|
|
42
|
+
label: Actual Behavior
|
|
43
|
+
description: What actually happened.
|
|
44
|
+
validations:
|
|
45
|
+
required: true
|
|
46
|
+
|
|
47
|
+
- type: input
|
|
48
|
+
id: version
|
|
49
|
+
attributes:
|
|
50
|
+
label: Package Version
|
|
51
|
+
description: What version of search-ads-api are you using?
|
|
52
|
+
placeholder: "0.1.0"
|
|
53
|
+
validations:
|
|
54
|
+
required: true
|
|
55
|
+
|
|
56
|
+
- type: input
|
|
57
|
+
id: python-version
|
|
58
|
+
attributes:
|
|
59
|
+
label: Python Version
|
|
60
|
+
description: What version of Python are you using?
|
|
61
|
+
placeholder: "3.13.0"
|
|
62
|
+
validations:
|
|
63
|
+
required: true
|
|
64
|
+
|
|
65
|
+
- type: dropdown
|
|
66
|
+
id: os
|
|
67
|
+
attributes:
|
|
68
|
+
label: Operating System
|
|
69
|
+
options:
|
|
70
|
+
- macOS
|
|
71
|
+
- Linux
|
|
72
|
+
- Windows
|
|
73
|
+
validations:
|
|
74
|
+
required: true
|
|
75
|
+
|
|
76
|
+
- type: textarea
|
|
77
|
+
id: additional
|
|
78
|
+
attributes:
|
|
79
|
+
label: Additional Context
|
|
80
|
+
description: Any other context about the problem (logs, screenshots, etc.)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest a new feature or enhancement
|
|
3
|
+
labels: ["type: feature"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for suggesting a feature! Please fill out the form below.
|
|
9
|
+
|
|
10
|
+
- type: textarea
|
|
11
|
+
id: problem
|
|
12
|
+
attributes:
|
|
13
|
+
label: Problem Statement
|
|
14
|
+
description: What problem would this feature solve? Is it related to a frustration?
|
|
15
|
+
placeholder: I'm always frustrated when...
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: solution
|
|
21
|
+
attributes:
|
|
22
|
+
label: Proposed Solution
|
|
23
|
+
description: Describe the solution you'd like to see.
|
|
24
|
+
validations:
|
|
25
|
+
required: true
|
|
26
|
+
|
|
27
|
+
- type: textarea
|
|
28
|
+
id: alternatives
|
|
29
|
+
attributes:
|
|
30
|
+
label: Alternatives Considered
|
|
31
|
+
description: Have you considered any alternative solutions or workarounds?
|
|
32
|
+
|
|
33
|
+
- type: textarea
|
|
34
|
+
id: additional
|
|
35
|
+
attributes:
|
|
36
|
+
label: Additional Context
|
|
37
|
+
description: Any other context, screenshots, or examples.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
commit-message:
|
|
8
|
+
prefix: "⬆️"
|
|
9
|
+
labels:
|
|
10
|
+
- "dependencies"
|
|
11
|
+
groups:
|
|
12
|
+
python-packages:
|
|
13
|
+
patterns:
|
|
14
|
+
- "*"
|
|
15
|
+
|
|
16
|
+
- package-ecosystem: "github-actions"
|
|
17
|
+
directory: "/"
|
|
18
|
+
schedule:
|
|
19
|
+
interval: "weekly"
|
|
20
|
+
commit-message:
|
|
21
|
+
prefix: "👷"
|
|
22
|
+
labels:
|
|
23
|
+
- "dependencies"
|
|
24
|
+
- "github-actions"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.13"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v6
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@v7
|
|
21
|
+
with:
|
|
22
|
+
version: "latest"
|
|
23
|
+
|
|
24
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
25
|
+
run: uv python install ${{ matrix.python-version }}
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: uv sync --extra dev
|
|
29
|
+
|
|
30
|
+
- name: Run linting
|
|
31
|
+
run: uv run ruff check .
|
|
32
|
+
|
|
33
|
+
- name: Run formatting check
|
|
34
|
+
run: uv run ruff format --check .
|
|
35
|
+
|
|
36
|
+
- name: Run type checking
|
|
37
|
+
run: uv run mypy asa_api_client
|
|
38
|
+
|
|
39
|
+
- name: Run tests
|
|
40
|
+
run: uv run pytest --cov=asa_api_client --cov-report=xml
|
|
41
|
+
|
|
42
|
+
- name: Upload coverage to Codecov
|
|
43
|
+
uses: codecov/codecov-action@v5
|
|
44
|
+
with:
|
|
45
|
+
file: ./coverage.xml
|
|
46
|
+
fail_ci_if_error: false
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Deploy Documentation
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: "pages"
|
|
15
|
+
cancel-in-progress: false
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Install uv
|
|
24
|
+
uses: astral-sh/setup-uv@v4
|
|
25
|
+
with:
|
|
26
|
+
version: "latest"
|
|
27
|
+
|
|
28
|
+
- name: Set up Python
|
|
29
|
+
run: uv python install 3.13
|
|
30
|
+
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: uv sync --extra docs
|
|
33
|
+
|
|
34
|
+
- name: Build documentation
|
|
35
|
+
run: uv run mkdocs build
|
|
36
|
+
|
|
37
|
+
- name: Setup Pages
|
|
38
|
+
uses: actions/configure-pages@v4
|
|
39
|
+
|
|
40
|
+
- name: Upload artifact
|
|
41
|
+
uses: actions/upload-pages-artifact@v3
|
|
42
|
+
with:
|
|
43
|
+
path: site
|
|
44
|
+
|
|
45
|
+
deploy:
|
|
46
|
+
environment:
|
|
47
|
+
name: github-pages
|
|
48
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
needs: build
|
|
51
|
+
steps:
|
|
52
|
+
- name: Deploy to GitHub Pages
|
|
53
|
+
id: deployment
|
|
54
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
environment: pypi
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write # Required for trusted publishing
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v6
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v7
|
|
19
|
+
with:
|
|
20
|
+
version: "latest"
|
|
21
|
+
|
|
22
|
+
- name: Set up Python
|
|
23
|
+
run: uv python install 3.13
|
|
24
|
+
|
|
25
|
+
- name: Build package
|
|
26
|
+
run: uv build
|
|
27
|
+
|
|
28
|
+
- name: Publish to PyPI
|
|
29
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual environments
|
|
24
|
+
.venv/
|
|
25
|
+
venv/
|
|
26
|
+
ENV/
|
|
27
|
+
|
|
28
|
+
# IDE
|
|
29
|
+
.idea/
|
|
30
|
+
.vscode/
|
|
31
|
+
*.swp
|
|
32
|
+
*.swo
|
|
33
|
+
|
|
34
|
+
# Testing
|
|
35
|
+
.pytest_cache/
|
|
36
|
+
.coverage
|
|
37
|
+
htmlcov/
|
|
38
|
+
.tox/
|
|
39
|
+
.nox/
|
|
40
|
+
|
|
41
|
+
# mypy
|
|
42
|
+
.mypy_cache/
|
|
43
|
+
|
|
44
|
+
# ruff
|
|
45
|
+
.ruff_cache/
|
|
46
|
+
|
|
47
|
+
# Documentation
|
|
48
|
+
site/
|
|
49
|
+
|
|
50
|
+
# Environment
|
|
51
|
+
.env
|
|
52
|
+
.env.local
|
|
53
|
+
*.pem
|
|
54
|
+
|
|
55
|
+
# OS
|
|
56
|
+
.DS_Store
|
|
57
|
+
Thumbs.db
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Peth Pty Ltd
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: asa-api-client
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A modern Python client for the Apple Search Ads API with full type safety and async support
|
|
5
|
+
Project-URL: Homepage, https://github.com/SamPetherbridge/asa-api-client
|
|
6
|
+
Project-URL: Documentation, https://asa-api-client.peth.au
|
|
7
|
+
Project-URL: Repository, https://github.com/SamPetherbridge/asa-api-client
|
|
8
|
+
Project-URL: Issues, https://github.com/SamPetherbridge/asa-api-client/issues
|
|
9
|
+
Author-email: Peth Pty Ltd <hello@peth.com.au>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: advertising,api,apple,asa,async,pydantic,search-ads
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Framework :: Pydantic :: 2
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.13
|
|
22
|
+
Requires-Dist: httpx>=0.27.0
|
|
23
|
+
Requires-Dist: pydantic-settings>=2.6.0
|
|
24
|
+
Requires-Dist: pydantic>=2.10.0
|
|
25
|
+
Requires-Dist: pyjwt[crypto]>=2.9.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: mypy>=1.13.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pandas-stubs>=2.2.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pandas>=2.2.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pre-commit>=4.0.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-cov>=6.0.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest-httpx>=0.34.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest>=8.3.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: ruff>=0.8.0; extra == 'dev'
|
|
36
|
+
Provides-Extra: docs
|
|
37
|
+
Requires-Dist: mkdocs-material>=9.5.0; extra == 'docs'
|
|
38
|
+
Requires-Dist: mkdocs>=1.6.0; extra == 'docs'
|
|
39
|
+
Requires-Dist: mkdocstrings[python]>=0.27.0; extra == 'docs'
|
|
40
|
+
Provides-Extra: pandas
|
|
41
|
+
Requires-Dist: pandas>=2.2.0; extra == 'pandas'
|
|
42
|
+
Description-Content-Type: text/markdown
|
|
43
|
+
|
|
44
|
+
# ASA API Client
|
|
45
|
+
|
|
46
|
+
[](https://pypi.org/project/asa-api-client/)
|
|
47
|
+
[](https://pypi.org/project/asa-api-client/)
|
|
48
|
+
[](https://github.com/SamPetherbridge/asa-api-client/blob/main/LICENSE)
|
|
49
|
+
[](https://github.com/SamPetherbridge/asa-api-client/actions/workflows/ci.yml)
|
|
50
|
+
|
|
51
|
+
A modern, fully-typed Python client for the Apple Search Ads API with async support and Pydantic models.
|
|
52
|
+
|
|
53
|
+
## Features
|
|
54
|
+
|
|
55
|
+
- **Full Type Safety** - Complete type hints with strict mypy compliance
|
|
56
|
+
- **Async Support** - Both sync and async methods in a unified client
|
|
57
|
+
- **Pydantic Models** - Validated request/response models
|
|
58
|
+
- **Resource-based API** - Intuitive `client.campaigns.list()` pattern
|
|
59
|
+
- **Automatic Pagination** - `iter_all()` and `iter_all_async()` helpers
|
|
60
|
+
- **Reports with Pandas** - Optional DataFrame export
|
|
61
|
+
|
|
62
|
+
## Installation
|
|
63
|
+
|
|
64
|
+
Using [uv](https://docs.astral.sh/uv/) (recommended):
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
uv add asa-api-client
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Using pip:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pip install asa-api-client
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
With pandas support:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
uv add "asa-api-client[pandas]"
|
|
80
|
+
# or
|
|
81
|
+
pip install "asa-api-client[pandas]"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Quick Start
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from asa_api_client import AppleSearchAdsClient
|
|
88
|
+
|
|
89
|
+
# From environment variables
|
|
90
|
+
client = AppleSearchAdsClient.from_env()
|
|
91
|
+
|
|
92
|
+
# Or explicit configuration
|
|
93
|
+
client = AppleSearchAdsClient(
|
|
94
|
+
client_id="SEARCHADS.xxx",
|
|
95
|
+
team_id="SEARCHADS.xxx",
|
|
96
|
+
key_id="xxx",
|
|
97
|
+
org_id=123456,
|
|
98
|
+
private_key_path="private-key.pem",
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# List campaigns
|
|
102
|
+
with client:
|
|
103
|
+
campaigns = client.campaigns.list()
|
|
104
|
+
for campaign in campaigns:
|
|
105
|
+
print(f"{campaign.name}: {campaign.status}")
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Environment Variables
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
export ASA_CLIENT_ID="SEARCHADS.your-client-id"
|
|
112
|
+
export ASA_TEAM_ID="SEARCHADS.your-team-id"
|
|
113
|
+
export ASA_KEY_ID="your-key-id"
|
|
114
|
+
export ASA_ORG_ID="123456"
|
|
115
|
+
export ASA_PRIVATE_KEY_PATH="/path/to/private-key.pem"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Or use a `.env` file:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
ASA_CLIENT_ID=SEARCHADS.your-client-id
|
|
122
|
+
ASA_TEAM_ID=SEARCHADS.your-team-id
|
|
123
|
+
ASA_KEY_ID=your-key-id
|
|
124
|
+
ASA_ORG_ID=123456
|
|
125
|
+
ASA_PRIVATE_KEY_PATH=private-key.pem
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Resources
|
|
129
|
+
|
|
130
|
+
### Campaigns
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
# List all campaigns
|
|
134
|
+
campaigns = client.campaigns.list()
|
|
135
|
+
|
|
136
|
+
# Get a specific campaign
|
|
137
|
+
campaign = client.campaigns.get(campaign_id)
|
|
138
|
+
|
|
139
|
+
# Find with filters
|
|
140
|
+
from asa_api_client.models import Selector
|
|
141
|
+
enabled = client.campaigns.find(
|
|
142
|
+
Selector().where("status", "==", "ENABLED")
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Create a campaign
|
|
146
|
+
from asa_api_client.models import CampaignCreate, Money, CampaignSupplySource
|
|
147
|
+
campaign = client.campaigns.create(
|
|
148
|
+
CampaignCreate(
|
|
149
|
+
name="My Campaign",
|
|
150
|
+
adam_id=123456789,
|
|
151
|
+
countries_or_regions=["US"],
|
|
152
|
+
daily_budget_amount=Money(amount="100", currency="USD"),
|
|
153
|
+
supply_sources=[CampaignSupplySource.APPSTORE_SEARCH_RESULTS],
|
|
154
|
+
)
|
|
155
|
+
)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Ad Groups
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
# Access ad groups through campaign
|
|
162
|
+
ad_groups = client.campaigns(campaign_id).ad_groups.list()
|
|
163
|
+
|
|
164
|
+
# Create an ad group
|
|
165
|
+
from asa_api_client.models import AdGroupCreate
|
|
166
|
+
ad_group = client.campaigns(campaign_id).ad_groups.create(
|
|
167
|
+
AdGroupCreate(
|
|
168
|
+
name="My Ad Group",
|
|
169
|
+
default_bid_amount=Money(amount="1.00", currency="USD"),
|
|
170
|
+
)
|
|
171
|
+
)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Keywords
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
# List keywords in an ad group
|
|
178
|
+
keywords = client.campaigns(campaign_id).ad_groups(ad_group_id).keywords.list()
|
|
179
|
+
|
|
180
|
+
# Create keywords (bulk only)
|
|
181
|
+
from asa_api_client.models import KeywordCreate, KeywordMatchType
|
|
182
|
+
result = client.campaigns(campaign_id).ad_groups(ad_group_id).keywords.create_bulk([
|
|
183
|
+
KeywordCreate(
|
|
184
|
+
text="my keyword",
|
|
185
|
+
match_type=KeywordMatchType.EXACT,
|
|
186
|
+
bid_amount=Money(amount="1.50", currency="USD"),
|
|
187
|
+
)
|
|
188
|
+
])
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Reports
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
from datetime import date
|
|
195
|
+
|
|
196
|
+
# Campaign report
|
|
197
|
+
report = client.reports.campaigns(
|
|
198
|
+
start_date=date(2024, 1, 1),
|
|
199
|
+
end_date=date(2024, 1, 31),
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
# Convert to DataFrame (requires pandas)
|
|
203
|
+
df = report.to_dataframe()
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Async Usage
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
import asyncio
|
|
210
|
+
|
|
211
|
+
async def main():
|
|
212
|
+
client = AppleSearchAdsClient.from_env()
|
|
213
|
+
|
|
214
|
+
async with client:
|
|
215
|
+
campaigns = await client.campaigns.list_async()
|
|
216
|
+
|
|
217
|
+
# Async iteration
|
|
218
|
+
async for campaign in client.campaigns.iter_all_async():
|
|
219
|
+
print(campaign.name)
|
|
220
|
+
|
|
221
|
+
asyncio.run(main())
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## CLI
|
|
225
|
+
|
|
226
|
+
For a command-line interface, install [search-ads-cli](https://github.com/SamPetherbridge/search-ads-cli):
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
uv add search-ads-cli
|
|
230
|
+
# or
|
|
231
|
+
pip install search-ads-cli
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## License
|
|
235
|
+
|
|
236
|
+
MIT License - Copyright (c) 2025 Peth Pty Ltd
|