Sign up a customer
Silky's signup endpoint is public - no auth, no demo, no sales call. You give it an email. It gives you back an account plus a trial API key that is live immediately.
Endpoint
POST /api/v1/accounts/signup
Body: { "email": "founder@acme.com", "source": "claude-agent" }
Response (HTTP 202):
{
"success": true,
"data": {
"account_id": "acc_01HXXX...",
"status": "pending_verification",
"trial_api_key": "sk_trial_abc123...",
"email_verified": false,
"message": "Check your email to verify your address. Your API key is active now - you can start building immediately.",
"enrichment_task_id": "task_01HXXX..."
},
"meta": { "request_id": "req_abc123def456" },
"error": null
}
The trial_api_key is returned once. Store it; you cannot retrieve it later. Generate a new one via POST /api/v1/api-keys if lost.
curl
curl -X POST https://app.silky.so/api/v1/accounts/signup \
-H "Content-Type: application/json" \
-d '{"email": "founder@acme.com", "source": "claude-agent"}'
JavaScript
const res = await fetch('https://app.silky.so/api/v1/accounts/signup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'founder@acme.com', source: 'claude-agent' }),
});
const { data } = await res.json();
const apiKey = data.trial_api_key;
// Store apiKey. All subsequent calls use: Authorization: Bearer <apiKey>
Python
import requests
r = requests.post(
'https://app.silky.so/api/v1/accounts/signup',
json={'email': 'founder@acme.com', 'source': 'claude-agent'},
timeout=30,
)
r.raise_for_status()
api_key = r.json()['data']['trial_api_key']
# Store api_key. Use it as Authorization: Bearer <api_key> on every subsequent call.
What happens next
- A verification email goes to the address. The customer clicks it once to unlock the full plan; the trial key keeps working regardless.
- Silky runs an async enrichment task (
enrichment_task_id) that crawls the domain, fetches branding colours + logo, and sets a sensible timezone. PollGET /api/v1/tasks/{id}if you want to wait for it. - An
account_enrichedwebhook fires when enrichment finishes (about 10-30 seconds). Subscribe viaPOST /api/v1/webhooksif you want push instead of poll.
Duplicate handling
If the email already has an account, the endpoint returns HTTP 202 with the existing account_id and a message telling the caller to check email for the verification link. It does not return a new API key. Build your flow so a duplicate signup is a no-op, not an error.
If another account already claims the same email domain (e.g. someone at acme.com signed up before), the endpoint returns HTTP 409 with error.type = "conflict" and a human-readable reason. Bounce the user to that account's admin or pick a different domain.
Verifying the email programmatically
The verification link in the email points to /auth/verify-email?token=.... For a fully headless onboarding flow, you cannot read the email on behalf of the user. Two options:
- Let the human click the link themselves. The trial key works in the meantime.
- Use the invite flow instead: have an existing admin call
POST /api/v1/accounts/{id}/usersto create a member with a known password. That skips email verification entirely but requires you to already be signed in.
Rate limits
The signup endpoint is IP-rate-limited. Steady state you can create one account per minute per IP. Burst up to 10 in 10 minutes. If you hit 429, wait for the Retry-After header and try again.
Hand this to Claude
Sign up a new Silky account for founder@acme.com, store the trial
API key in an env var called SILKY_API_KEY, and print the account_id.