const { status, messageId } = await playcode.email.send({
to: 'anna@example.com',
subject: 'Your invoice',
html: '<p>Thank you!</p>',
replyTo: 'support@example.com',
idempotencyKey: invoice.id,
})
| Field | What it does |
|---|---|
to |
One address, or a list of up to 10. Leave it out to email the project owner's account address |
subject |
The subject line |
html, text |
The body: at least one of them |
from |
The sender. An address at your verified domain is used as written; otherwise the email goes out from the app's playcode.email address, with this name on it |
replyTo |
Where replies go |
headers |
Stored with the email, not sent |
idempotencyKey |
Sending again with the same key returns the first email instead of a second one |
The answer's status is sending, held, captured or withheld: Send email from your app explains each one. A retry with the same idempotencyKey returns the email as it is now, which can also be delivered, bounced or complained. New values can appear, so treat an unknown one as not delivered yet.
Email to your customers is held until your app sends from your own verified domain, and a workspace without a Pro or Max plan delivers none: see Who receives your app's email.
A request waits 10 seconds by default (timeoutMs). The SDK never retries a send by itself: with an idempotencyKey, your own retry is safe; without one, a retry after a timeout can send twice. import { sendEmail } from '@playcode/sdk/email' gives the same call without the client.
Video and images
#const job = await playcode.media.video({
prompt: 'A paper boat on a lake at dawn',
quality: 'draft',
idempotencyKey: id,
})
const { url } = await job.wait()
playcode.media.video() starts a render and returns a job. job.wait() waits until the video is ready, 15 minutes at most by default; job.get() reads its state, and job.cancel() stops it. quality is draft (a fast preview), standard (the default) or high, each with its own price per second. With an idempotencyKey, a retry returns the same job instead of paying twice. The result is an address on Playcode, and each second of video is paid from the workspace's credits. The app's key needs the media service: ask Playcode's agent to switch on media for the app.
playcode.media.image() is in the SDK too, but your app's key cannot use it yet.
The Playcode API
#import { Playcode } from '@playcode/sdk'
const playcode = new Playcode({ apiToken: process.env.PLAYCODE_TOKEN })
const domain = await playcode.api.domainGet({ domain: 'example.com' })
if (domain.uid) {
const input = { autoRenew: true }
await playcode.api.domainUpdate({ uid: domain.uid, input })
}
playcode.api has one typed method for each operation of the Playcode API at the SDK's release: domains, projects with their files, commands and publishes, chats, workspaces, billing, apps and more. Its credential is an access token, never the app's secret key, and what the token may do was decided when it was made: see Access tokens and permissions.
Each write carries an Idempotency-Key, and the same key rides every retry. The client retries a network error, a 429 or a 5xx at most 2 times. The key stays the same, so a retry never doubles a write. Its calls have no default timeout: pass signal in the options to bound one. Pass your own key as the second argument: { idempotencyKey }.
Webhooks
#import { verifyWebhook } from '@playcode/sdk'
const { id, event } = verifyWebhook({
signature: request.headers.get('playcode-signature') ?? undefined,
body: rawBody,
secret: process.env.PLAYCODE_WEBHOOK_SECRET!,
})
Pass the raw request body, exactly as it arrived: a re-encoded body does not match the signature. Playcode tries a delivery up to 8 times, so skip an id you already handled. PLAYCODE_WEBHOOK_SECRET is the endpoint's pcwh_... signing secret, shown once when you add the endpoint. The call is synchronous and needs no Node module. It throws PlaycodeWebhookError for a bad signature, or for a delivery older than 300 seconds (toleranceSeconds changes that). See Webhooks.
Limits
#- Image generation from your app's own key is not available yet.
- An operation added to the Playcode API after the SDK's release needs a newer SDK.
- The tokens, webhooks, secret-key and OAuth-app operations of
playcode.apitake a signed-in person: every access token is refused there.