Recording Studio

Record, upload, or generate a greeting.

Drop-in widget. Load https://webforms.dropcowboy.com/latest/dropcowboy-recording-studio.min.js and pass it a site token your server mints. Do not rebuild the recorder, file upload, or text-to-speech step; the widget already does it.

When to use this vs REST

Use Recording Studio when a user records, uploads, or generates a greeting in your app. Use POST /media/public/media to upload a file you already have from a server.

Do not rebuild

  • A microphone recorder or upload widget.
  • Text-to-speech generation inside the recorder.

Drop-in

  1. On your server, trade your API key for a short-lived site token (the key needs numbers:write):
// Your server. Browser code never sees KEY/SECRET.
app.post('/dropcowboy/token', async function (req, res) {
  const r = await fetch('https://api-v2.dropcowboy.com/phone/public/embed/token', {
    method: 'POST',
    headers: {
      'x-key': process.env.DC_KEY,
      'x-secret': process.env.DC_SECRET,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ site_id: process.env.DC_SITE_ID, scope: ['media'], ttl_seconds: 900 })
  });
  const body = await r.json();
  if (!r.ok) return res.status(r.status).json(body);
  // The API wraps results in data. Hand the browser just the token.
  res.json({ token: body.data.token, expires_at: body.data.expires_at });
});

Or test the mint with cURL:

# On your server: trade your API key (needs numbers:write) for a site token. 1 hour max.
# site_id is one UUID per app; generate your own in place of the example.
curl -s -X POST https://api-v2.dropcowboy.com/phone/public/embed/token \
  -H "x-key: $KEY" -H "x-secret: $SECRET" \
  -H "Content-Type: application/json" \
  -d '{"site_id":"00000000-0000-4000-8000-000000000000","scope":["media"],"ttl_seconds":900}'
  1. Load the script, init with the token, and call a method:
<script src="https://webforms.dropcowboy.com/latest/dropcowboy-recording-studio.min.js"></script>
<script>
(async function () {
  const minted = await fetch('/dropcowboy/token', { method: 'POST' }).then(function (r) { return r.json(); });
  await DropCowboy.studio.init({ token: minted.token });
  DropCowboy.studio.setTheme({ theme: 'LIGHT', primaryColor: '#009efb' });
  document.getElementById('record-greeting').addEventListener('click', function () {
    DropCowboy.studio.open();
  });
})();
</script>

Pin a version with SRI

/latest/ changes whenever we ship. To pin a release, load the same file from /vX.Y.Z/ and add its Subresource Integrity hash. Each release lists its hashes at https://webforms.dropcowboy.com/vX.Y.Z/building-blocks-manifest.json: take the integrity of the entry whose file is dropcowboy-recording-studio.js. It covers dropcowboy-recording-studio.min.js as well, because both names serve the same bytes.

<script src="https://webforms.dropcowboy.com/vX.Y.Z/dropcowboy-recording-studio.min.js"
        integrity="sha384-INTEGRITY_FROM_MANIFEST"
        crossorigin="anonymous"></script>

Do not put integrity on a /latest/ URL. The file changes under it and the browser will refuse to run it.

From your server

Already have the audio file? Skip the widget and store it from your server with an API key that has media:write. Pass ext when the file is not a WAV.

Upload a greeting you already have:

curl -X POST https://api-v2.dropcowboy.com/media/public/media \
  -H "x-key: $KEY" -H "x-secret: $SECRET" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://files.example.com/greeting.mp3","ext":".mp3","name":"Greeting"}'

JS API / HTML tag

Method What it does
init({ token }) Site token with media scope.
setTheme({ theme, primaryColor }) LIGHT/DARK plus accent.
open(options) Opens the studio UI.
addErrorListener(fn) -> stop Fires on upload or encode errors.
close() Closes the studio.

Auth and scopes

Site token with the media scope. Your API secret stays on your server.

Site token scope: media. Mint it with POST https://api-v2.dropcowboy.com/phone/public/embed/token using an API key with numbers:write. Tokens last up to one hour.

Limits

  • Site tokens last at most one hour (the default). Mint a fresh one per page load or session; do not cache one across users.
  • To store a file you already have on a server, skip the widget and upload with POST /media/public/media.

Routes are on https://api-v2.dropcowboy.com.

  • POST /media/public/media - upload a recording by URL
  • POST /phone/public/embed/token - mint the site token

Full reference: Embed site tokens, Media API.

Copy the code

The snippets on this page. Your server keeps the API key pair (KEY and SECRET for curl, DC_KEY and DC_SECRET for Node); the browser only sees the short-lived site token.

Load the Recording Studio
<script src="https://webforms.dropcowboy.com/latest/dropcowboy-recording-studio.min.js"></script>
<script>
(async function () {
  const minted = await fetch('/dropcowboy/token', { method: 'POST' }).then(function (r) { return r.json(); });
  await DropCowboy.studio.init({ token: minted.token });
  DropCowboy.studio.setTheme({ theme: 'LIGHT', primaryColor: '#009efb' });
  document.getElementById('record-greeting').addEventListener('click', function () {
    DropCowboy.studio.open();
  });
})();
</script>
Mint a site token (your server)
// Your server. Browser code never sees KEY/SECRET.
app.post('/dropcowboy/token', async function (req, res) {
  const r = await fetch('https://api-v2.dropcowboy.com/phone/public/embed/token', {
    method: 'POST',
    headers: {
      'x-key': process.env.DC_KEY,
      'x-secret': process.env.DC_SECRET,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ site_id: process.env.DC_SITE_ID, scope: ['media'], ttl_seconds: 900 })
  });
  const body = await r.json();
  if (!r.ok) return res.status(r.status).json(body);
  // The API wraps results in data. Hand the browser just the token.
  res.json({ token: body.data.token, expires_at: body.data.expires_at });
});
Mint a site token (curl)
# On your server: trade your API key (needs numbers:write) for a site token. 1 hour max.
# site_id is one UUID per app; generate your own in place of the example.
curl -s -X POST https://api-v2.dropcowboy.com/phone/public/embed/token \
  -H "x-key: $KEY" -H "x-secret: $SECRET" \
  -H "Content-Type: application/json" \
  -d '{"site_id":"00000000-0000-4000-8000-000000000000","scope":["media"],"ttl_seconds":900}'
Load the Recording Studio
<script src="https://webforms.dropcowboy.com/vX.Y.Z/dropcowboy-recording-studio.min.js"
        integrity="sha384-INTEGRITY_FROM_MANIFEST"
        crossorigin="anonymous"></script>
Upload a greeting you already have
curl -X POST https://api-v2.dropcowboy.com/media/public/media \
  -H "x-key: $KEY" -H "x-secret: $SECRET" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://files.example.com/greeting.mp3","ext":".mp3","name":"Greeting"}'