Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

## Unreleased

### Destinations: batch secret rotation

New method on `client.destinations`:

- `batch_update(team_id, *, destination_type=, updates=)` — rotate secrets for
up to 100 destinations of the same type in a single request. Each update is
applied independently; partial failures are reported per item with
`has_errors`, `error_code` and `message`.

Available on sync and async clients, mirrored under `with_raw_response`,
and takes the usual `auth_token` / `headers` / `timeout` overrides.

`BatchUpdateDestinationsBodyUpdatesItem` is exported from `supermetrics` for
convenience:
`from supermetrics import BatchUpdateDestinationsBodyUpdatesItem`.

### Table Groups: list, export, import, edit

New `client.table_groups` resource with four methods:
Expand Down
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Official Python client for Supermetrics
* Fully typed request and response models, generated from the spec as `attrs` classes
* Comprehensive API coverage: login links (including update), logins (including account
listing and revocation), accounts, queries, DWH transfers (including clone and batch
create) and transfer runs, DWH destinations, DWH table groups (list, export, import,
create) and transfer runs, DWH destinations (including batch secret rotation), DWH table groups (list, export, import,
edit), DWH backfills, custom fields, data blending, account tags, Connector Builder
* Custom exception hierarchy with HTTP status code mapping
* Resource-based API organization
Expand Down Expand Up @@ -449,6 +449,22 @@ if usage.is_used:
print(f"still used by {transfer.transfer_id}: {transfer.transfer_name}")
else:
client.destinations.delete(team_id=12345, destination_id=8)

# Rotate secrets for multiple destinations of the same type in one call
from supermetrics import BatchUpdateDestinationsBodyUpdatesItem

results = client.destinations.batch_update(
team_id=12345,
destination_type="DWH_SNOWFLAKE",
updates=[
BatchUpdateDestinationsBodyUpdatesItem(destination_id=8, new_secret="not-a-real-new-password"),
BatchUpdateDestinationsBodyUpdatesItem(destination_id=9, new_secret="not-a-real-new-password"),
],
)
if results.has_errors:
for item in results.results:
if item.status == "error":
print(f" destination {item.destination_id} failed: {item.error_code}")
```

### Data Warehouse Table Groups
Expand Down
44 changes: 43 additions & 1 deletion docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -2621,7 +2621,49 @@ else:
client.destinations.delete(team_id=12345, destination_id=8)
```

