Authentication & API keys

Every request carries an API key in the Authorization header. A key belongs to one SpaceKru account, has read, read & write or AI conversation access, and works only while the account is on a paid plan.

The SpaceKru API (v1.1) is a REST/JSON API available on every paid SpaceKru plan. It syncs leads both ways (upsert by external_id), adds leads to campaigns, creates and moves deals and asks AI Employees to follow up, manages products, quotes, orders, payments and bookings, lets your platform chat with your Customer Service AI Employee, and sends signed webhooks for 16 events that say who caused each change. Base URL: https://app.spacekru.com/api/public/v1. Authentication: Bearer API key (sk_live_…). Documentation: https://www.spacekru.com/developers (Spanish: https://www.spacekru.com/es/developers). OpenAPI 3.1: https://app.spacekru.com/api/public/v1/openapi.json.

Leer en español

API keys

Send the key as a Bearer token on every request:

Authorization: Bearer sk_live_…
  • Format: sk_live_ followed by 43 characters. Anything else answers 401 without even reaching our database.
  • Every key is live: there is no test mode. Tag test leads (for example docs-test) so you can find and remove them.
  • The key is shown once, when it is created. We store only a keyed hash of it, so nobody — including SpaceKru — can show it to you again.
  • Up to 5 active keys per account. Name each key after the tool that uses it ("Zapier", "Website form", "ERP sync") so you can revoke one without touching the rest.

Who can create keys

Only the account owner, in Integrations → API & Webhooks (key names up to 100 characters). The same panel shows each key's last use, the request count of the last 30 days, and every webhook subscription.

Scopes

  • Read only (read): every GET except webhooks and conversations.
  • Read & write (read + write): everything that creates or changes data, and every /subscriptions operation.
  • AI conversations (conversations, optional, only with read & write): the /conversations operations. They spend AI tokens, so the owner grants it explicitly when creating the key.

A key without the scope an operation needs answers 403 INSUFFICIENT_SCOPE.

OperationWhat it doesScopePlan module
GET /pingTest the connectionread—
GET /leadsList leads (newest first)readcrm
POST /leadsCreate a leadwritecrm
GET /leads/{id}Retrieve a leadreadcrm
PATCH /leads/{id}Update a leadwritecrm
POST /leads/{id}/notesAdd a note to a leadwritecrm
GET /dealsList dealsreadcrm
POST /dealsCreate a dealwritecrm
GET /deals/{id}Retrieve a dealreadcrm
PATCH /deals/{id}Update or move a dealwritecrm
GET /quotesList quotesreadsales_os
POST /quotesCreate a quotewritesales_os
GET /quotes/{id}Retrieve a quotereadsales_os
PATCH /quotes/{id}Update a quotewritesales_os
GET /ordersList ordersreadsales_os
POST /ordersCreate an orderwritesales_os
GET /orders/{id}Retrieve an orderreadsales_os
PATCH /orders/{id}Update an orderwritesales_os
GET /subscriptionsList webhook subscriptionswrite—
POST /subscriptionsSubscribe a URL to an event (REST Hook)write—
DELETE /subscriptions/{id}Unsubscribewrite—
PUT /leads/external/{external_id}Create or update a lead by your id (upsert)writecrm
GET /agentsList AI Employeesreadcrm
GET /pipeline-stagesList pipeline stagesreadcrm
GET /campaignsList campaignsreadcrm
GET /campaigns/{id}Retrieve a campaignreadcrm
POST /campaigns/{id}/leadsAdd leads to a campaignwritecrm
POST /deals/{id}/follow-upsAsk the AI Employee to follow upwritecrm
DELETE /deals/{id}/follow-upsCancel pending follow-upswritecrm
GET /productsList productsreadsales_os
POST /productsCreate a productwritesales_os
GET /products/{id}Retrieve a productreadsales_os
PATCH /products/{id}Update a productwritesales_os
PATCH /products/{id}/variants/{variant_id}Update a variant (price, stock)writesales_os
GET /bookingsList bookingsreadscheduler
POST /bookingsCreate a bookingwritescheduler
GET /bookings/{id}Retrieve a bookingreadscheduler
PATCH /bookings/{id}Reschedule or update a bookingwritescheduler
GET /booking-resourcesList bookable resourcesreadscheduler
GET /availabilityFree slots of a dayreadscheduler
GET /conversations/availabilityIs an AI Employee ready to chat?conversations—
POST /conversationsOpen a conversationconversations—
GET /conversations/{id}Retrieve a conversationconversations—
POST /conversations/{id}/messagesSend the customer's messageconversations—
GET /conversations/{id}/messagesList the messages of a conversationconversations—
POST /conversations/{id}/closeClose a conversationconversations—
POST /quotes/{id}/convertConvert a quote into an orderwritesales_os
POST /orders/{id}/paymentsRecord a paymentwritesales_os

