@sandstormapp/sdk 0.2.0 → 1.0.0
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.
- package/README.md +73 -124
- package/dist/index.d.ts +126 -39
- package/dist/index.js +173 -64
- package/dist/openapi.d.ts +2438 -15121
- package/dist/openapi.js +1 -123
- package/openapi.json +5551 -19761
- package/package.json +13 -2
package/README.md
CHANGED
|
@@ -1,188 +1,137 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ads.dev
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The [ads.dev](https://ads.dev) API for Node, Deno, Bun and edge runtimes: image, video and audio generation with 34 models on your brand, the brand kit and library, and the ads your competitors run. Every model's input is typed, so the model you name decides what `input` takes.
|
|
4
|
+
|
|
5
|
+
It is published as `ads.dev`, `adsdotdev`, `sandstormapp` and `@sandstormapp/sdk`, the same package under four names, and needs nothing at runtime but `fetch` and Web Crypto.
|
|
4
6
|
|
|
5
7
|
```bash
|
|
6
|
-
|
|
8
|
+
npm install ads.dev
|
|
7
9
|
```
|
|
8
10
|
|
|
9
11
|
```ts
|
|
10
|
-
import { Sandstorm } from '
|
|
11
|
-
|
|
12
|
-
const sandstorm = new Sandstorm({ apiKey: process.env.SANDSTORM_API_KEY })
|
|
12
|
+
import { Sandstorm } from 'ads.dev'
|
|
13
13
|
|
|
14
|
-
const
|
|
15
|
-
{ prompt: 'A ceramic mug on a sunlit bench, steam rising, morning light', asset_name: 'Sunlit Mug' },
|
|
16
|
-
{ wait: 120 },
|
|
17
|
-
)
|
|
18
|
-
if (task.status === 'succeeded') console.log(task.files)
|
|
19
|
-
```
|
|
14
|
+
const sandstorm = new Sandstorm()
|
|
20
15
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
-d '{"prompt":"A ceramic mug on a sunlit bench, steam rising, morning light","asset_name":"Sunlit Mug"}'
|
|
16
|
+
const generation = await sandstorm.generations.run('nano-banana-pro', {
|
|
17
|
+
prompt: 'A ceramic mug on a sunlit bench, steam rising',
|
|
18
|
+
aspect_ratio: '4:5',
|
|
19
|
+
})
|
|
20
|
+
console.log(generation.output[0]?.url)
|
|
27
21
|
```
|
|
28
22
|
|
|
29
23
|
## A key
|
|
30
24
|
|
|
31
|
-
|
|
25
|
+
`new Sandstorm()` reads `SANDSTORM_API_KEY`. Make a key in Sandstorm under Settings → API keys, or in one command, which signs you in in the browser and writes the key to `.env`:
|
|
32
26
|
|
|
33
|
-
```
|
|
34
|
-
|
|
27
|
+
```bash
|
|
28
|
+
curl -fsSL https://ads.dev/login.mjs -o sandstorm-login.mjs && node sandstorm-login.mjs
|
|
35
29
|
```
|
|
36
30
|
|
|
37
|
-
`brand` is sent as `x-sandstorm-brand` on every request. `baseUrl` points the client somewhere other than `https://agent.sandstormapp.com`, such as an API running locally.
|
|
38
|
-
|
|
39
|
-
## Reading
|
|
40
|
-
|
|
41
|
-
A tool that only reads, such as `search_assets`, `read_offer` or `get_brand_identity`, is a `GET` with its arguments as query parameters, a list as its name repeated, and answers the tool's own JSON at once; the method takes the same arguments as an object:
|
|
42
|
-
|
|
43
31
|
```ts
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
32
|
+
new Sandstorm({
|
|
33
|
+
apiKey: process.env.SANDSTORM_API_KEY,
|
|
34
|
+
brand: '6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f',
|
|
35
|
+
baseUrl: 'https://ads.dev',
|
|
36
|
+
maxRetries: 2,
|
|
37
|
+
timeoutMs: 60_000,
|
|
38
|
+
})
|
|
51
39
|
```
|
|
52
40
|
|
|
53
|
-
A
|
|
41
|
+
A key acts on the brand it was made on; `brand` names another brand of the same organization. `baseUrl` defaults to `SANDSTORM_API_URL`, then `https://ads.dev`. Keep the key on your server: anyone who holds it spends your credits.
|
|
54
42
|
|
|
55
|
-
##
|
|
43
|
+
## Generations
|
|
56
44
|
|
|
57
|
-
|
|
45
|
+
`run` makes a generation and answers it once it has finished, holding each request on the API with `Prefer: wait` rather than polling. A generation that fails or is canceled throws `GenerationFailed`, which carries it.
|
|
58
46
|
|
|
59
47
|
```ts
|
|
60
|
-
const
|
|
61
|
-
// { task_id: '…', status: 'running' }
|
|
62
|
-
```
|
|
48
|
+
const still = await sandstorm.generations.run('nano-banana-2-lite', { prompt: 'Two lemons in a blue bowl' })
|
|
63
49
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
50
|
+
const clip = await sandstorm.generations.run('seedance-2.5/image-to-video', {
|
|
51
|
+
start_image: still.output[0]!.id,
|
|
52
|
+
prompt: 'Slow push in as the light warms',
|
|
53
|
+
resolution: '720p',
|
|
54
|
+
})
|
|
68
55
|
```
|
|
69
56
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
```ts
|
|
73
|
-
const answer = await sandstorm.tools.generate_image_nano_banana_pro({ prompt, asset_name: 'Sunlit Mug' }, { wait: 30 })
|
|
74
|
-
if (answer.status === 'running') console.log('still running', answer.task_id)
|
|
75
|
-
else console.log(answer.files)
|
|
76
|
-
```
|
|
57
|
+
Every media input takes an asset id (`asset_…`) or a public https URL, so the output of one generation goes straight into the next.
|
|
77
58
|
|
|
78
|
-
|
|
59
|
+
For work that runs long, queue it and come back to it, or take a webhook:
|
|
79
60
|
|
|
80
61
|
```ts
|
|
81
|
-
await sandstorm.
|
|
82
|
-
|
|
62
|
+
const queued = await sandstorm.generations.create('kling-3-pro/image-to-video', input, { webhookUrl: 'https://yourapp.com/hooks/sandstorm' })
|
|
63
|
+
const finished = await sandstorm.generations.wait(queued.id)
|
|
83
64
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
-H "Authorization: Bearer $SANDSTORM_API_KEY" -H 'Content-Type: application/json' \
|
|
87
|
-
-d '{"slug":"summer-drop","confirm":true}'
|
|
65
|
+
await sandstorm.generations.get(queued.id)
|
|
66
|
+
await sandstorm.generations.cancel(queued.id)
|
|
88
67
|
```
|
|
89
68
|
|
|
90
|
-
|
|
69
|
+
A generation is `queued`, then `running`, then `succeeded`, `failed` or `canceled`; `credits` is what it was charged once it finished, and a failed one is free. Cancelling a queued generation costs nothing; one the model has already started stops where the model allows it, and otherwise finishes and is charged.
|
|
70
|
+
|
|
71
|
+
`create` sends an `Idempotency-Key` with every call and keeps it across its retries, so a retry never makes a second generation. Pass your own to make a call safe across process restarts:
|
|
91
72
|
|
|
92
73
|
```ts
|
|
93
|
-
|
|
74
|
+
await sandstorm.generations.create('nano-banana-pro', input, { idempotencyKey: 'campaign-42-hero' })
|
|
94
75
|
```
|
|
95
76
|
|
|
96
|
-
|
|
97
|
-
curl https://agent.sandstormapp.com/v1/tools -H "Authorization: Bearer $SANDSTORM_API_KEY"
|
|
98
|
-
```
|
|
77
|
+
## Lists
|
|
99
78
|
|
|
100
|
-
|
|
79
|
+
Every list answers one page when awaited and walks every page when iterated:
|
|
101
80
|
|
|
102
81
|
```ts
|
|
103
|
-
const
|
|
104
|
-
```
|
|
82
|
+
const page = await sandstorm.generations.list({ status: 'succeeded', limit: 50 })
|
|
105
83
|
|
|
106
|
-
|
|
107
|
-
curl https://agent.sandstormapp.com/v1/tasks/$TASK_ID -H "Authorization: Bearer $SANDSTORM_API_KEY"
|
|
84
|
+
for await (const asset of sandstorm.assets.list({ type: 'image' })) console.log(asset.id, asset.url)
|
|
108
85
|
```
|
|
109
86
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
`tasks.wait` polls that route every two seconds until the status leaves `running`, and resolves to the task with its result or error:
|
|
87
|
+
## Everything else
|
|
113
88
|
|
|
114
89
|
```ts
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
```
|
|
90
|
+
await sandstorm.models.list({ type: 'video' })
|
|
91
|
+
await sandstorm.models.get('nano-banana-pro/edit')
|
|
118
92
|
|
|
119
|
-
|
|
93
|
+
await sandstorm.brand.get()
|
|
94
|
+
await sandstorm.assets.import('https://yourcdn.com/hero.png', { name: 'Hero shot' })
|
|
95
|
+
await sandstorm.assets.get('asset_9c1e77aa')
|
|
96
|
+
await sandstorm.offers.list({ query: 'cold brew' })
|
|
97
|
+
await sandstorm.offers.get('offer_0f8e2b6a4c1d4e7f9a3b5c7d9e1f2a4b')
|
|
98
|
+
await sandstorm.characters.list({ kind: 'subject' })
|
|
99
|
+
await sandstorm.voices.list({ use_case: 'advertisement', limit: 5 })
|
|
120
100
|
|
|
121
|
-
|
|
122
|
-
|
|
101
|
+
const [advertiser] = (await sandstorm.advertisers.list({ query: 'Liquid Death' })).data
|
|
102
|
+
await sandstorm.ads.list({ advertiser: advertiser!.id, status: 'active' })
|
|
103
|
+
await sandstorm.ads.get('ad_5e1c9a3b')
|
|
123
104
|
```
|
|
124
105
|
|
|
125
|
-
|
|
126
|
-
curl https://agent.sandstormapp.com/v1/tasks -H "Authorization: Bearer $SANDSTORM_API_KEY"
|
|
127
|
-
```
|
|
106
|
+
## Webhooks
|
|
128
107
|
|
|
129
|
-
|
|
108
|
+
A generation made with `webhookUrl` is POSTed to it once it finishes, signed in `Sandstorm-Signature`. Verify the raw body before you trust it:
|
|
130
109
|
|
|
131
110
|
```ts
|
|
132
|
-
|
|
133
|
-
```
|
|
111
|
+
import { verifyWebhook } from 'ads.dev'
|
|
134
112
|
|
|
135
|
-
|
|
136
|
-
|
|
113
|
+
const secret = await sandstorm.webhooks.secret()
|
|
114
|
+
|
|
115
|
+
const event = await verifyWebhook({ secret, body: await request.text(), signature: request.headers.get('sandstorm-signature') })
|
|
116
|
+
if (event.type === 'generation.succeeded') console.log(event.data.output)
|
|
137
117
|
```
|
|
138
118
|
|
|
139
|
-
|
|
119
|
+
It refuses a body that was changed, a signature from another secret and a delivery older than five minutes. An event's `id` is the same on every retry of it, so a handler can skip one it has seen.
|
|
120
|
+
|
|
121
|
+
## Errors
|
|
140
122
|
|
|
141
|
-
A
|
|
123
|
+
A refusal throws `SandstormError` with the HTTP `status`, its `type` and `code`, the `param` at fault and the `requestId` to quote to support. Requests Sandstorm could not take (408, 429, 500, 502, 503, 504) and network failures are retried twice with backoff, after the `Retry-After` the API asks for.
|
|
142
124
|
|
|
143
125
|
```ts
|
|
144
|
-
import { SandstormError } from '
|
|
126
|
+
import { SandstormError } from 'ads.dev'
|
|
145
127
|
|
|
146
128
|
try {
|
|
147
|
-
await sandstorm.
|
|
129
|
+
await sandstorm.generations.create('nano-banana-pro', { prompt: 'A mug on a bench' })
|
|
148
130
|
} catch (error) {
|
|
149
|
-
if (error instanceof SandstormError && error.code === '
|
|
131
|
+
if (error instanceof SandstormError && error.code === 'insufficient_credits') console.log('Add credits in Sandstorm')
|
|
150
132
|
}
|
|
151
133
|
```
|
|
152
134
|
|
|
153
|
-
| status | code | when |
|
|
154
|
-
| --- | --- | --- |
|
|
155
|
-
| 400 | `bad_request` | the query or body does not match the tool's schema; the message names the mismatch |
|
|
156
|
-
| 401 | `unauthorized` | the bearer is not a live key |
|
|
157
|
-
| 402 | `billing` | the organization cannot run Sandstorm right now |
|
|
158
|
-
| 403 | `forbidden` | the tool asks first and the body did not carry `confirm: true`, or the brand named is not one of the organization's |
|
|
159
|
-
| 404 | `tool_not_found`, `task_not_found` | no such tool for this brand, or no such task |
|
|
160
|
-
| 405 | `method_not_allowed` | a read was posted, or a task tool was read; the message names the method that works |
|
|
161
|
-
| 409 | `task_not_running` | the task to stop has already ended |
|
|
162
|
-
| 422 | `tool_failed` | a read the tool refused, with the tool's reason |
|
|
163
|
-
| 429 | `rate_limited` | more than 300 requests in a minute from this key |
|
|
164
|
-
|
|
165
|
-
An answer that is not the API's, such as one from the edge, throws with its `status`, no `code`, and the text of the answer.
|
|
166
|
-
|
|
167
|
-
## The generated client
|
|
168
|
-
|
|
169
|
-
`src/openapi.ts` and `openapi.json` are generated from the API's `GET /v1/openapi.json`, which the API produces from its live tool catalogue, and both are committed, so the package builds without an API. To regenerate:
|
|
170
|
-
|
|
171
|
-
```bash
|
|
172
|
-
yarn generate https://agent.sandstormapp.com/v1/openapi.json # from a running API, replacing openapi.json
|
|
173
|
-
yarn generate path/to/openapi.json # from a document on disk
|
|
174
|
-
yarn generate # from the committed openapi.json
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
`yarn test` fails when the committed `src/openapi.ts` is not what the committed document generates, and a document regenerated from the API shows every catalogue change as a diff of `openapi.json`. `agent/README.md` says how to run the API locally; its document is at `http://localhost:8787/v1/openapi.json`.
|
|
178
|
-
|
|
179
135
|
## Developing
|
|
180
136
|
|
|
181
|
-
|
|
182
|
-
yarn install
|
|
183
|
-
yarn typecheck # src, test and scripts
|
|
184
|
-
yarn test # the client against a stubbed fetch, and the stale-output check
|
|
185
|
-
yarn build # dist/, which is what the package ships
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
Node 22.18 or newer runs `scripts/generate.ts` as it is.
|
|
137
|
+
`openapi.json` is the API's own document, held to what the API serves by the agent project's tests; `yarn generate` turns it into `src/openapi.ts`, and `yarn ci:test` fails when the two disagree. `yarn release` publishes the build as `ads.dev`, `adsdotdev`, `sandstormapp` and `@sandstormapp/sdk`.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,52 +1,139 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export type
|
|
4
|
-
export type
|
|
5
|
-
export type
|
|
6
|
-
export type
|
|
7
|
-
|
|
1
|
+
import type { components, operations } from './openapi.ts';
|
|
2
|
+
type Schemas = components['schemas'];
|
|
3
|
+
export type Generation = Schemas['Generation'];
|
|
4
|
+
export type GenerationEvent = Schemas['GenerationEvent'];
|
|
5
|
+
export type Model = Schemas['Model'];
|
|
6
|
+
export type Asset = Schemas['Asset'];
|
|
7
|
+
export type LibraryAsset = Schemas['LibraryAsset'];
|
|
8
|
+
export type Brand = Schemas['Brand'];
|
|
9
|
+
export type OfferSummary = Schemas['OfferSummary'];
|
|
10
|
+
export type Offer = Schemas['Offer'];
|
|
11
|
+
export type Character = Schemas['Character'];
|
|
12
|
+
export type Voice = Schemas['Voice'];
|
|
13
|
+
export type Advertiser = Schemas['Advertiser'];
|
|
14
|
+
export type AdSummary = Schemas['AdSummary'];
|
|
15
|
+
export type Ad = Schemas['Ad'];
|
|
16
|
+
type CreateGeneration = Schemas['CreateGeneration'];
|
|
17
|
+
type Refusal = Schemas['Error']['error'];
|
|
18
|
+
export type ModelId = CreateGeneration['model'];
|
|
19
|
+
export type ModelInput<Id extends ModelId> = Extract<CreateGeneration, {
|
|
20
|
+
model: Id;
|
|
21
|
+
}>['input'];
|
|
22
|
+
type Query<Operation extends keyof operations> = NonNullable<operations[Operation]['parameters']['query']>;
|
|
23
|
+
type Flag<Value> = [Value] extends ['true' | 'false' | undefined] ? boolean : Value;
|
|
24
|
+
type Params<Operation extends keyof operations> = {
|
|
25
|
+
readonly [Name in Exclude<keyof Query<Operation>, 'cursor'>]?: Flag<Query<Operation>[Name]>;
|
|
8
26
|
};
|
|
9
|
-
export type
|
|
10
|
-
type
|
|
11
|
-
type
|
|
12
|
-
type
|
|
13
|
-
export type
|
|
14
|
-
export type
|
|
15
|
-
export type
|
|
16
|
-
|
|
17
|
-
export type Stopped = paths['/v1/tasks/{taskId}/stop']['post']['responses'][202]['content']['application/json'];
|
|
18
|
-
export interface Wait {
|
|
19
|
-
readonly wait: number;
|
|
20
|
-
}
|
|
21
|
-
export interface ToolCall<Name extends ToolName> {
|
|
22
|
-
(input: ToolInput<Name>): Promise<Started>;
|
|
23
|
-
(input: ToolInput<Name>, options: Wait): Promise<Task | Started>;
|
|
24
|
-
}
|
|
25
|
-
export type ToolRead<Name extends ToolName> = undefined extends Query<Name> ? (query?: ToolInput<Name>) => Promise<ReadResult<Name>> : (query: ToolInput<Name>) => Promise<ReadResult<Name>>;
|
|
26
|
-
export type Tools = {
|
|
27
|
-
readonly [Name in ToolName]: Method<Name> extends 'get' ? ToolRead<Name> : ToolCall<Name>;
|
|
27
|
+
export type GenerationParams = Params<'listGenerations'>;
|
|
28
|
+
export type ModelParams = Params<'listModels'>;
|
|
29
|
+
export type AssetParams = Params<'listAssets'>;
|
|
30
|
+
export type OfferParams = Params<'listOffers'>;
|
|
31
|
+
export type CharacterParams = Params<'listCharacters'>;
|
|
32
|
+
export type VoiceParams = Params<'listVoices'>;
|
|
33
|
+
export type AdvertiserParams = Params<'listAdvertisers'> & {
|
|
34
|
+
readonly query: string;
|
|
28
35
|
};
|
|
29
|
-
export
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
export type AdParams = Params<'listAds'>;
|
|
37
|
+
export interface List<Item> {
|
|
38
|
+
readonly object: 'list';
|
|
39
|
+
readonly data: Item[];
|
|
40
|
+
readonly has_more: boolean;
|
|
41
|
+
readonly next_cursor: string | null;
|
|
34
42
|
}
|
|
35
43
|
export interface Options {
|
|
36
|
-
readonly apiKey
|
|
37
|
-
readonly brand?: string;
|
|
44
|
+
readonly apiKey?: string;
|
|
38
45
|
readonly baseUrl?: string;
|
|
46
|
+
readonly brand?: string;
|
|
47
|
+
readonly maxRetries?: number;
|
|
48
|
+
readonly timeoutMs?: number;
|
|
49
|
+
readonly fetch?: typeof fetch;
|
|
50
|
+
}
|
|
51
|
+
export interface CreateOptions {
|
|
52
|
+
readonly webhookUrl?: string;
|
|
53
|
+
readonly wait?: number;
|
|
54
|
+
readonly idempotencyKey?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface WaitOptions {
|
|
57
|
+
readonly timeoutMs?: number;
|
|
39
58
|
}
|
|
40
59
|
export declare class SandstormError extends Error {
|
|
41
60
|
readonly name = "SandstormError";
|
|
42
61
|
readonly status: number;
|
|
43
|
-
readonly
|
|
44
|
-
|
|
62
|
+
readonly type: Refusal['type'];
|
|
63
|
+
readonly code: string;
|
|
64
|
+
readonly param: string | undefined;
|
|
65
|
+
readonly requestId: string | undefined;
|
|
66
|
+
constructor(status: number, refusal: Omit<Refusal, 'request_id'> & {
|
|
67
|
+
readonly request_id?: string;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
export declare class GenerationFailed extends Error {
|
|
71
|
+
readonly name = "GenerationFailed";
|
|
72
|
+
readonly generation: Generation;
|
|
73
|
+
constructor(generation: Generation);
|
|
74
|
+
}
|
|
75
|
+
export declare const isFinished: (generation: Generation) => boolean;
|
|
76
|
+
export declare class Page<Item> implements PromiseLike<List<Item>>, AsyncIterable<Item> {
|
|
77
|
+
#private;
|
|
78
|
+
constructor(read: (cursor: string | undefined) => Promise<List<Item>>);
|
|
79
|
+
then<Fulfilled = List<Item>, Rejected = never>(fulfilled?: ((list: List<Item>) => Fulfilled | PromiseLike<Fulfilled>) | null, rejected?: ((reason: unknown) => Rejected | PromiseLike<Rejected>) | null): Promise<Fulfilled | Rejected>;
|
|
80
|
+
[Symbol.asyncIterator](): AsyncIterator<Item>;
|
|
45
81
|
}
|
|
46
82
|
export declare class Sandstorm {
|
|
47
83
|
#private;
|
|
48
|
-
|
|
49
|
-
readonly
|
|
50
|
-
|
|
51
|
-
|
|
84
|
+
constructor({ apiKey, baseUrl, brand, maxRetries, timeoutMs, fetch: fetcher, }?: Options);
|
|
85
|
+
readonly generations: {
|
|
86
|
+
create: <Id extends ModelId>(model: Id, input: ModelInput<Id>, { webhookUrl, wait, idempotencyKey }?: CreateOptions) => Promise<Generation>;
|
|
87
|
+
get: (id: string, { wait }?: {
|
|
88
|
+
readonly wait?: number;
|
|
89
|
+
}) => Promise<Generation>;
|
|
90
|
+
wait: (id: string, { timeoutMs }?: WaitOptions) => Promise<Generation>;
|
|
91
|
+
run: <Id extends ModelId>(model: Id, input: ModelInput<Id>, { timeoutMs, ...options }?: Omit<CreateOptions, "wait"> & WaitOptions) => Promise<Generation>;
|
|
92
|
+
cancel: (id: string) => Promise<Generation>;
|
|
93
|
+
list: (params?: GenerationParams) => Page<Generation>;
|
|
94
|
+
};
|
|
95
|
+
readonly models: {
|
|
96
|
+
list: (params?: ModelParams) => Page<Model>;
|
|
97
|
+
get: (id: ModelId) => Promise<Model>;
|
|
98
|
+
};
|
|
99
|
+
readonly assets: {
|
|
100
|
+
list: (params?: AssetParams) => Page<LibraryAsset>;
|
|
101
|
+
get: (id: string) => Promise<Asset>;
|
|
102
|
+
import: (url: string, { name, idempotencyKey }?: {
|
|
103
|
+
readonly name?: string;
|
|
104
|
+
readonly idempotencyKey?: string;
|
|
105
|
+
}) => Promise<Asset>;
|
|
106
|
+
};
|
|
107
|
+
readonly brand: {
|
|
108
|
+
get: () => Promise<Brand>;
|
|
109
|
+
};
|
|
110
|
+
readonly offers: {
|
|
111
|
+
list: (params?: OfferParams) => Page<OfferSummary>;
|
|
112
|
+
get: (id: string) => Promise<Offer>;
|
|
113
|
+
};
|
|
114
|
+
readonly characters: {
|
|
115
|
+
list: (params?: CharacterParams) => Page<Character>;
|
|
116
|
+
};
|
|
117
|
+
readonly voices: {
|
|
118
|
+
list: (params?: VoiceParams) => Page<Voice>;
|
|
119
|
+
};
|
|
120
|
+
readonly advertisers: {
|
|
121
|
+
list: (params: AdvertiserParams) => Page<Advertiser>;
|
|
122
|
+
};
|
|
123
|
+
readonly ads: {
|
|
124
|
+
list: (params?: AdParams) => Page<AdSummary>;
|
|
125
|
+
get: (id: string) => Promise<Ad>;
|
|
126
|
+
};
|
|
127
|
+
readonly webhooks: {
|
|
128
|
+
secret: () => Promise<string>;
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export interface Delivery {
|
|
132
|
+
readonly secret: string;
|
|
133
|
+
readonly body: string;
|
|
134
|
+
readonly signature: string | null;
|
|
135
|
+
readonly toleranceSeconds?: number;
|
|
136
|
+
readonly now?: number;
|
|
52
137
|
}
|
|
138
|
+
export declare function verifyWebhook({ secret, body, signature, toleranceSeconds, now }: Delivery): Promise<GenerationEvent>;
|
|
139
|
+
export {};
|