**Async usage** (all seven methods above are also available on
#### batch_update()

Rotate secrets for multiple destinations of the same type in a single request.
Each update is applied independently — if one fails, the others still succeed.

```python
from supermetrics import BatchUpdateDestinationsBodyUpdatesItem

results = client.destinations.batch_update(
team_id=12345,
destination_type="DWH_SNOWFLAKE",
updates=[
BatchUpdateDestinationsBodyUpdatesItem(destination_id=8, new_secret="not-a-real-new-password"),
BatchUpdateDestinationsBodyUpdatesItem(destination_id=9, new_secret="not-a-real-new-password"),
],
)
```

**Parameters:**

- `team_id` (int, required): Unique identifier of the team
- `destination_type` (str, required): Destination type shared by all items in the batch
(e.g. `"DWH_SNOWFLAKE"`)
- `updates` (list[BatchUpdateDestinationsBodyUpdatesItem], required): Secret rotations to
apply — each carries `destination_id` and `new_secret`. Between 1 and 100 items;
duplicates are rejected.

**Returns:** `BatchUpdateDestinationsResponse200Data` with `has_errors` (bool) and
`results`, a list of items carrying `destination_id`, `status` (`"success"` or `"error"`),
and, on failure, `error_code` and `message`.

**Raises:** `SupermetricsAuthError` (401), `SupermetricsForbiddenError` (403), `SupermetricsValidationError` (400), `SupermetricsRateLimitError` (429), `SupermetricsServerError` (500), `NetworkError`

**Example:**

```python
if results.has_errors:
for item in results.results:
if item.status == "error":
print(f" destination {item.destination_id} failed: {item.error_code}")
```

**Async usage** (all eight methods above are also available on
`DestinationsAsyncResource`):

```python
Expand Down
115 changes: 115 additions & 0 deletions openapi-spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1568,6 +1568,121 @@ paths:
$ref: '#/components/responses/InternalServerError'
security:
- ApiKeyAuth: []
/teams/{team_id}/destinations/batch:
patch:
summary: Batch rotate destination secrets
description: 'Rotate secrets for multiple destinations of the same type in a
single request.

Each update is applied independently — if one fails, the others still succeed.


Batch-level validations (checked before any processing):

- The updates array must contain between 1 and 100 items.

- Each item must include a valid destination_id and a non-empty new_secret.

- Duplicate destination_id values are not allowed.

'
operationId: batchUpdateDestinations
tags:
- Data Destinations
requestBody:
description: Batch of secret rotations sharing a single destination type
required: true
content:
application/json:
schema:
type: object
required:
- type
- updates
properties:
type:
type: string
description: Destination type shared by all items in the batch
example: DWH_SNOWFLAKE
updates:
type: array
minItems: 1
maxItems: 100
items:
type: object
required:
- destination_id
- new_secret
properties:
destination_id:
type: integer
description: ID of the destination to rotate the secret for
new_secret:
type: string
description: New secret value for credential rotation
responses:
'200':
description: Batch processed
headers:
Access-Control-Allow-Origin:
$ref: '#/components/headers/Access-Control-Allow-Origin'
content:
application/json:
schema:
type: object
properties:
meta:
$ref: '#/components/schemas/Meta'
data:
type: object
required:
- has_errors
- results
properties:
has_errors:
type: boolean
description: True if any item in the batch failed. Allows
quick failure detection without iterating all results.
results:
type: array
items:
type: object
required:
- destination_id
- status
properties:
destination_id:
type: integer
status:
type: string
enum:
- success
- error
error_code:
type: string
description: Error code identifying the failure reason.
Only present when status is error.
message:
type: string
description: Human-readable error description. Only
present when status is error.
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
security:
- ApiKeyAuth: []
parameters:
- $ref: '#/components/parameters/TeamId'
servers:
- url: https://dts-api.supermetrics.com/v1
description: Global production public Supermetrics Data Warehouse Destinations
API base path.
x-internal: false
/teams/{team_id}/destinations/test-connection:
post:
summary: Test destination connection
Expand Down
2 changes: 2 additions & 0 deletions scripts/references/sdk-endpoint-filters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ endpoints:
path: /teams/{team_id}/destinations/test-connection
- method: GET
path: /teams/{team_id}/destinations/{destination_id}/usage
- method: PATCH
path: /teams/{team_id}/destinations/batch

# Table Groups
#
Expand Down
5 changes: 5 additions & 0 deletions src/supermetrics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

from supermetrics.__version__ import __version__
from supermetrics._auth import AsyncTokenProvider, TokenProvider
from supermetrics._generated.supermetrics_api_client.models.batch_update_destinations_body_updates_item import (
BatchUpdateDestinationsBodyUpdatesItem,
)
from supermetrics._generated.supermetrics_api_client.models.blend_config import BlendConfig
from supermetrics._generated.supermetrics_api_client.models.blend_config_query_table import BlendConfigQueryTable
from supermetrics._generated.supermetrics_api_client.models.blend_datasource_field_ref import BlendDatasourceFieldRef
Expand Down Expand Up @@ -107,6 +110,8 @@
"TransferDataSourceSetting",
"CloneTransferBody",
"TransferConfigurationRequest",
# Destination batch update. batch_update() takes a list of these.
"BatchUpdateDestinationsBodyUpdatesItem",
# Table group request models. import_ and edit take these as the body payload.
"ImportTableGroupBody",
"EditTableGroupBody",
Expand Down
Loading