Plan modules (403)

Some operations need a module of your plan, the same one the app needs: crm (leads, deals, campaigns), sales_os (products, quotes, orders) and scheduler (bookings). Without it the answer is 403 MODULE_NOT_AVAILABLE. Every paid plan includes the three modules today.

Response language

error.message comes in English or Spanish. Send Accept-Language: es (or en) to choose; without it, the language of the profile of the person who created the key is used. The Content-Language header tells you which one you got. Error codes, field names, event names and details[].issue never change: branch on them, not on the message.

Plan requirements (402)

The API works only while the account is on an active paid plan (the 7-day free trial of a paid plan counts). Otherwise every request answers 402 PLAN_UPGRADE_REQUIRED with one of these messages:

SituationMessage you receive
No paid planThe SpaceKru API is available on paid plans only. Upgrade your plan to connect Zapier, Make or your own system.
Subscription cancelled, unpaid or past dueYour SpaceKru subscription is not active. Update your payment method to restore API access.
The plan does not include the APIYour current SpaceKru plan does not include API access.
Account closedThis SpaceKru account is closed.
  • There is no grace period: a payment that fails pauses the API right away (within about a minute).
  • Keys are not deleted. When the account is back on a paid plan, the same keys and webhooks work again.
  • If we can't verify the plan for a moment, you get 503 ELIGIBILITY_UNAVAILABLE with Retry-After: 10. It fails closed: retry, it is never a free pass.

401 vs 402 vs 403

StatusCodeMeaning
401INVALID_API_KEYNo key, a malformed key, an unknown key or a revoked key. The response carries WWW-Authenticate: Bearer.
402PLAN_UPGRADE_REQUIREDThe key is valid, but the account is not on an active paid plan.
403INSUFFICIENT_SCOPE / MODULE_NOT_AVAILABLEThe key lacks the scope (e.g. a read-only key calling POST /leads), or the plan lacks the module.

Revoke and rotate keys

  • Revoke a key in Integrations → API & Webhooks. It stops working on the very next request — there is no cache.
  • Revoking a key also deactivates the webhook subscriptions it created (disabled_reason: "key_revoked"). Subscriptions created by other keys are not affected.

To rotate a key without downtime:

  1. Create a new key with the same access.
  2. Deploy it to your integration (environment variable, Zapier/Make/n8n connection).
  3. Check in the panel that the new key shows a recent "Last used".
  4. Revoke the old key. If the old key created webhooks, subscribe them again with the new key (and if they used exclude_own_changes, they now skip the new key's changes).

Security & best practices

  • Server-to-server only. The API sends no CORS headers, so browsers block calls from web pages — on purpose. A key in front-end code, a mobile app or a public repository can be stolen; keep it on a server or inside your automation tool.
  • Store keys as secrets: environment variables, a secrets manager, or the credential store of Zapier, Make or n8n.
  • Least privilege: a Read only key for reporting; AI conversations only for the key of your chat integration.
  • One key per integration, so revoking one never breaks the others.
  • Verify every webhook signature and reject old timestamps — see Verify signatures.
  • Tenant isolation: a key can only ever see its own account. An id from another account answers 404, exactly like an id that does not exist — also inside a body (lead_id, product_id…).
  • Webhook targets are restricted to public https:// hosts on port 443, checked on every delivery; redirects are never followed.

Example: check a key

curl
curl "https://app.spacekru.com/api/public/v1/ping" \
  -H "Authorization: Bearer $SPACEKRU_API_KEY"
Node.js
const res = await fetch('https://app.spacekru.com/api/public/v1/ping', {
  headers: {
    Authorization: `Bearer ${process.env.SPACEKRU_API_KEY}`,
  },
});
const body = await res.json();
if (!res.ok) {
  // Branch on body.error.code; quote body.error.request_id to support.
  throw new Error(`${body.error.code}: ${body.error.message} (request ${body.error.request_id})`);
}
console.log(body);
Python
import os

import requests

r = requests.get(
    "https://app.spacekru.com/api/public/v1/ping",
    headers={
        "Authorization": f"Bearer {os.environ['SPACEKRU_API_KEY']}",
    },
    timeout=30,
)
body = r.json()
if not r.ok:
    # Branch on body["error"]["code"]; quote body["error"]["request_id"] to support.
    raise RuntimeError(f"{body['error']['code']}: {body['error']['message']} (request {body['error']['request_id']})")
print(body)