Install
#npm install @playcode/sdk
import { Playcode } from '@playcode/sdk'
const pc = new Playcode() // reads PLAYCODE_SECRET_KEY when a call needs it
Creating the client never throws and never calls the network: a missing key fails on the first call that needs it. Inside a Cloud app, the key is already in the environment.
Configuration
#| Option | Environment variable | What it is |
|---|---|---|
apiKey |
PLAYCODE_SECRET_KEY |
The app's secret key (pcsk_...), for email and media. Server-side only |
apiToken |
PLAYCODE_TOKEN |
An access token (pc_live_...), for pc.api |
emailUrl |
PLAYCODE_EMAIL_URL |
Playcode Email's address. Set it only for a test environment |
mediaUrl |
PLAYCODE_MEDIA_URL |
Playcode Media's address. Set it only for a test environment |
apiOrigin |
PLAYCODE_API_ORIGIN |
The API's address; https://playcode.io by default |
timeoutMs |
How long one email or video request may take; 10 seconds by default |
The environment is read at call time, so values loaded after the client was created still count.
Email: pc.email.send()
#const { status, messageId } = await pc.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. 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: see Send email from your app. New values can appear, so treat an unknown one as not delivered yet. The SDK never retries a send by itself.
import { sendEmail } from '@playcode/sdk/email' gives the same call without the client.
Video and images: pc.media
#const job = await pc.media.video({ prompt: 'A paper boat on a lake at dawn', quality: 'draft', idempotencyKey: id })
const { url } = await job.wait()
pc.media.video() starts a render and answers 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 standard, high or draft. 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 for video: ask the agent to switch on media for the app. pc.media.image() is in the SDK too, but your app's key cannot use it yet: see Limits.
Management API: pc.api
#const pc = new Playcode({ apiToken: process.env.PLAYCODE_TOKEN })
const domain = await pc.api.domainGet({ domain: 'example.com' })
if (domain.uid) await pc.api.domainUpdate({ uid: domain.uid, input: { autoRenew: true } })
pc.api has one typed method for each operation of the API at the SDK's release. Its credential is an access token, never the app's secret key. Each write carries an Idempotency-Key, and the same key rides every retry: the client retries a network error, a 429 or a 5xx 2 times, so a retry never doubles a write. Pass your own key as the second argument: { idempotencyKey }. See The API and Access tokens and permissions.
Webhooks: verifyWebhook()
#import { verifyWebhook } from '@playcode/sdk'
const { id, event } = verifyWebhook({
signature: req.headers['playcode-signature'],
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. It throws PlaycodeWebhookError for a bad signature, or a delivery older than 300 seconds (toleranceSeconds changes that). See Webhooks.
Errors
#| Error | When | What it carries |
|---|---|---|
PlaycodeApiError |
Playcode answered with an error | status, code, message (Playcode's own words), requestId |
PlaycodeConnectionError |
Playcode never answered: network, TLS or timeout | message, cause |
PlaycodeConfigError |
No key or token for the call | message, naming the missing variable |
PlaycodeWebhookError |
A delivery failed verification | message |
Limits
#- The secret key stays on the server. A key in browser code is a leaked key: anyone who has it can send email and use AI as your app.
- The SDK does not call AI models. Your app calls them with the model maker's own SDK through Playcode: see Add AI to your app.
- Image generation from your app's own key is not available yet: the key cannot carry the image permission today.
- An operation added to the API after the SDK's release needs a newer SDK.