Clients and projects
Discover existing IDs through the directory, then read the client register. Create/update saves a coherent client/project aggregate without browser draft hydration. Replace synthetic values with your actual business settings.
List customer engagements
Operation: clients.list · GET /client-register
Use the existing register aggregate with nested projects, commercial engagement terms, role rates and source attribution mappings. A client is your customer, separate from your ScopeWorth organization and workspace. GET /directory discovers project and client IDs. Listing returns all aggregates ordered by customer name without pagination; onboarding clients may have zero projects. Detail omits browser drafts. POST accepts a complete form without an autosave; PATCH requires the latest version from GET and stale writes return 409. Existing projects belong to that client, initiatives belong to that project, connections belong to that workspace, and current creator scope still applies. Amounts are integer minor currency units and rate units remain explicit. Organization-pooled limits are atomic and retries consume capacity once. Quota/conflict returns 409, invalid values 400, foreign resources 404. Writes require Idempotency-Key; reuse it only with the same normalized request, use a new key for each intentional edit. No invitation, email, provider request, logo, draft, deletion or archive endpoint is exposed. Mappings can attribute existing local evidence through the existing service.
Required key scope: clients:read. Current creator action: clients.read. Eligible plans: free, starter, growth, scale; legacy contracts: free, entry, growth. stable contract. These badges do not override current role, evidence window, quotas or target ownership.
-
PATCH requires the latest nonnegative version; version zero configures an onboarding client without a profile.
-
Writes require at least one project; omitting existing projects or initiatives does not delete them. All existing IDs must belong to the same client/project and workspace.
-
Commercial and project end dates cannot precede start dates; duplicate mapping pairs and currency/unit constraints use the shared register refinements.
-
Public writes preserve browser drafts; their normal version checks reject stale edits.
Success statuses: 200. The JSON response is the saved/read representation. Synthetic examples below show shape, not customer evidence.
Synthetic response:
View schema or synthetic response
{
"clients": [
{
"clientId": "11111111-1111-4111-8111-111111111111",
"connections": [],
"connectorWarning": true,
"form": {
"commercial": {
"billingFrequency": null,
"billingModel": "time_and_materials",
"blendedCostPerHourCents": null,
"contractedAmountCents": null,
"contractedHours": null,
"contractEnd": null,
"contractStart": "2026-10-01",
"currency": "USD",
"defaultBillingRatePerHourCents": null,
"hourlyBillingRateCents": null,
"includeAiToolingCosts": false,
"includeCloudCosts": false,
"includeContractorCosts": false,
"includeMeetingCosts": false,
"monthlyFeeCents": null,
"revenueSource": null,
"targetMarginPct": null
},
"profile": {
"accountManager": null,
"companyName": "Example customer",
"contactEmail": null,
"contactName": null,
"country": null,
"deliveryLead": null,
"industry": null,
"internalOwner": null,
"logoUrl": null,
"region": null,
"status": "active",
"timeZone": null,
"website": null
},
"projects": [
{
"budgetCents": null,
"description": null,
"endsOn": null,
"id": "22222222-2222-4222-8222-222222222222",
"initiatives": [],
"mappings": [],
"name": "Example delivery",
"objective": null,
"outcomeMetric": null,
"projectType": "Software delivery",
"rates": [],
"risk": "unknown",
"scopeLockDate": "2026-10-01",
"startsOn": "2026-10-01",
"status": "active",
"team": []
}
]
},
"version": 1
}
]
}
Use IDs and versions from your own preceding responses. Replace the synthetic UUIDs, dates and names in these independent examples. Set SCOPEWORTH_API_BASE and SCOPEWORTH_API_KEY only on your server.
cURL
curl --request GET "$SCOPEWORTH_API_BASE/organizations/example-org/workspaces/example-workspace/client-register" \
--header "Authorization: Bearer $SCOPEWORTH_API_KEY"JavaScript fetch
// Run on your server. API_BASE ends in /api/v1 (combined host) or /v1 (verified cell).
const response = await fetch(process.env.SCOPEWORTH_API_BASE + "/organizations/example-org/workspaces/example-workspace/client-register", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.SCOPEWORTH_API_KEY}`
},
});
if (!response.ok) throw new Error(`ScopeWorth refused request: ${response.status}`);
const result = await response.json();Python requests
import os, requests
headers = {"Authorization":"Bearer " + os.environ["SCOPEWORTH_API_KEY"]}
response = requests.request("GET", os.environ["SCOPEWORTH_API_BASE"] + "/organizations/example-org/workspaces/example-workspace/client-register", headers=headers, timeout=30)
response.raise_for_status()
result = response.json()For refusals, follow error recovery. A scope or plan badge is eligibility, not proof of authorization or available evidence. Read current directory IDs and versions before correcting a request. Keep an idempotency key for one unchanged mutation attempt; never blindly retry uncertain external work.
Read a customer engagement
Operation: clients.read · GET /client-register/:clientId
Use the existing register aggregate with nested projects, commercial engagement terms, role rates and source attribution mappings. A client is your customer, separate from your ScopeWorth organization and workspace. GET /directory discovers project and client IDs. Listing returns all aggregates ordered by customer name without pagination; onboarding clients may have zero projects. Detail omits browser drafts. POST accepts a complete form without an autosave; PATCH requires the latest version from GET and stale writes return 409. Existing projects belong to that client, initiatives belong to that project, connections belong to that workspace, and current creator scope still applies. Amounts are integer minor currency units and rate units remain explicit. Organization-pooled limits are atomic and retries consume capacity once. Quota/conflict returns 409, invalid values 400, foreign resources 404. Writes require Idempotency-Key; reuse it only with the same normalized request, use a new key for each intentional edit. No invitation, email, provider request, logo, draft, deletion or archive endpoint is exposed. Mappings can attribute existing local evidence through the existing service.
Required key scope: clients:read. Current creator action: clients.read. Eligible plans: free, starter, growth, scale; legacy contracts: free, entry, growth. stable contract. These badges do not override current role, evidence window, quotas or target ownership.
-
PATCH requires the latest nonnegative version; version zero configures an onboarding client without a profile.
-
Writes require at least one project; omitting existing projects or initiatives does not delete them. All existing IDs must belong to the same client/project and workspace.
-
Commercial and project end dates cannot precede start dates; duplicate mapping pairs and currency/unit constraints use the shared register refinements.
-
Public writes preserve browser drafts; their normal version checks reject stale edits.
Parameters (required flags, defaults, units and bounds are the canonical schema):
View schema or synthetic response
[
{
"example": "11111111-1111-4111-8111-111111111111",
"in": "path",
"name": "clientId",
"required": true,
"schema": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)quot;,
"type": "string"
}
}
]
Success statuses: 200. The JSON response is the saved/read representation. Synthetic examples below show shape, not customer evidence.
Synthetic response:
View schema or synthetic response
{
"clientId": "11111111-1111-4111-8111-111111111111",
"connections": [],
"connectorWarning": true,
"form": {
"commercial": {
"billingFrequency": null,
"billingModel": "time_and_materials",
"blendedCostPerHourCents": null,
"contractedAmountCents": null,
"contractedHours": null,
"contractEnd": null,
"contractStart": "2026-10-01",
"currency": "USD",
"defaultBillingRatePerHourCents": null,
"hourlyBillingRateCents": null,
"includeAiToolingCosts": false,
"includeCloudCosts": false,
"includeContractorCosts": false,
"includeMeetingCosts": false,
"monthlyFeeCents": null,
"revenueSource": null,
"targetMarginPct": null
},
"profile": {
"accountManager": null,
"companyName": "Example customer",
"contactEmail": null,
"contactName": null,
"country": null,
"deliveryLead": null,
"industry": null,
"internalOwner": null,
"logoUrl": null,
"region": null,
"status": "active",
"timeZone": null,
"website": null
},
"projects": [
{
"budgetCents": null,
"description": null,
"endsOn": null,
"id": "22222222-2222-4222-8222-222222222222",
"initiatives": [],
"mappings": [],
"name": "Example delivery",
"objective": null,
"outcomeMetric": null,
"projectType": "Software delivery",
"rates": [],
"risk": "unknown",
"scopeLockDate": "2026-10-01",
"startsOn": "2026-10-01",
"status": "active",
"team": []
}
]
},
"version": 1
}
Use IDs and versions from your own preceding responses. Replace the synthetic UUIDs, dates and names in these independent examples. Set SCOPEWORTH_API_BASE and SCOPEWORTH_API_KEY only on your server.
cURL
curl --request GET "$SCOPEWORTH_API_BASE/organizations/example-org/workspaces/example-workspace/client-register/11111111-1111-4111-8111-111111111111" \
--header "Authorization: Bearer $SCOPEWORTH_API_KEY"JavaScript fetch
// Run on your server. API_BASE ends in /api/v1 (combined host) or /v1 (verified cell).
const response = await fetch(process.env.SCOPEWORTH_API_BASE + "/organizations/example-org/workspaces/example-workspace/client-register/11111111-1111-4111-8111-111111111111", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.SCOPEWORTH_API_KEY}`
},
});
if (!response.ok) throw new Error(`ScopeWorth refused request: ${response.status}`);
const result = await response.json();Python requests
import os, requests
headers = {"Authorization":"Bearer " + os.environ["SCOPEWORTH_API_KEY"]}
response = requests.request("GET", os.environ["SCOPEWORTH_API_BASE"] + "/organizations/example-org/workspaces/example-workspace/client-register/11111111-1111-4111-8111-111111111111", headers=headers, timeout=30)
response.raise_for_status()
result = response.json()For refusals, follow error recovery. A scope or plan badge is eligibility, not proof of authorization or available evidence. Read current directory IDs and versions before correcting a request. Keep an idempotency key for one unchanged mutation attempt; never blindly retry uncertain external work.
Create a customer and its projects
Operation: clients.create · POST /client-register
Use the existing register aggregate with nested projects, commercial engagement terms, role rates and source attribution mappings. A client is your customer, separate from your ScopeWorth organization and workspace. GET /directory discovers project and client IDs. Listing returns all aggregates ordered by customer name without pagination; onboarding clients may have zero projects. Detail omits browser drafts. POST accepts a complete form without an autosave; PATCH requires the latest version from GET and stale writes return 409. Existing projects belong to that client, initiatives belong to that project, connections belong to that workspace, and current creator scope still applies. Amounts are integer minor currency units and rate units remain explicit. Organization-pooled limits are atomic and retries consume capacity once. Quota/conflict returns 409, invalid values 400, foreign resources 404. Writes require Idempotency-Key; reuse it only with the same normalized request, use a new key for each intentional edit. No invitation, email, provider request, logo, draft, deletion or archive endpoint is exposed. Mappings can attribute existing local evidence through the existing service.
Required key scope: clients:write. Current creator action: clients.manage. Eligible plans: free, starter, growth, scale; legacy contracts: free, entry, growth. stable contract. These badges do not override current role, evidence window, quotas or target ownership.
-
PATCH requires the latest nonnegative version; version zero configures an onboarding client without a profile.
-
Writes require at least one project; omitting existing projects or initiatives does not delete them. All existing IDs must belong to the same client/project and workspace.
-
Commercial and project end dates cannot precede start dates; duplicate mapping pairs and currency/unit constraints use the shared register refinements.
-
Public writes preserve browser drafts; their normal version checks reject stale edits.
Parameters (required flags, defaults, units and bounds are the canonical schema):
View schema or synthetic response
[
{
"example": "example-create-1",
"in": "header",
"name": "idempotency-key",
"required": true,
"schema": {
"pattern": "^[\\x21-\\x7e]{1,200}quot;,
"type": "string"
}
}
]
Request body schema:
View schema or synthetic response
{
"content": {
"application/json": {
"examples": {
"synthetic1": {
"value": {
"form": {
"commercial": {
"billingFrequency": null,
"billingModel": "time_and_materials",
"blendedCostPerHourCents": null,
"contractedAmountCents": null,
"contractedHours": null,
"contractEnd": null,
"contractStart": "2026-10-01",
"currency": "USD",
"defaultBillingRatePerHourCents": null,
"hourlyBillingRateCents": null,
"includeAiToolingCosts": false,
"includeCloudCosts": false,
"includeContractorCosts": false,
"includeMeetingCosts": false,
"monthlyFeeCents": null,
"revenueSource": null,
"targetMarginPct": null
},
"profile": {
"accountManager": null,
"companyName": "Example customer",
"contactEmail": null,
"contactName": null,
"country": null,
"deliveryLead": null,
"industry": null,
"internalOwner": null,
"logoUrl": null,
"region": null,
"status": "active",
"timeZone": null,
"website": null
},
"projects": [
{
"budgetCents": null,
"description": null,
"endsOn": null,
"initiatives": [],
"mappings": [],
"name": "Example delivery",
"objective": null,
"outcomeMetric": null,
"projectType": "Software delivery",
"rates": [],
"risk": "unknown",
"scopeLockDate": "2026-10-01",
"startsOn": "2026-10-01",
"status": "active",
"team": []
}
]
}
}
}
},
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"form": {
"properties": {
"commercial": {
"properties": {
"billingFrequency": {
"anyOf": [
{
"maxLength": 80,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"billingModel": {
"enum": [
"time_and_materials",
"fixed_price",
"retainer"
],
"type": "string"
},
"blendedCostPerHourCents": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null
},
"contractedAmountCents": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null
},
"contractedHours": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null
},
"contractEnd": {
"anyOf": [
{
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))quot;,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"contractStart": {
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))quot;,
"type": "string"
},
"currency": {
"pattern": "^[A-Z]{3}quot;,
"type": "string"
},
"defaultBillingRatePerHourCents": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null
},
"hourlyBillingRateCents": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null
},
"includeAiToolingCosts": {
"default": false,
"type": "boolean"
},
"includeCloudCosts": {
"default": false,
"type": "boolean"
},
"includeContractorCosts": {
"default": false,
"type": "boolean"
},
"includeMeetingCosts": {
"default": false,
"type": "boolean"
},
"monthlyFeeCents": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null
},
"revenueSource": {
"anyOf": [
{
"maxLength": 120,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"targetMarginPct": {
"anyOf": [
{
"maximum": 100,
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"billingModel",
"currency",
"contractStart"
],
"type": "object"
},
"profile": {
"properties": {
"accountManager": {
"anyOf": [
{
"maxLength": 160,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"companyName": {
"maxLength": 200,
"minLength": 1,
"type": "string"
},
"contactEmail": {
"anyOf": [
{
"format": "email",
"maxLength": 320,
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}quot;,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"contactName": {
"anyOf": [
{
"maxLength": 160,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"country": {
"anyOf": [
{
"maxLength": 120,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"deliveryLead": {
"anyOf": [
{
"maxLength": 160,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"displayName": {
"anyOf": [
{
"maxLength": 120,
"minLength": 1,
"type": "string"
},
{
"type": "null"
}
]
},
"industry": {
"anyOf": [
{
"maxLength": 120,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"internalOwner": {
"anyOf": [
{
"maxLength": 160,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"logoUrl": {
"anyOf": [
{
"maxLength": 2048,
"pattern": "^\\/workspaces\\/.*",
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"region": {
"anyOf": [
{
"maxLength": 120,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"status": {
"default": "active",
"enum": [
"active",
"archived"
],
"type": "string"
},
"timeZone": {
"anyOf": [
{
"maxLength": 80,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"website": {
"anyOf": [
{
"format": "uri",
"maxLength": 2048,
"type": "string"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"companyName"
],
"type": "object"
},
"projects": {
"items": {
"properties": {
"budgetCents": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null
},
"description": {
"anyOf": [
{
"maxLength": 4000,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"endsOn": {
"anyOf": [
{
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))quot;,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"id": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)quot;,
"type": "string"
},
"initiatives": {
"default": [],
"items": {
"properties": {
"budgetCents": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null
},
"description": {
"anyOf": [
{
"maxLength": 2000,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"id": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)quot;,
"type": "string"
},
"name": {
"maxLength": 200,
"minLength": 1,
"type": "string"
},
"priority": {
"default": "none",
"enum": [
"high",
"medium",
"low",
"none"
],
"type": "string"
},
"source": {
"const": "manual",
"default": "manual",
"type": "string"
},
"status": {
"default": "planned",
"enum": [
"planned",
"active",
"completed",
"cancelled"
],
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"maxItems": 100,
"type": "array"
},
"mappings": {
"default": [],
"items": {
"properties": {
"connectionId": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)quot;,
"type": "string"
},
"externalProjectKey": {
"maxLength": 120,
"minLength": 1,
"type": "string"
}
},
"required": [
"connectionId",
"externalProjectKey"
],
"type": "object"
},
"maxItems": 100,
"type": "array"
},
"name": {
"maxLength": 200,
"minLength": 1,
"type": "string"
},
"objective": {
"anyOf": [
{
"maxLength": 2000,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"outcomeMetric": {
"anyOf": [
{
"maxLength": 500,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"projectType": {
"anyOf": [
{
"maxLength": 120,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"rates": {
"default": [],
"items": {
"properties": {
"amountCents": {
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
"currency": {
"pattern": "^[A-Z]{3}quot;,
"type": "string"
},
"role": {
"maxLength": 120,
"minLength": 1,
"type": "string"
},
"unit": {
"default": "hour",
"enum": [
"hour",
"day"
],
"type": "string"
}
},
"required": [
"role",
"amountCents",
"currency"
],
"type": "object"
},
"maxItems": 100,
"type": "array"
},
"risk": {
"default": "unknown",
"enum": [
"low",
"medium",
"high",
"unknown"
],
"type": "string"
},
"scopeLockDate": {
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))quot;,
"type": "string"
},
"startsOn": {
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))quot;,
"type": "string"
},
"status": {
"default": "active",
"enum": [
"active",
"paused",
"completed",
"archived"
],
"type": "string"
},
"team": {
"default": [],
"items": {
"properties": {
"alias": {
"maxLength": 120,
"minLength": 1,
"type": "string"
},
"allocationPct": {
"anyOf": [
{
"maximum": 100,
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null
},
"role": {
"maxLength": 120,
"minLength": 1,
"type": "string"
}
},
"required": [
"alias",
"role"
],
"type": "object"
},
"maxItems": 100,
"type": "array"
}
},
"required": [
"name",
"startsOn",
"scopeLockDate"
],
"type": "object"
},
"maxItems": 100,
"minItems": 1,
"type": "array"
}
},
"required": [
"profile",
"commercial",
"projects"
],
"type": "object"
},
"version": {
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
}
},
"required": [
"form"
],
"type": "object"
}
}
},
"required": true
}
Success statuses: 201. The JSON response is the saved/read representation. Synthetic examples below show shape, not customer evidence.
Synthetic response:
View schema or synthetic response
{
"clientId": "11111111-1111-4111-8111-111111111111",
"connections": [],
"connectorWarning": true,
"form": {
"commercial": {
"billingFrequency": null,
"billingModel": "time_and_materials",
"blendedCostPerHourCents": null,
"contractedAmountCents": null,
"contractedHours": null,
"contractEnd": null,
"contractStart": "2026-10-01",
"currency": "USD",
"defaultBillingRatePerHourCents": null,
"hourlyBillingRateCents": null,
"includeAiToolingCosts": false,
"includeCloudCosts": false,
"includeContractorCosts": false,
"includeMeetingCosts": false,
"monthlyFeeCents": null,
"revenueSource": null,
"targetMarginPct": null
},
"profile": {
"accountManager": null,
"companyName": "Example customer",
"contactEmail": null,
"contactName": null,
"country": null,
"deliveryLead": null,
"industry": null,
"internalOwner": null,
"logoUrl": null,
"region": null,
"status": "active",
"timeZone": null,
"website": null
},
"projects": [
{
"budgetCents": null,
"description": null,
"endsOn": null,
"id": "22222222-2222-4222-8222-222222222222",
"initiatives": [],
"mappings": [],
"name": "Example delivery",
"objective": null,
"outcomeMetric": null,
"projectType": "Software delivery",
"rates": [],
"risk": "unknown",
"scopeLockDate": "2026-10-01",
"startsOn": "2026-10-01",
"status": "active",
"team": []
}
]
},
"rowsAttributed": 0,
"version": 1
}
Use IDs and versions from your own preceding responses. Replace the synthetic UUIDs, dates and names in these independent examples. Set SCOPEWORTH_API_BASE and SCOPEWORTH_API_KEY only on your server.
cURL
curl --request POST "$SCOPEWORTH_API_BASE/organizations/example-org/workspaces/example-workspace/client-register" \
--header "Authorization: Bearer $SCOPEWORTH_API_KEY" \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: example-operation-attempt-1' \
--data-raw '{"form":{"profile":{"companyName":"Example customer","industry":null,"region":null,"country":null,"timeZone":null,"contactName":null,"contactEmail":null,"website":null,"logoUrl":null,"internalOwner":null,"accountManager":null,"deliveryLead":null,"status":"active"},"commercial":{"billingModel":"time_and_materials","currency":"USD","contractStart":"2026-10-01","contractEnd":null,"contractedAmountCents":null,"contractedHours":null,"targetMarginPct":null,"billingFrequency":null,"revenueSource":null,"hourlyBillingRateCents":null,"monthlyFeeCents":null,"blendedCostPerHourCents":null,"defaultBillingRatePerHourCents":null,"includeCloudCosts":false,"includeMeetingCosts":false,"includeAiToolingCosts":false,"includeContractorCosts":false},"projects":[{"name":"Example delivery","projectType":"Software delivery","status":"active","startsOn":"2026-10-01","endsOn":null,"scopeLockDate":"2026-10-01","budgetCents":null,"objective":null,"outcomeMetric":null,"risk":"unknown","description":null,"team":[],"rates":[],"mappings":[],"initiatives":[]}]}}'JavaScript fetch
// Run on your server. API_BASE ends in /api/v1 (combined host) or /v1 (verified cell).
const response = await fetch(process.env.SCOPEWORTH_API_BASE + "/organizations/example-org/workspaces/example-workspace/client-register", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SCOPEWORTH_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "example-operation-attempt-1"
},
body: JSON.stringify({
"form": {
"profile": {
"companyName": "Example customer",
"industry": null,
"region": null,
"country": null,
"timeZone": null,
"contactName": null,
"contactEmail": null,
"website": null,
"logoUrl": null,
"internalOwner": null,
"accountManager": null,
"deliveryLead": null,
"status": "active"
},
"commercial": {
"billingModel": "time_and_materials",
"currency": "USD",
"contractStart": "2026-10-01",
"contractEnd": null,
"contractedAmountCents": null,
"contractedHours": null,
"targetMarginPct": null,
"billingFrequency": null,
"revenueSource": null,
"hourlyBillingRateCents": null,
"monthlyFeeCents": null,
"blendedCostPerHourCents": null,
"defaultBillingRatePerHourCents": null,
"includeCloudCosts": false,
"includeMeetingCosts": false,
"includeAiToolingCosts": false,
"includeContractorCosts": false
},
"projects": [
{
"name": "Example delivery",
"projectType": "Software delivery",
"status": "active",
"startsOn": "2026-10-01",
"endsOn": null,
"scopeLockDate": "2026-10-01",
"budgetCents": null,
"objective": null,
"outcomeMetric": null,
"risk": "unknown",
"description": null,
"team": [],
"rates": [],
"mappings": [],
"initiatives": []
}
]
}
}),
});
if (!response.ok) throw new Error(`ScopeWorth refused request: ${response.status}`);
const result = await response.json();Python requests
import os, requests
headers = {"Authorization":"Bearer " + os.environ["SCOPEWORTH_API_KEY"],"Content-Type":"application/json","Idempotency-Key":"example-operation-attempt-1"}
response = requests.request("POST", os.environ["SCOPEWORTH_API_BASE"] + "/organizations/example-org/workspaces/example-workspace/client-register", headers=headers, json=__import__("json").loads("{\"form\":{\"profile\":{\"companyName\":\"Example customer\",\"industry\":null,\"region\":null,\"country\":null,\"timeZone\":null,\"contactName\":null,\"contactEmail\":null,\"website\":null,\"logoUrl\":null,\"internalOwner\":null,\"accountManager\":null,\"deliveryLead\":null,\"status\":\"active\"},\"commercial\":{\"billingModel\":\"time_and_materials\",\"currency\":\"USD\",\"contractStart\":\"2026-10-01\",\"contractEnd\":null,\"contractedAmountCents\":null,\"contractedHours\":null,\"targetMarginPct\":null,\"billingFrequency\":null,\"revenueSource\":null,\"hourlyBillingRateCents\":null,\"monthlyFeeCents\":null,\"blendedCostPerHourCents\":null,\"defaultBillingRatePerHourCents\":null,\"includeCloudCosts\":false,\"includeMeetingCosts\":false,\"includeAiToolingCosts\":false,\"includeContractorCosts\":false},\"projects\":[{\"name\":\"Example delivery\",\"projectType\":\"Software delivery\",\"status\":\"active\",\"startsOn\":\"2026-10-01\",\"endsOn\":null,\"scopeLockDate\":\"2026-10-01\",\"budgetCents\":null,\"objective\":null,\"outcomeMetric\":null,\"risk\":\"unknown\",\"description\":null,\"team\":[],\"rates\":[],\"mappings\":[],\"initiatives\":[]}]}}"), timeout=30)
response.raise_for_status()
result = response.json()For refusals, follow error recovery. A scope or plan badge is eligibility, not proof of authorization or available evidence. Read current directory IDs and versions before correcting a request. Keep an idempotency key for one unchanged mutation attempt; never blindly retry uncertain external work.
Save returned client/project IDs and version. Creation requires at least one project. Currency/reporting configuration must match the engagement. Distinct workspace clients/projects count toward plan caps.
Update a customer engagement
Operation: clients.update · PATCH /client-register/:clientId
Use the existing register aggregate with nested projects, commercial engagement terms, role rates and source attribution mappings. A client is your customer, separate from your ScopeWorth organization and workspace. GET /directory discovers project and client IDs. Listing returns all aggregates ordered by customer name without pagination; onboarding clients may have zero projects. Detail omits browser drafts. POST accepts a complete form without an autosave; PATCH requires the latest version from GET and stale writes return 409. Existing projects belong to that client, initiatives belong to that project, connections belong to that workspace, and current creator scope still applies. Amounts are integer minor currency units and rate units remain explicit. Organization-pooled limits are atomic and retries consume capacity once. Quota/conflict returns 409, invalid values 400, foreign resources 404. Writes require Idempotency-Key; reuse it only with the same normalized request, use a new key for each intentional edit. No invitation, email, provider request, logo, draft, deletion or archive endpoint is exposed. Mappings can attribute existing local evidence through the existing service.
Required key scope: clients:write. Current creator action: clients.manage. Eligible plans: free, starter, growth, scale; legacy contracts: free, entry, growth. stable contract. These badges do not override current role, evidence window, quotas or target ownership.
-
PATCH requires the latest nonnegative version; version zero configures an onboarding client without a profile.
-
Writes require at least one project; omitting existing projects or initiatives does not delete them. All existing IDs must belong to the same client/project and workspace.
-
Commercial and project end dates cannot precede start dates; duplicate mapping pairs and currency/unit constraints use the shared register refinements.
-
Public writes preserve browser drafts; their normal version checks reject stale edits.
Parameters (required flags, defaults, units and bounds are the canonical schema):
View schema or synthetic response
[
{
"example": "11111111-1111-4111-8111-111111111111",
"in": "path",
"name": "clientId",
"required": true,
"schema": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)quot;,
"type": "string"
}
},
{
"example": "example-update-1",
"in": "header",
"name": "idempotency-key",
"required": true,
"schema": {
"pattern": "^[\\x21-\\x7e]{1,200}quot;,
"type": "string"
}
}
]
Request body schema:
View schema or synthetic response
{
"content": {
"application/json": {
"examples": {
"synthetic1": {
"value": {
"form": {
"commercial": {
"billingFrequency": null,
"billingModel": "time_and_materials",
"blendedCostPerHourCents": null,
"contractedAmountCents": null,
"contractedHours": null,
"contractEnd": null,
"contractStart": "2026-10-01",
"currency": "USD",
"defaultBillingRatePerHourCents": null,
"hourlyBillingRateCents": null,
"includeAiToolingCosts": false,
"includeCloudCosts": false,
"includeContractorCosts": false,
"includeMeetingCosts": false,
"monthlyFeeCents": null,
"revenueSource": null,
"targetMarginPct": null
},
"profile": {
"accountManager": null,
"companyName": "Example customer",
"contactEmail": null,
"contactName": null,
"country": null,
"deliveryLead": null,
"industry": null,
"internalOwner": null,
"logoUrl": null,
"region": null,
"status": "active",
"timeZone": null,
"website": null
},
"projects": [
{
"budgetCents": null,
"description": null,
"endsOn": null,
"id": "22222222-2222-4222-8222-222222222222",
"initiatives": [],
"mappings": [],
"name": "Example delivery",
"objective": null,
"outcomeMetric": null,
"projectType": "Software delivery",
"rates": [],
"risk": "unknown",
"scopeLockDate": "2026-10-01",
"startsOn": "2026-10-01",
"status": "active",
"team": []
}
]
},
"version": 1
}
}
},
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"form": {
"properties": {
"commercial": {
"properties": {
"billingFrequency": {
"anyOf": [
{
"maxLength": 80,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"billingModel": {
"enum": [
"time_and_materials",
"fixed_price",
"retainer"
],
"type": "string"
},
"blendedCostPerHourCents": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null
},
"contractedAmountCents": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null
},
"contractedHours": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null
},
"contractEnd": {
"anyOf": [
{
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))quot;,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"contractStart": {
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))quot;,
"type": "string"
},
"currency": {
"pattern": "^[A-Z]{3}quot;,
"type": "string"
},
"defaultBillingRatePerHourCents": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null
},
"hourlyBillingRateCents": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null
},
"includeAiToolingCosts": {
"default": false,
"type": "boolean"
},
"includeCloudCosts": {
"default": false,
"type": "boolean"
},
"includeContractorCosts": {
"default": false,
"type": "boolean"
},
"includeMeetingCosts": {
"default": false,
"type": "boolean"
},
"monthlyFeeCents": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null
},
"revenueSource": {
"anyOf": [
{
"maxLength": 120,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"targetMarginPct": {
"anyOf": [
{
"maximum": 100,
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"billingModel",
"currency",
"contractStart"
],
"type": "object"
},
"profile": {
"properties": {
"accountManager": {
"anyOf": [
{
"maxLength": 160,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"companyName": {
"maxLength": 200,
"minLength": 1,
"type": "string"
},
"contactEmail": {
"anyOf": [
{
"format": "email",
"maxLength": 320,
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}quot;,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"contactName": {
"anyOf": [
{
"maxLength": 160,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"country": {
"anyOf": [
{
"maxLength": 120,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"deliveryLead": {
"anyOf": [
{
"maxLength": 160,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"displayName": {
"anyOf": [
{
"maxLength": 120,
"minLength": 1,
"type": "string"
},
{
"type": "null"
}
]
},
"industry": {
"anyOf": [
{
"maxLength": 120,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"internalOwner": {
"anyOf": [
{
"maxLength": 160,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"logoUrl": {
"anyOf": [
{
"maxLength": 2048,
"pattern": "^\\/workspaces\\/.*",
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"region": {
"anyOf": [
{
"maxLength": 120,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"status": {
"default": "active",
"enum": [
"active",
"archived"
],
"type": "string"
},
"timeZone": {
"anyOf": [
{
"maxLength": 80,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"website": {
"anyOf": [
{
"format": "uri",
"maxLength": 2048,
"type": "string"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"companyName"
],
"type": "object"
},
"projects": {
"items": {
"properties": {
"budgetCents": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null
},
"description": {
"anyOf": [
{
"maxLength": 4000,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"endsOn": {
"anyOf": [
{
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))quot;,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"id": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)quot;,
"type": "string"
},
"initiatives": {
"default": [],
"items": {
"properties": {
"budgetCents": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null
},
"description": {
"anyOf": [
{
"maxLength": 2000,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"id": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)quot;,
"type": "string"
},
"name": {
"maxLength": 200,
"minLength": 1,
"type": "string"
},
"priority": {
"default": "none",
"enum": [
"high",
"medium",
"low",
"none"
],
"type": "string"
},
"source": {
"const": "manual",
"default": "manual",
"type": "string"
},
"status": {
"default": "planned",
"enum": [
"planned",
"active",
"completed",
"cancelled"
],
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"maxItems": 100,
"type": "array"
},
"mappings": {
"default": [],
"items": {
"properties": {
"connectionId": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)quot;,
"type": "string"
},
"externalProjectKey": {
"maxLength": 120,
"minLength": 1,
"type": "string"
}
},
"required": [
"connectionId",
"externalProjectKey"
],
"type": "object"
},
"maxItems": 100,
"type": "array"
},
"name": {
"maxLength": 200,
"minLength": 1,
"type": "string"
},
"objective": {
"anyOf": [
{
"maxLength": 2000,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"outcomeMetric": {
"anyOf": [
{
"maxLength": 500,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"projectType": {
"anyOf": [
{
"maxLength": 120,
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"rates": {
"default": [],
"items": {
"properties": {
"amountCents": {
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
"currency": {
"pattern": "^[A-Z]{3}quot;,
"type": "string"
},
"role": {
"maxLength": 120,
"minLength": 1,
"type": "string"
},
"unit": {
"default": "hour",
"enum": [
"hour",
"day"
],
"type": "string"
}
},
"required": [
"role",
"amountCents",
"currency"
],
"type": "object"
},
"maxItems": 100,
"type": "array"
},
"risk": {
"default": "unknown",
"enum": [
"low",
"medium",
"high",
"unknown"
],
"type": "string"
},
"scopeLockDate": {
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))quot;,
"type": "string"
},
"startsOn": {
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))quot;,
"type": "string"
},
"status": {
"default": "active",
"enum": [
"active",
"paused",
"completed",
"archived"
],
"type": "string"
},
"team": {
"default": [],
"items": {
"properties": {
"alias": {
"maxLength": 120,
"minLength": 1,
"type": "string"
},
"allocationPct": {
"anyOf": [
{
"maximum": 100,
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null
},
"role": {
"maxLength": 120,
"minLength": 1,
"type": "string"
}
},
"required": [
"alias",
"role"
],
"type": "object"
},
"maxItems": 100,
"type": "array"
}
},
"required": [
"name",
"startsOn",
"scopeLockDate"
],
"type": "object"
},
"maxItems": 100,
"minItems": 1,
"type": "array"
}
},
"required": [
"profile",
"commercial",
"projects"
],
"type": "object"
},
"version": {
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
}
},
"required": [
"form",
"version"
],
"type": "object"
}
}
},
"required": true
}
Success statuses: 200. The JSON response is the saved/read representation. Synthetic examples below show shape, not customer evidence.
Synthetic response:
View schema or synthetic response
{
"clientId": "11111111-1111-4111-8111-111111111111",
"connections": [],
"connectorWarning": true,
"form": {
"commercial": {
"billingFrequency": null,
"billingModel": "time_and_materials",
"blendedCostPerHourCents": null,
"contractedAmountCents": null,
"contractedHours": null,
"contractEnd": null,
"contractStart": "2026-10-01",
"currency": "USD",
"defaultBillingRatePerHourCents": null,
"hourlyBillingRateCents": null,
"includeAiToolingCosts": false,
"includeCloudCosts": false,
"includeContractorCosts": false,
"includeMeetingCosts": false,
"monthlyFeeCents": null,
"revenueSource": null,
"targetMarginPct": null
},
"profile": {
"accountManager": null,
"companyName": "Example customer",
"contactEmail": null,
"contactName": null,
"country": null,
"deliveryLead": null,
"industry": null,
"internalOwner": null,
"logoUrl": null,
"region": null,
"status": "active",
"timeZone": null,
"website": null
},
"projects": [
{
"budgetCents": null,
"description": null,
"endsOn": null,
"id": "22222222-2222-4222-8222-222222222222",
"initiatives": [],
"mappings": [],
"name": "Example delivery",
"objective": null,
"outcomeMetric": null,
"projectType": "Software delivery",
"rates": [],
"risk": "unknown",
"scopeLockDate": "2026-10-01",
"startsOn": "2026-10-01",
"status": "active",
"team": []
}
]
},
"rowsAttributed": 0,
"version": 2
}
Use IDs and versions from your own preceding responses. Replace the synthetic UUIDs, dates and names in these independent examples. Set SCOPEWORTH_API_BASE and SCOPEWORTH_API_KEY only on your server.
cURL
curl --request PATCH "$SCOPEWORTH_API_BASE/organizations/example-org/workspaces/example-workspace/client-register/11111111-1111-4111-8111-111111111111" \
--header "Authorization: Bearer $SCOPEWORTH_API_KEY" \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: example-operation-attempt-1' \
--data-raw '{"form":{"profile":{"companyName":"Example customer","industry":null,"region":null,"country":null,"timeZone":null,"contactName":null,"contactEmail":null,"website":null,"logoUrl":null,"internalOwner":null,"accountManager":null,"deliveryLead":null,"status":"active"},"commercial":{"billingModel":"time_and_materials","currency":"USD","contractStart":"2026-10-01","contractEnd":null,"contractedAmountCents":null,"contractedHours":null,"targetMarginPct":null,"billingFrequency":null,"revenueSource":null,"hourlyBillingRateCents":null,"monthlyFeeCents":null,"blendedCostPerHourCents":null,"defaultBillingRatePerHourCents":null,"includeCloudCosts":false,"includeMeetingCosts":false,"includeAiToolingCosts":false,"includeContractorCosts":false},"projects":[{"id":"22222222-2222-4222-8222-222222222222","name":"Example delivery","projectType":"Software delivery","status":"active","startsOn":"2026-10-01","endsOn":null,"scopeLockDate":"2026-10-01","budgetCents":null,"objective":null,"outcomeMetric":null,"risk":"unknown","description":null,"team":[],"rates":[],"mappings":[],"initiatives":[]}]},"version":1}'JavaScript fetch
// Run on your server. API_BASE ends in /api/v1 (combined host) or /v1 (verified cell).
const response = await fetch(process.env.SCOPEWORTH_API_BASE + "/organizations/example-org/workspaces/example-workspace/client-register/11111111-1111-4111-8111-111111111111", {
method: "PATCH",
headers: {
"Authorization": `Bearer ${process.env.SCOPEWORTH_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "example-operation-attempt-1"
},
body: JSON.stringify({
"form": {
"profile": {
"companyName": "Example customer",
"industry": null,
"region": null,
"country": null,
"timeZone": null,
"contactName": null,
"contactEmail": null,
"website": null,
"logoUrl": null,
"internalOwner": null,
"accountManager": null,
"deliveryLead": null,
"status": "active"
},
"commercial": {
"billingModel": "time_and_materials",
"currency": "USD",
"contractStart": "2026-10-01",
"contractEnd": null,
"contractedAmountCents": null,
"contractedHours": null,
"targetMarginPct": null,
"billingFrequency": null,
"revenueSource": null,
"hourlyBillingRateCents": null,
"monthlyFeeCents": null,
"blendedCostPerHourCents": null,
"defaultBillingRatePerHourCents": null,
"includeCloudCosts": false,
"includeMeetingCosts": false,
"includeAiToolingCosts": false,
"includeContractorCosts": false
},
"projects": [
{
"id": "22222222-2222-4222-8222-222222222222",
"name": "Example delivery",
"projectType": "Software delivery",
"status": "active",
"startsOn": "2026-10-01",
"endsOn": null,
"scopeLockDate": "2026-10-01",
"budgetCents": null,
"objective": null,
"outcomeMetric": null,
"risk": "unknown",
"description": null,
"team": [],
"rates": [],
"mappings": [],
"initiatives": []
}
]
},
"version": 1
}),
});
if (!response.ok) throw new Error(`ScopeWorth refused request: ${response.status}`);
const result = await response.json();Python requests
import os, requests
headers = {"Authorization":"Bearer " + os.environ["SCOPEWORTH_API_KEY"],"Content-Type":"application/json","Idempotency-Key":"example-operation-attempt-1"}
response = requests.request("PATCH", os.environ["SCOPEWORTH_API_BASE"] + "/organizations/example-org/workspaces/example-workspace/client-register/11111111-1111-4111-8111-111111111111", headers=headers, json=__import__("json").loads("{\"form\":{\"profile\":{\"companyName\":\"Example customer\",\"industry\":null,\"region\":null,\"country\":null,\"timeZone\":null,\"contactName\":null,\"contactEmail\":null,\"website\":null,\"logoUrl\":null,\"internalOwner\":null,\"accountManager\":null,\"deliveryLead\":null,\"status\":\"active\"},\"commercial\":{\"billingModel\":\"time_and_materials\",\"currency\":\"USD\",\"contractStart\":\"2026-10-01\",\"contractEnd\":null,\"contractedAmountCents\":null,\"contractedHours\":null,\"targetMarginPct\":null,\"billingFrequency\":null,\"revenueSource\":null,\"hourlyBillingRateCents\":null,\"monthlyFeeCents\":null,\"blendedCostPerHourCents\":null,\"defaultBillingRatePerHourCents\":null,\"includeCloudCosts\":false,\"includeMeetingCosts\":false,\"includeAiToolingCosts\":false,\"includeContractorCosts\":false},\"projects\":[{\"id\":\"22222222-2222-4222-8222-222222222222\",\"name\":\"Example delivery\",\"projectType\":\"Software delivery\",\"status\":\"active\",\"startsOn\":\"2026-10-01\",\"endsOn\":null,\"scopeLockDate\":\"2026-10-01\",\"budgetCents\":null,\"objective\":null,\"outcomeMetric\":null,\"risk\":\"unknown\",\"description\":null,\"team\":[],\"rates\":[],\"mappings\":[],\"initiatives\":[]}]},\"version\":1}"), timeout=30)
response.raise_for_status()
result = response.json()For refusals, follow error recovery. A scope or plan badge is eligibility, not proof of authorization or available evidence. Read current directory IDs and versions before correcting a request. Keep an idempotency key for one unchanged mutation attempt; never blindly retry uncertain external work.
Read the current register before PATCH. Preserve IDs of retained projects and send the current version. Review project replacement/removal effects. Stale versions return 409. Follow schema currency precision; do not submit legacy UI draft fields. Existing source mappings can enqueue normal synchronization; success does not establish live provider success.
Continue with commercial inputs, imports and plans.