rozsireni o keywords a uprava swaggeru
This commit is contained in:
@@ -38,6 +38,7 @@ app/
|
||||
credentials.py X- header dependencies (GA / GSC / Ads / Sklik)
|
||||
idempotency.py in-memory idempotency store for writes (opt-in per request)
|
||||
sklik_guards.py write guard rails: forced paused status, optional budget caps
|
||||
sklik_models.py typed request bodies for Sklik writes (Swagger schema; extra fields pass through)
|
||||
clients/
|
||||
google.py shared Google client: Bearer/SA token minting + requests
|
||||
sklik_client.py Sklik JSON-RPC client (login + session + list/report paging)
|
||||
|
||||
+42
-5
@@ -49,6 +49,7 @@ access denied, bad arguments) are surfaced as `upstream_error` with the Sklik
|
||||
| GET | `/sklik/campaigns` | `campaigns.list`, all pages collected. |
|
||||
| GET | `/sklik/groups` | `groups.list`, filterable by `campaign_ids`. |
|
||||
| GET | `/sklik/ads` | `ads.list`, filterable by `campaign_ids` / `group_ids`. |
|
||||
| GET | `/sklik/keywords` | `keywords.list`, filterable by `campaign_ids` / `group_ids`. |
|
||||
| POST | `/sklik/campaigns` `/sklik/groups` `/sklik/ads` | **Create — always paused.** |
|
||||
| PUT | `/sklik/campaigns` `/sklik/groups` `/sklik/ads` | **Update** by id (partial). |
|
||||
| DELETE | `/sklik/campaigns` `/sklik/groups` `/sklik/ads` | **Remove** (`?ids=1,2,3`) — reversible. |
|
||||
@@ -94,18 +95,48 @@ Query parameters:
|
||||
| Remove | `DELETE /sklik/{entity}?ids=1,2` | `{entity}.remove` | ids in the query |
|
||||
| Restore | `POST /sklik/{entity}/restore?ids=1,2` | `{entity}.restore` | ids in the query |
|
||||
|
||||
`{entity}` ∈ `campaigns`, `groups`, `ads`. The structs are exactly the ones Sklik
|
||||
`{entity}` ∈ `campaigns`, `groups`, `ads`, `keywords`. The structs are exactly the ones Sklik
|
||||
documents ([campaigns.create](https://api.sklik.cz/drak/campaigns.create.html),
|
||||
[campaigns.update](https://api.sklik.cz/drak/campaigns.update.html), and the
|
||||
`groups.*` / `ads.*` equivalents). Sklik batches are **all-or-nothing**: if one
|
||||
item fails, nothing is applied.
|
||||
|
||||
### Create — everything is paused, not configurable
|
||||
### The bodies are typed in Swagger
|
||||
|
||||
Create and update bodies are modelled (`app/sklik_models.py`), so `/docs` shows
|
||||
every field with its type, whether it is required, the allowed enum values
|
||||
(campaign `type`, `status`, `adType`, `adSelection`, `paymentMethod`,
|
||||
`premiseMode`, `videoFormat`) and a description with the unit. "Try it out" is
|
||||
therefore fillable without reading the Sklik docs first.
|
||||
|
||||
Two properties of the models matter:
|
||||
|
||||
- **They do not restrict you.** Every model accepts undeclared fields and
|
||||
forwards them to Sklik untouched, so the less common parts of the API
|
||||
(retargeting, product sets, anything Sklik adds later) keep working without a
|
||||
code change here. The schema documents the common path; it is not a whitelist.
|
||||
- **Update is genuinely partial.** Only the fields you actually send are
|
||||
forwarded, so omitting a field leaves it alone rather than resetting it. An
|
||||
explicit `null` is still sent (that is how you clear `totalBudget`).
|
||||
|
||||
Schema violations (missing required field, bad enum value) come back as **422**
|
||||
with the offending field in `detail[].loc` — before any Sklik call. The business
|
||||
guard rails (budget ceilings, blocked activation) return **400** / **403**.
|
||||
|
||||
### Create — campaigns, groups and ads are paused, not configurable
|
||||
|
||||
Sklik's `status` field **defaults to `active`**, so an omitted status would
|
||||
create a *live, spending* campaign. The proxy therefore forces
|
||||
`status: "suspend"` on every created entity and ignores any other value you
|
||||
send (the override is logged).
|
||||
`status: "suspend"` on every created campaign, group and ad, and ignores any
|
||||
other value you send (the override is logged).
|
||||
|
||||
> **Keywords are the exception** and are *not* forced. A keyword cannot spend
|
||||
> anything on its own — the campaign, group and ad above it are all created
|
||||
> paused, and those gate the spending. Forcing keywords paused as well would
|
||||
> only create a trap: you activate the campaign in the Sklik UI, nothing
|
||||
> happens, and the cause is a fourth paused level nobody expected. Sklik's own
|
||||
> default (`active`) applies; send `status` explicitly if you want otherwise.
|
||||
> `GET /sklik/write-limits` lists which entities are force-paused.
|
||||
|
||||
### Update — ordinary CRUD, status is not forced
|
||||
|
||||
@@ -125,7 +156,13 @@ way.
|
||||
> one, so the ad gets a **new id**. Re-read the group's ads after such an
|
||||
> update. Changing only `status` keeps the id.
|
||||
|
||||
`type` cannot be changed on a campaign.
|
||||
Immutable fields, so `PUT` does not offer them at all:
|
||||
|
||||
| Entity | Cannot be changed |
|
||||
| --- | --- |
|
||||
| campaign | `type` |
|
||||
| keyword | `name`, `matchType` — remove it and create a new one |
|
||||
| ad | the creative (see the note above) |
|
||||
|
||||
### Remove and restore — reversible
|
||||
|
||||
|
||||
Reference in New Issue
Block a user