SlateCore API

Read-only REST API for your slate, team, awards, calendar, and finances. Built so your public website (or your coproducers' websites) can read live data from SlateCore — no need to duplicate everything into a separate CMS. We also send outbound webhooks so your site can invalidate the moment something changes here.

Base URL

https://slatecore.app/api/v1

Generate your API key from Settings → API & Webhooks inside the app. Available on Studio and Label tiers.

Authentication

Every request requires the X-API-Key header with your key. Keys are hashed with SHA-256 at rest — the cleartext is shown once on creation, so store it safely (secrets manager / env var). If you lose it, revoke and create a new one.

bash
curl -H "X-API-Key: sk_live_..." \
  https://slatecore.app/api/v1/ping

Each key carries a set of scopes (projects:read, team:read, etc.). An endpoint that requires a scope your key doesn't have returns 403 insufficient_scope.

Rate limits

Per-minute and per-day limits configurable per key (defaults: 60/min, 10,000/day). When you exceed, the endpoint returns 429 rate_limit_exceeded with a Retry-After header. Responses are edge-cached with s-maxage=30, stale-while-revalidate=60 — lean on the cache to avoid churning a request per page view.

Errors

All errors share the shape { error, message }:

400bad_requestInvalid query (e.g. limit > 100).
401invalid_api_keyMissing X-API-Key or key revoked.
403insufficient_scopeThe key doesn't have the scope this endpoint requires.
404not_foundResource doesn't exist or isn't accessible for your tenant.
429rate_limit_exceededYou exceeded the per-minute or per-day limit.
500internal_errorOn us. Retry with exponential backoff.

Endpoints

Visibility: private by default

This API only returns projects you've marked public. By default a project is private and does not appear here or on the websites that consume the API. Choose what to expose in Settings → API & Webhooks → Public visibility: your projects are grouped by slate (confirmed slate, in consideration, etc.) with a per-project switch and a button to publish a whole group at once. The control lives in the API settings —not on the project— on purpose: what goes public is decided by whoever manages the API (the manageApiKeys permission), not anyone with project access. If you coproduce, each company publishes the shared project to its own API independently. The filter applies to /projects, /projects/:id, their awards, and each project's /events, /milestones and /finanzas.

Recommended: publish your confirmed slate and keep anything still in consideration or passed private. Review this list before sharing your API key or wiring up your site.

GET/pingno scope required

Health check. Returns 200 for any active key.

Request

bash
curl -H "X-API-Key: $SLATE_API_KEY" \
  https://slatecore.app/api/v1/ping

Response

json
{ "ok": true, "tenant_id": "..." }
GET/brandingno scope required

Returns the caller tenant's public branding (name, logos, color).

Request

bash
curl -H "X-API-Key: $SLATE_API_KEY" \
  https://slatecore.app/api/v1/branding

Response

json
{
  "data": {
    "name": "Mi Productora",
    "logo_url": "https://...",
    "favicon_url": "https://...",
    "apple_touch_icon_url": "https://...",
    "primary_color": "#2563eb"
  }
}
GET/projectsprojects:read

List of accessible projects (own + collab) you've published to the public API. Paginated. Only published projects appear — manage which in Settings → API & Webhooks → Public visibility.

Query params

pageintPage number, defaults to 1.
limitintPage size 1–100, defaults to 20.

Request

bash
curl -H "X-API-Key: $SLATE_API_KEY" \
  "https://slatecore.app/api/v1/projects?page=1&limit=20"

Response

json
{
  "data": [
    {
      "id": "uuid",
      "nombre": "La Balada del Chupacabras",
      "logline": "...",
      "estatus": "Producción",
      "tipo_de_proyecto": "Largometraje",
      "genero": ["Coming of Age", "Comedia"],
      "poster_url": "https://...",
      "productoras_info": [
        { "nombre": "TM Cine", "logoUrl": "...", "website": "..." }
      ],
      "part_of_slate": "Yes",
      "trailer_url": "https://www.youtube.com/watch?v=…",
      "collaboration_role": null
    }
  ],
  "meta": { "total": 14, "page": 1, "limit": 20 }
}
GET/projects/:idprojects:detail

Full project detail including lead/authors/crew/comps. Returns 404 unless the project is published (public visibility on).

Request

bash
curl -H "X-API-Key: $SLATE_API_KEY" \
  https://slatecore.app/api/v1/projects/<uuid>

Response

json
{
  "data": {
    "id": "uuid",
    "nombre": "...",
    "logline": "...",
    "sinopsis": "...",
    "autores": [{ "nombre": "...", "apellido": "..." }],
    "crew": [{ "rol": "Dirección", "nombre": "..." }],
    "comparables": [{ "titulo": "...", "año": 2023 }],
    "part_of_slate": "Yes",
    "trailer_url": "https://vimeo.com/123456789/abcdef"
  }
}
GET/projects/:id/awardsawards:read

Festival selections / awards for that project.

Request

bash
curl -H "X-API-Key: $SLATE_API_KEY" \
  https://slatecore.app/api/v1/projects/<uuid>/awards

Response

json
{
  "data": [
    {
      "festival": "Sundance",
      "año": 2025,
      "estatus": "Selección oficial",
      "premio": null
    }
  ]
}
GET/teamteam:read

Public team directory of the caller's tenant.

Request

bash
curl -H "X-API-Key: $SLATE_API_KEY" \
  https://slatecore.app/api/v1/team

Response

json
{
  "data": [
    {
      "id": "uuid",
      "nombre": "Sebastián Sariñana",
      "rol": "Dirección",
      "foto_url": "https://...",
      "imdb_url": "https://www.imdb.com/name/..."
    }
  ]
}
GET/eventsevents:read

Calendar events visible to the caller (own + collab projects).

Request

bash
curl -H "X-API-Key: $SLATE_API_KEY" \
  https://slatecore.app/api/v1/events

Response

json
{
  "data": [
    {
      "id": "uuid",
      "titulo": "Pitch a Netflix",
      "fecha": "2026-06-12T15:00:00Z",
      "proyecto_id": "uuid"
    }
  ]
}
GET/milestonesmilestones:read

Milestones visible to the caller (own + collab projects).

Request

bash
curl -H "X-API-Key: $SLATE_API_KEY" \
  https://slatecore.app/api/v1/milestones

Response

json
{
  "data": [
    {
      "id": "uuid",
      "titulo": "Primer corte",
      "fecha_objetivo": "2026-09-01",
      "completado": false,
      "proyecto_id": "uuid"
    }
  ]
}
GET/finanzasfinanzas:read

Per-project P&L summaries, grouped by currency. Aggregates only — never row-level data. Sensitive scope: opt-in per key.

Request

bash
curl -H "X-API-Key: $SLATE_API_KEY" \
  https://slatecore.app/api/v1/finanzas

Response

json
{
  "data": [
    {
      "proyecto_id": "uuid",
      "totals": {
        "MXN": { "ingresos": 12000000, "gastos": 8500000 },
        "USD": { "ingresos": 50000, "gastos": 12000 }
      }
    }
  ]
}

Webhooks

Receive a POST to your URL whenever a piece of data changes in SlateCore — useful for revalidating Next.js, invalidating Webflow caches, or kicking off deploys. Register a webhook from Settings → API & Webhooks in the app: pick the events you care about and we generate an HMAC secret so you can verify the origin. We retry up to 3 times with backoff (1 min, 5 min, 15 min) if your endpoint returns 5xx or times out.

Events

project.created · project.updated · project.deleted

INSERT/UPDATE/DELETE on projects, plus any change to a row in project_collaborators (alta/baja/slate change). Fans out to every active collab tenant.

award.created · award.updated · award.deleted

INSERT/UPDATE/DELETE on festivales. Fans out to collabs.

team.created · team.updated · team.deleted

INSERT/UPDATE/DELETE on crew_cast. Fans out to collabs.

milestone.created · milestone.updated · milestone.deleted

INSERT/UPDATE/DELETE on milestones. Fans out to collabs.

event.created · event.updated · event.deleted

INSERT/UPDATE/DELETE on eventos. Fans out when the event is project-scoped; tenant-only events stay owner-only.

Payload

Every event arrives in the same shape. tenant_id always points at the receiving tenant — for coproductions you receive one event per collaborating tenant. owner_tenant_id identifies the resource owner when an event arrives via fan-out.

json
{
  "event": "project.updated",
  "id": "uuid-of-resource",
  "tenant_id": "uuid-of-receiver",
  "proyecto_id": "uuid-or-null",
  "owner_tenant_id": "uuid-or-null",
  "reason": "collaboration_changed",
  "timestamp": "2026-05-05T16:30:00Z"
}

Headers we send: X-Slate-Event, X-Slate-Signature, X-Slate-Delivery (unique id — handy for deduping on your side).

Verify the HMAC signature

Each delivery includes X-Slate-Signature: sha256=<hmac>. Compute the HMAC-SHA256 of the raw body (don't re-stringify the JSON — use the bytes you received) with your secret and compare before trusting it.

javascript
const crypto = require('crypto')

app.post('/slate-webhook', (req, res) => {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', process.env.SLATE_WEBHOOK_SECRET)
    .update(req.rawBody)         // raw bytes, not JSON.stringify
    .digest('hex')

  if (req.header('x-slate-signature') !== expected) {
    return res.status(401).end()
  }

  // Respond 2xx fast — process async if slow.
  res.status(200).end()
})

Cross-tenant fan-out

When you edit a shared project, every collaborating tenant's webhooks also fire with their own tenant_id and owner_tenant_id pointing at the owner. Each consumer refetches with its own API key and gets its own view (including its part_of_slate, which is per-tenant).

When a collaborator changes something that only affects them (their own part_of_slate on a shared project), project.updated fires with reason: "collaboration_changed" only to that tenant — the owner doesn't get spammed.

Plan access

The API and webhooks are available on Studio and Label. Indie and School plans don't include API access. Compare plans on slatecore.app. Support: hello@slatecore.app.