
Your CRM.
Connected by Weave.
Bring customer details into Weave, hand off a referral, and keep both companies’ systems in the loop.
Build your connection.
Each connection belongs to a company or one of its referral partners. Its imported customer list stays private to that connection. When a partner sends a referral, Weave shares the selected customer’s details with the receiving company.
- An administrator creates a connection and issues a key with the scopes the integration needs.
- Your integration imports customers from the source CRM. A sender selects a customer and confirms permission to share their details.
- The receiving integration reads the referral, creates its CRM record, and sends the record ID and progress back to Weave.
Developer preview. This reference covers the implemented API contract. Access must be enabled for your environment and account, with a paid API entitlement. Native GSRM, ServiceTitan, Housecall Pro, and Albi connectors and self-service setup screens are in development. Provider names in the API identify a connection; they do not activate a native connector.
One connection. Scoped access.
Send your connection’s API key as a bearer token. Keep it on your server. Keys are shown once, can be revoked, and have explicit scopes such as customers:read, customers:write, and referrals:write.
GET /api/v1/connections/{connectionId}/customers
Authorization: Bearer YOUR_WEAVE_API_KEY
Accept: application/jsonConnection and key administration requires an authorized Weave session. Session-based writes also require a matching Origin header. A company administrator cannot use their own access to browse a partner’s private customer list. Partner administrators control whether their team can access imported customers.
Request fields use camelCase. Returned database records use snake_case. Successful responses wrap records in data; paginated lists also return nextCursor. Use the full paths shown below on your Weave environment’s host.
From customer to referral.
Import the contact and service address with the CRM’s stable customer ID and its last update time. Keep unit or suite numbers separate. Optional company name and contact preferences help the receiving team follow up.
POST /api/v1/connections/{connectionId}/customers
Authorization: Bearer YOUR_WEAVE_API_KEY
Content-Type: application/json
{
"externalId": "customer-123",
"name": "Pat Homeowner",
"firstName": "Pat",
"lastName": "Homeowner",
"phone": "4255550123",
"email": "pat@example.com",
"address": {
"line1": "123 Main St",
"line2": "Unit 4",
"city": "Monroe",
"state": "WA",
"postalCode": "98272"
},
"sourceUpdatedAt": "2026-10-06T12:00:00Z"
}Use the returned Weave customer ID to submit the referral. Include the service need, urgency, and explicit consent to contact. Weave supplies the referral source company and referral contact from its membership records.
POST /api/v1/connections/{connectionId}/customers/{customerId}/referrals
Authorization: Bearer YOUR_WEAVE_API_KEY
Content-Type: application/json
Idempotency-Key: referral-customer-123-water-001
{
"lossType": "water",
"description": "Burst supply line under the kitchen sink.",
"isEmergency": true,
"consentToContact": true
}For a partner integration acting on a person’s behalf, include submittedByMemberId to identify the sending partner member. Weave verifies the membership. Without it, an API-key submission has company attribution but no individual referral contact. Session-based submissions use the signed-in member.
The receiving integration reads the referral, writes a customer, lead, or job to its CRM, then acknowledges that record with PUT /api/v1/connections/{connectionId}/referrals/{referralId}/crm-link. For example, send {"recordType":"job","externalId":"job-456"}. Only the receiving company can advance referral status. Status updates record progress; they do not execute payments.
A referral preserves the details shared at submission. Later customer imports do not silently rewrite it. CRM record IDs remain private to the connection that supplied them.
A better address, confirmed.
Use Google-powered autocomplete and address validation through your authenticated Weave connection. Both endpoints require customers:read and currently support US addresses. Show the returned Google Maps attribution alongside suggestions and results.
POST /api/v1/connections/{connectionId}/addresses/autocomplete
{
"input": "1600 Amphitheatre",
"sessionToken": "47c01763-bf66-47d8-bfb7-7120a9582381"
}
POST /api/v1/connections/{connectionId}/addresses/validate
{
"address": {
"line1": "1600 Amphitheatre Parkway",
"city": "Mountain View",
"state": "CA",
"postalCode": "94043"
},
"sessionToken": "47c01763-bf66-47d8-bfb7-7120a9582381"
}Create a fresh session token when address editing starts. Reuse it for suggestions and the first validation request, which ends the autocomplete session. If the sender edits the result, validate again without that token and include the first validation’s responseId as previousResponseId.
The response includes originalAddress, suggestedAddress, and an assessment of confirm or fix. Always have the sender confirm the address, including any unit or suite. Unresolved or missing details require a correction. If lookup is unavailable, allow manual entry.
After confirmation, pass confirmedAddress when referring an imported customer. It changes the address on that referral’s snapshot and leaves the source customer record intact. Keep Google keys on the server.
Keep both sides informed.
Register an HTTPS endpoint for the events your integration needs. Notifications contain identifiers; fetch the current authorized record for customer details and the latest status.
POST /api/v1/connections/{connectionId}/webhooks
Authorization: Bearer YOUR_WEAVE_API_KEY
Content-Type: application/json
{
"url": "https://your-app.example.com/webhooks/weave",
"events": ["referral.created", "referral.status_changed"]
}Verify X-Weave-Signature before processing the exact raw request body. Its format is t=timestamp,v1=signature. Compute HMAC-SHA256 with the connection’s outbound secret over timestamp + "." + rawBody, compare securely, and reject timestamps more than five minutes from your clock.
Durably accept the event before returning a 2xx response. Deduplicate by the body’s id or X-Weave-Event-Id. Delivery is at least once and events can arrive out of order.
To send CRM changes into Weave, post a normalized event to /api/webhooks/crm/{connectionId} and sign it with the separate inbound secret. This endpoint accepts the Weave event schema, not a provider’s raw webhook format. Your connector translates the CRM payload first. Rotating secrets invalidates both old secrets immediately.
Build for the second attempt.
- Referral retries: reuse the same
Idempotency-Keyand request body. Reusing a key with changed content returns 409. - Customer versions: send
sourceUpdatedAt. Older or equal versions are ignored, and deletion tombstones stop stale imports from restoring removed customers. - Event recovery: poll the events feed using its cursor. Webhooks make up to eight delivery attempts; inspect deliveries and explicitly retry exhausted items.
- Limits: JSON bodies are limited to 64 KiB. Requests are limited to 120 per minute per caller and connection; Google address requests also share a 120-per-minute connection limit. Honor
Retry-Afteron 429 responses. - Errors: 401 means missing or invalid authentication, 402 means a paid API entitlement is required, 403 means access is denied, and 422 means invalid input. Responses include an error code, message, and request ID.
Every endpoint, in one place.
Search the implemented API and expand an endpoint for its access requirements and request schema. The downloadable OpenAPI contract includes parameters and response schemas.
29 endpoints
GET/api/v1/capabilitiesDiscover implemented features and connector status
Public reference; no API key required.
Full response schemas in OpenAPI ↗GET/api/v1/openapiRead the OpenAPI 3.1.1 contract
Public reference; no API key required.
Full response schemas in OpenAPI ↗GET/api/v1/connectionsList connections visible to the signed-in person
Requires an authorized Weave session; connection changes require its owner’s administrator.
Full response schemas in OpenAPI ↗POST/api/v1/connectionsCreate a company or partner CRM connection
Requires an authorized Weave session; connection changes require its owner’s administrator.
JSON request schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"tenantId": {
"type": "string",
"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)$"
},
"partnerOrgId": {
"default": null,
"anyOf": [
{
"type": "string",
"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)$"
},
{
"type": "null"
}
]
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"provider": {
"type": "string",
"enum": [
"custom",
"gsrm",
"servicetitan",
"housecall_pro",
"albi"
]
},
"customerAccess": {
"default": "admins",
"type": "string",
"enum": [
"admins",
"team"
]
}
},
"required": [
"tenantId",
"name",
"provider"
],
"additionalProperties": false
}Full response schemas in OpenAPI ↗GET/api/v1/connections/{connectionId}Read connection settings
Requires an authorized Weave session; connection changes require its owner’s administrator.
Full response schemas in OpenAPI ↗PATCH/api/v1/connections/{connectionId}Rename, disable, or change team customer access
Requires an authorized Weave session; connection changes require its owner’s administrator.
JSON request schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"status": {
"type": "string",
"enum": [
"active",
"disabled"
]
},
"customerAccess": {
"type": "string",
"enum": [
"admins",
"team"
]
}
},
"additionalProperties": false
}Full response schemas in OpenAPI ↗GET/api/v1/connections/{connectionId}/keysList API key metadata
Requires an authorized Weave session; connection changes require its owner’s administrator.
Full response schemas in OpenAPI ↗POST/api/v1/connections/{connectionId}/keysIssue a scoped API key
Requires an authorized Weave session; connection changes require its owner’s administrator.
JSON request schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"scopes": {
"minItems": 1,
"maxItems": 8,
"type": "array",
"items": {
"type": "string",
"enum": [
"customers:read",
"customers:write",
"referrals:read",
"referrals:write",
"referrals:status",
"links:write",
"events:read",
"webhooks:manage"
]
}
},
"expiresInDays": {
"default": 90,
"type": "integer",
"minimum": 1,
"maximum": 365
}
},
"required": [
"name",
"scopes"
],
"additionalProperties": false
}Full response schemas in OpenAPI ↗DELETE/api/v1/connections/{connectionId}/keys/{keyId}Revoke an API key
Requires an authorized Weave session; connection changes require its owner’s administrator.
Full response schemas in OpenAPI ↗POST/api/v1/connections/{connectionId}/webhook-secret/rotateRotate both direction-specific webhook secrets immediately
Requires an authorized Weave session; connection changes require its owner’s administrator.
Full response schemas in OpenAPI ↗GET/api/v1/connections/{connectionId}/customersSearch the connection’s imported customers
Required scope: customers:read
Full response schemas in OpenAPI ↗POST/api/v1/connections/{connectionId}/customersImport a customer, ignoring older or equal source versions
Required scope: customers:write
JSON request schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"externalId": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"phone": {
"type": "string"
},
"firstName": {
"type": "string",
"maxLength": 200
},
"lastName": {
"type": "string",
"maxLength": 200
},
"companyName": {
"type": "string",
"maxLength": 200
},
"preferredContactMethod": {
"type": "string",
"enum": [
"phone",
"email"
]
},
"preferredContactTime": {
"type": "string",
"maxLength": 200
},
"email": {
"default": null,
"anyOf": [
{
"type": "string",
"maxLength": 254,
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
},
{
"type": "null"
}
]
},
"address": {
"type": "object",
"properties": {
"line1": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"line2": {
"type": "string",
"maxLength": 100
},
"city": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"state": {
"type": "string"
},
"postalCode": {
"type": "string",
"pattern": "^\\d{5}(-?\\d{4})?$"
}
},
"required": [
"line1",
"city",
"state",
"postalCode"
]
},
"sourceUpdatedAt": {
"type": "string",
"format": "date-time",
"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])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
},
"required": [
"externalId",
"name",
"phone",
"address",
"sourceUpdatedAt"
],
"additionalProperties": false
}Full response schemas in OpenAPI ↗POST/api/v1/connections/{connectionId}/addresses/autocompleteSuggest US addresses with Google Places
Required scope: customers:read
JSON request schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"input": {
"type": "string",
"minLength": 3,
"maxLength": 200
},
"sessionToken": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,36}$"
}
},
"required": [
"input",
"sessionToken"
],
"additionalProperties": false
}Full response schemas in OpenAPI ↗POST/api/v1/connections/{connectionId}/addresses/validateCheck and standardize an address with Google
Required scope: customers:read
JSON request schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"address": {
"type": "object",
"properties": {
"line1": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"line2": {
"type": "string",
"maxLength": 100
},
"city": {
"type": "string",
"maxLength": 100
},
"state": {
"type": "string",
"maxLength": 50
},
"postalCode": {
"type": "string",
"maxLength": 20
}
},
"required": [
"line1"
],
"additionalProperties": false
},
"sessionToken": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,36}$"
},
"previousResponseId": {
"type": "string",
"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)$"
}
},
"required": [
"address"
],
"additionalProperties": false
}Full response schemas in OpenAPI ↗GET/api/v1/connections/{connectionId}/customers/{customerId}Read a customer from this CRM connection
Required scope: customers:read
Full response schemas in OpenAPI ↗POST/api/v1/connections/{connectionId}/customers/deleteRemove cached details and preserve a versioned tombstone
Required scope: customers:write
JSON request schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"externalId": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"sourceUpdatedAt": {
"type": "string",
"format": "date-time",
"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])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
},
"required": [
"externalId",
"sourceUpdatedAt"
],
"additionalProperties": false
}Full response schemas in OpenAPI ↗POST/api/v1/connections/{connectionId}/customers/{customerId}/referralsShare a snapshot of this customer as a referral
Required scope: customers:read + referrals:write
JSON request schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"kind": {
"default": "referral",
"type": "string",
"enum": [
"referral",
"damage_report"
]
},
"lossType": {
"type": "string",
"enum": [
"water",
"fire",
"smoke",
"mold",
"storm",
"sewage",
"biohazard",
"reconstruction",
"contents",
"other"
]
},
"isEmergency": {
"default": false,
"type": "boolean"
},
"description": {
"type": "string",
"minLength": 1,
"maxLength": 4000
},
"occurredOn": {
"type": "string",
"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])))$"
},
"insurance": {
"type": "object",
"properties": {
"carrier": {
"type": "string",
"maxLength": 200
},
"claimNumber": {
"type": "string",
"maxLength": 100
}
}
},
"consentToContact": {
"type": "boolean",
"const": true
},
"partnerOrgId": {
"type": "string",
"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)$"
},
"submittedByMemberId": {
"type": "string",
"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)$"
},
"confirmedAddress": {
"type": "object",
"properties": {
"line1": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"line2": {
"type": "string",
"maxLength": 100
},
"city": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"state": {
"type": "string"
},
"postalCode": {
"type": "string",
"pattern": "^\\d{5}(-?\\d{4})?$"
}
},
"required": [
"line1",
"city",
"state",
"postalCode"
]
}
},
"required": [
"lossType",
"description",
"consentToContact"
],
"additionalProperties": false
}Full response schemas in OpenAPI ↗GET/api/v1/connections/{connectionId}/referralsList authorized referrals
Required scope: referrals:read
Full response schemas in OpenAPI ↗POST/api/v1/connections/{connectionId}/referralsSubmit a referral with explicit consent
Required scope: referrals:write
JSON request schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"kind": {
"default": "referral",
"type": "string",
"enum": [
"referral",
"damage_report"
]
},
"lossType": {
"type": "string",
"enum": [
"water",
"fire",
"smoke",
"mold",
"storm",
"sewage",
"biohazard",
"reconstruction",
"contents",
"other"
]
},
"isEmergency": {
"default": false,
"type": "boolean"
},
"description": {
"type": "string",
"minLength": 1,
"maxLength": 4000
},
"occurredOn": {
"type": "string",
"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])))$"
},
"contact": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"phone": {
"type": "string"
},
"email": {
"anyOf": [
{
"type": "string",
"const": ""
},
{
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
}
]
},
"firstName": {
"type": "string",
"maxLength": 200
},
"lastName": {
"type": "string",
"maxLength": 200
},
"companyName": {
"type": "string",
"maxLength": 200
},
"preferredContactMethod": {
"type": "string",
"enum": [
"phone",
"email"
]
},
"preferredContactTime": {
"type": "string",
"maxLength": 200
}
},
"required": [
"name",
"phone"
],
"additionalProperties": false
},
"address": {
"type": "object",
"properties": {
"line1": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"line2": {
"type": "string",
"maxLength": 100
},
"city": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"state": {
"type": "string"
},
"postalCode": {
"type": "string",
"pattern": "^\\d{5}(-?\\d{4})?$"
}
},
"required": [
"line1",
"city",
"state",
"postalCode"
]
},
"insurance": {
"type": "object",
"properties": {
"carrier": {
"type": "string",
"maxLength": 200
},
"claimNumber": {
"type": "string",
"maxLength": 100
}
}
},
"consentToContact": {
"type": "boolean",
"const": true
},
"partnerOrgId": {
"type": "string",
"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)$"
},
"submittedByMemberId": {
"type": "string",
"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)$"
}
},
"required": [
"lossType",
"description",
"contact",
"address",
"consentToContact"
],
"additionalProperties": false
}Full response schemas in OpenAPI ↗GET/api/v1/connections/{connectionId}/referrals/{referralId}Read a referral and this connection’s CRM links
Required scope: referrals:read
Full response schemas in OpenAPI ↗PATCH/api/v1/connections/{connectionId}/referrals/{referralId}/statusReceiving company advances the referral status
Required scope: referrals:status
JSON request schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"submitted",
"in_review",
"accepted",
"declined",
"contacted",
"inspection_scheduled",
"estimate_sent",
"won",
"lost",
"in_progress",
"completed",
"invoiced",
"paid",
"canceled"
]
},
"reason": {
"type": "string",
"minLength": 1,
"maxLength": 1000
}
},
"required": [
"status"
],
"additionalProperties": false
}Full response schemas in OpenAPI ↗PUT/api/v1/connections/{connectionId}/referrals/{referralId}/crm-linkAcknowledge a customer, lead, or job in this CRM
Required scope: links:write
JSON request schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"externalId": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"recordType": {
"type": "string",
"enum": [
"customer",
"lead",
"job"
]
}
},
"required": [
"externalId",
"recordType"
],
"additionalProperties": false
}Full response schemas in OpenAPI ↗GET/api/v1/connections/{connectionId}/eventsCatch up on this connection’s durable event feed
Required scope: events:read
Full response schemas in OpenAPI ↗GET/api/v1/connections/{connectionId}/webhooksList webhook subscriptions
Required scope: webhooks:manage
Full response schemas in OpenAPI ↗POST/api/v1/connections/{connectionId}/webhooksSubscribe an HTTPS endpoint to selected events
Required scope: webhooks:manage
JSON request schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"url": {
"type": "string",
"maxLength": 2000,
"pattern": "^https:\\/\\/[^/@?#:]+(?::443)?(?:[/?][^#]*)?$"
},
"events": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "string",
"enum": [
"customer.updated",
"customer.deleted",
"referral.created",
"referral.status_changed",
"referral.linked"
]
}
}
},
"required": [
"url",
"events"
],
"additionalProperties": false
}Full response schemas in OpenAPI ↗DELETE/api/v1/connections/{connectionId}/webhooks/{subscriptionId}Disable a webhook subscription
Required scope: webhooks:manage
Full response schemas in OpenAPI ↗GET/api/v1/connections/{connectionId}/deliveriesInspect delivery status and retry attempts
Required scope: webhooks:manage
Full response schemas in OpenAPI ↗POST/api/v1/connections/{connectionId}/deliveries/{deliveryId}/retryRetry an exhausted delivery
Required scope: webhooks:manage
Full response schemas in OpenAPI ↗POST/api/webhooks/crm/{connectionId}Send a signed, provider-neutral CRM event
Requires a valid X-Weave-Signature using the inbound secret.
JSON request schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"oneOf": [
{
"type": "object",
"properties": {
"eventId": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"type": {
"type": "string",
"const": "customer.upserted"
},
"data": {
"type": "object",
"properties": {
"externalId": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"phone": {
"type": "string"
},
"firstName": {
"type": "string",
"maxLength": 200
},
"lastName": {
"type": "string",
"maxLength": 200
},
"companyName": {
"type": "string",
"maxLength": 200
},
"preferredContactMethod": {
"type": "string",
"enum": [
"phone",
"email"
]
},
"preferredContactTime": {
"type": "string",
"maxLength": 200
},
"email": {
"default": null,
"anyOf": [
{
"type": "string",
"maxLength": 254,
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
},
{
"type": "null"
}
]
},
"address": {
"type": "object",
"properties": {
"line1": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"line2": {
"type": "string",
"maxLength": 100
},
"city": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"state": {
"type": "string"
},
"postalCode": {
"type": "string",
"pattern": "^\\d{5}(-?\\d{4})?$"
}
},
"required": [
"line1",
"city",
"state",
"postalCode"
]
},
"sourceUpdatedAt": {
"type": "string",
"format": "date-time",
"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])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
},
"required": [
"externalId",
"name",
"phone",
"address",
"sourceUpdatedAt"
],
"additionalProperties": false
}
},
"required": [
"eventId",
"type",
"data"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"eventId": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"type": {
"type": "string",
"const": "customer.deleted"
},
"data": {
"type": "object",
"properties": {
"externalId": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"sourceUpdatedAt": {
"type": "string",
"format": "date-time",
"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])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
},
"required": [
"externalId",
"sourceUpdatedAt"
],
"additionalProperties": false
}
},
"required": [
"eventId",
"type",
"data"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"eventId": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"type": {
"type": "string",
"const": "referral.status_changed"
},
"data": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"submitted",
"in_review",
"accepted",
"declined",
"contacted",
"inspection_scheduled",
"estimate_sent",
"won",
"lost",
"in_progress",
"completed",
"invoiced",
"paid",
"canceled"
]
},
"reason": {
"type": "string",
"minLength": 1,
"maxLength": 1000
},
"referralId": {
"type": "string",
"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)$"
}
},
"required": [
"status",
"referralId"
],
"additionalProperties": false
}
},
"required": [
"eventId",
"type",
"data"
],
"additionalProperties": false
}
]
}Full response schemas in OpenAPI ↗