{"openapi":"3.0.3","info":{"title":"Connections Developer API","version":"1.0.0","description":"Developer API for Connections relationship data: contacts, touches, search, your network (first/second-degree + warm-path introductions), introductions, registration products, forms, bundles, MyConnect, and email signatures. Hosted-event endpoints (/events and sub-resources, /hosts, /registrations, /webhooks) were retired from this API on 2026-07-10 - hosted events are owned by the events plane; consume its API at https://events.connectionsapi.com (OpenAPI: https://events.connectionsapi.com/openapi.json)."},"servers":[{"url":"https://connections.icu/v1"}],"components":{"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","description":"Connections workspace API key.","x-connections-credential":"connections-key"},"OAuth2":{"type":"http","scheme":"bearer","description":"Connections OAuth access token.","x-connections-credential":"oauth-access-token"},"memberSession":{"type":"http","scheme":"bearer","description":"The member's own Connections session access token, exactly as this product's own app sends it. Only operations that declare this scheme accept one.","x-connections-credential":"member-session"}},"schemas":{"ErrorResponse":{"type":"object","description":"Standard error payload returned by the Connections Developer API.","required":["error"],"properties":{"error":{"type":"string"}}},"DeletedResponse":{"type":"object","required":["deleted"],"properties":{"deleted":{"type":"boolean"}}},"IntrospectionResponse":{"type":"object","description":"Result of GET /v1/auth/introspect. Describes the current credential, the scopes it carries, and the capabilities (paths + methods) it can call. Agents should call this once before issuing other API calls.","required":["schemaVersion","status","credentialType","scopes","capabilities","docs","auth","rules"],"properties":{"schemaVersion":{"type":"string"},"status":{"type":"string","enum":["active"]},"credentialType":{"type":"string","enum":["api_key","oauth_token","user_session"]},"actorProfileId":{"type":"string","nullable":true},"ownerProfileId":{"type":"string","nullable":true},"scopes":{"type":"array","items":{"type":"string"}},"capabilities":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"summary":{"type":"string"},"requiredScopes":{"type":"array","items":{"type":"string"}},"methods":{"type":"array","items":{"type":"string"}},"paths":{"type":"array","items":{"type":"string"}}}}},"docs":{"type":"object","properties":{"humanUrl":{"type":"string"},"openApiUrl":{"type":"string"},"introspectUrl":{"type":"string"}}},"auth":{"type":"object","properties":{"acceptedHeaders":{"type":"array","items":{"type":"string"}}}},"rules":{"type":"array","items":{"type":"string"}}}},"AuditLogEntry":{"type":"object","description":"Admin audit log entry. Visible only with admin:read.","properties":{"id":{"type":"string"},"actor_profile_id":{"type":"string","nullable":true},"actor_name":{"type":"string","nullable":true},"action":{"type":"string"},"target_table":{"type":"string","nullable":true},"target_id":{"type":"string","nullable":true},"details":{"type":"object","nullable":true},"created_at":{"type":"string"}}},"AuditLogListResponse":{"type":"object","required":["entries"],"properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/AuditLogEntry"}}}},"ContactFolder":{"type":"object","description":"Contact folder/tag returned by the Connections Developer API.","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"color":{"type":"string","nullable":true},"icon":{"type":"string","nullable":true},"kind":{"type":"string","enum":["manual","auto_event","auto_company","auto_location"]},"sort_order":{"type":"integer"},"contact_count":{"type":"integer"},"average_score":{"type":"number","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"}}},"ContactFolderListResponse":{"type":"object","required":["folders"],"properties":{"folders":{"type":"array","items":{"$ref":"#/components/schemas/ContactFolder"}}}},"ContactFolderResponse":{"type":"object","required":["folder"],"properties":{"folder":{"$ref":"#/components/schemas/ContactFolder"}}},"Touch":{"type":"object","description":"Relationship touch returned by the Connections Developer API.","properties":{"id":{"type":"string","description":"Touch ID."},"contact_id":{"type":"string","description":"Contact ID for the person this touch belongs to."},"contact_name":{"type":"string","nullable":true,"description":"Current display name for the contact."},"kind":{"type":"string","enum":["note","meeting","call","message","email","introduction"],"description":"Touch type."},"body":{"type":"string","description":"Touch note body."},"occurred_at":{"type":"string","description":"ISO-8601 UTC timestamp when the touch occurred."},"metadata":{"type":"object","nullable":true,"description":"Source metadata for this touch."},"created_at":{"type":"string","description":"ISO-8601 UTC timestamp when the touch was created."},"updated_at":{"type":"string","description":"ISO-8601 UTC timestamp when the touch was last updated."}}},"TouchWriteInput":{"type":"object","required":["contact_id","body"],"description":"Touch write input. POST requires contact_id and body; kind defaults to note.","properties":{"contact_id":{"type":"string"},"kind":{"type":"string","enum":["note","meeting","call","message","email","introduction"]},"body":{"type":"string"},"occurred_at":{"type":"string","nullable":true}}},"ContactCallInput":{"type":"object","required":["storage_object_id"],"description":"A recorded call to log on the contact: the recording in the member’s storage locker, and when the call happened.","properties":{"storage_object_id":{"type":"string","description":"The call recording’s storage object ID (flow call_recording)."},"occurred_at":{"type":"string","nullable":true,"description":"ISO-8601 time of the call. Defaults to now."}}},"TouchListResponse":{"type":"object","required":["touches"],"properties":{"touches":{"type":"array","items":{"$ref":"#/components/schemas/Touch"}}}},"TouchResponse":{"type":"object","required":["touch"],"properties":{"touch":{"$ref":"#/components/schemas/Touch"}}},"Contact":{"type":"object","description":"Contact returned by the Connections Developer API.","properties":{"id":{"type":"string"},"name":{"type":"string"},"phone":{"type":"string","nullable":true},"email":{"type":"string","nullable":true},"context":{"type":"string","nullable":true},"location_label":{"type":"string","nullable":true},"last_met_label":{"type":"string","nullable":true},"color":{"type":"string","nullable":true},"is_favorite":{"type":"boolean"},"needs_follow_up":{"type":"boolean"},"company":{"type":"string","nullable":true},"job_title":{"type":"string","nullable":true},"tags":{"type":"array","items":{"type":"string"}},"relationship_signals":{"type":"object","description":"Folders, tags, touch summary, and relationship graph for this contact.","properties":{"tags":{"type":"array","items":{"type":"string"}},"folders":{"type":"array","items":{"type":"object"}},"touch_count":{"type":"integer"},"last_touch_at":{"type":"string","nullable":true},"relationships":{"type":"array","items":{"type":"object"}}}},"created_at":{"type":"string"},"updated_at":{"type":"string"}}},"ContactListResponse":{"type":"object","required":["contacts"],"properties":{"contacts":{"type":"array","items":{"$ref":"#/components/schemas/Contact"}}}},"ContactResponse":{"type":"object","required":["contact"],"properties":{"contact":{"$ref":"#/components/schemas/Contact"}}},"ContactSearchResponse":{"type":"object","description":"Result of GET /contacts/search.","required":["query","contacts"],"properties":{"query":{"type":"string"},"contacts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"phone":{"type":"string","nullable":true},"email":{"type":"string","nullable":true},"context":{"type":"string","nullable":true},"image_url":{"type":"string","nullable":true,"description":"The contact photo, when one is set."},"location_label":{"type":"string","nullable":true},"last_met_label":{"type":"string","nullable":true},"is_favorite":{"type":"boolean"},"needs_follow_up":{"type":"boolean"},"updated_at":{"type":"string"},"score":{"type":"number"}}}}}},"ContactTimelineResponse":{"type":"object","description":"Result of GET /contacts/{id}/timeline.","required":["contact","touches"],"properties":{"contact":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}},"touches":{"type":"array","items":{"$ref":"#/components/schemas/Touch"}}}},"ContactImportRow":{"type":"object","description":"One contact row in a POST /contacts/import batch.","properties":{"fullName":{"type":"string"},"title":{"type":"string"},"company":{"type":"string"},"emails":{"type":"array","items":{"type":"string"}},"phones":{"type":"array","items":{"type":"string"}},"websites":{"type":"array","items":{"type":"string"}},"note":{"type":"string"},"photoUrl":{"type":"string"},"externalId":{"type":"string","description":"Your own stable id for this person (a CRM record id, etc). Optional, but STRONGLY recommended: re-POSTing the same externalId later updates the same contact instead of creating a duplicate - without it, matching falls back to email/phone only, same as a plain file import."}}},"ContactImportRequest":{"type":"object","required":["source","contacts"],"description":"POST /contacts/import request body.","properties":{"source":{"type":"string","description":"Your label for this import (e.g. \"acme_crm\"). Lowercase slug, 1-40 chars: letters, digits, \"_\", \"-\"."},"contacts":{"type":"array","items":{"$ref":"#/components/schemas/ContactImportRow"},"description":"Up to 5000 rows per call."}}},"ContactImportResponse":{"type":"object","required":["import"],"properties":{"import":{"type":"object","properties":{"source":{"type":"string","enum":["developer"]},"total":{"type":"integer","description":"Rows submitted, including any dropped as blank."},"imported":{"type":"integer","description":"created + updated."},"created":{"type":"integer"},"updated":{"type":"integer"},"skipped":{"type":"integer"}}}}},"ContactWriteInput":{"type":"object","description":"Contact write input. POST requires name. PATCH updates only supplied fields.","properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"context":{"type":"string"},"locationLabel":{"type":"string"},"lastMetLabel":{"type":"string"},"color":{"type":"string"},"isFavorite":{"type":"boolean"},"needsFollowUp":{"type":"boolean"},"company":{"type":"string","description":"Overwrites unconditionally when supplied - never merged with the existing value."},"jobTitle":{"type":"string","description":"Overwrites unconditionally when supplied - never merged with the existing value."},"tags":{"type":"array","items":{"type":"string"}}}},"SearchResult":{"type":"object","description":"Search result returned by scoped Developer API search.","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["contact","touch"]},"title":{"type":"string"},"subtitle":{"type":"string","nullable":true},"summary":{"type":"string","nullable":true},"contact_id":{"type":"string","nullable":true},"score":{"type":"number"},"match":{"type":"string","enum":["lexical","semantic"]}}},"SearchResponse":{"type":"object","required":["query","results"],"properties":{"query":{"type":"string"},"results":{"type":"array","items":{"$ref":"#/components/schemas/SearchResult"}},"semantic":{"type":"object","properties":{"enabled":{"type":"boolean"},"degraded":{"type":"boolean"}}}}},"IntroductionRequest":{"type":"object","description":"Consent-preserving introduction request returned by the Connections Developer API.","properties":{"id":{"type":"string"},"requester_profile_id":{"type":"string"},"target_contact_id":{"type":"string","nullable":true},"broker_profile_id":{"type":"string","nullable":true},"broker_contact_id":{"type":"string","nullable":true},"query":{"type":"string"},"request_kind":{"type":"string","enum":["direct","brokered","unmatched","owner_brokered","co_attended"]},"status":{"type":"string","enum":["pending","approved","declined","expired","completed"]},"routing_mode":{"type":"string","enum":["direct","warm_path","unresolved","admin_review"]},"target_visibility":{"type":"string","enum":["broker_only","requester_visible","fully_redacted"]},"routing_metadata":{"type":"object"},"request_note":{"type":"string"},"broker_note":{"type":"string"},"redacted_summary":{"type":"string"},"approved_at":{"type":"string","nullable":true},"declined_at":{"type":"string","nullable":true},"expires_at":{"type":"string","nullable":true},"completed_at":{"type":"string","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"}}},"IntroductionRequestWriteInput":{"type":"object","required":["query"],"description":"Create a pending introduction request. target_contact_id and broker_contact_id must reference contacts owned by the credential. Protected requests stay redacted until the existing consent flow completes.","properties":{"query":{"type":"string"},"target_contact_id":{"type":"string","nullable":true},"broker_contact_id":{"type":"string","nullable":true},"request_kind":{"type":"string","enum":["direct","brokered","unmatched"]},"target_visibility":{"type":"string","enum":["broker_only","requester_visible","fully_redacted"]},"broker_path":{"type":"array","items":{"type":"string"}},"routing_metadata":{"type":"object"},"request_note":{"type":"string"},"broker_note":{"type":"string"},"redacted_summary":{"type":"string"}}},"IntroductionRequestListResponse":{"type":"object","required":["introduction_requests"],"properties":{"introduction_requests":{"type":"array","items":{"$ref":"#/components/schemas/IntroductionRequest"}}}},"IntroductionRequestResponse":{"type":"object","required":["introduction_request"],"properties":{"introduction_request":{"$ref":"#/components/schemas/IntroductionRequest"}}},"NetworkNeighborhoodResponse":{"type":"object","description":"Result of GET /network: the confirmed network neighborhood rooted at the credential owner.","required":["rootSub","nodes","edges","truncated"],"properties":{"rootSub":{"type":"string","description":"The credential owner's AEGIS sub."},"nodes":{"type":"array","items":{"type":"object","properties":{"sub":{"type":"string"},"ring":{"type":"integer","enum":[1,2]},"displayName":{"type":"string","description":"From the owner's own contact card. Always empty for ring-2 nodes (another owner's contact card never crosses the seam)."}}}},"edges":{"type":"array","items":{"type":"object","properties":{"fromSub":{"type":"string"},"toSub":{"type":"string"},"matchKind":{"type":"string","enum":["deterministic","user_confirmed"]},"ring":{"type":"integer","enum":[1,2]}}}},"truncated":{"type":"boolean","description":"True when a ring hit its limit: the picture is partial."}}},"WarmPathsResponse":{"type":"object","description":"Result of GET /network/warm-paths.","required":["target","paths"],"properties":{"target":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"linked":{"type":"boolean"}}},"paths":{"type":"array","items":{"type":"object","properties":{"viaSub":{"type":"string"},"viaDisplayName":{"type":"string"},"touches90d":{"type":"integer"},"lastTouchAt":{"type":"string","nullable":true},"score":{"type":"number"}}}},"fallback":{"type":"string","nullable":true,"enum":["first_degree_network",null]},"firstDegreeNetwork":{"type":"array","items":{"type":"object"},"description":"Present only when fallback is first_degree_network."}}},"ProductCatalogResponse":{"type":"object","required":["products","connect"],"properties":{"products":{"type":"array","description":"Products eligible for registration bypasses or imported product selection. Use id as stripe_product_id and defaultPrice.priceId as stripe_price_id when stripe_mode is imported.","items":{"type":"object","properties":{"id":{"type":"string","description":"Stripe product ID."},"name":{"type":"string"},"source":{"type":"string","enum":["platform","connect"]},"defaultPrice":{"type":"object","nullable":true,"properties":{"priceId":{"type":"string","nullable":true,"description":"Stripe price ID when available."},"unitAmount":{"type":"integer"},"currency":{"type":"string"},"interval":{"type":"string","nullable":true,"enum":["day","week","month","year",null]},"intervalCount":{"type":"integer"}}}}}},"connect":{"type":"object","properties":{"connected":{"type":"boolean"},"chargesEnabled":{"type":"boolean"},"error":{"type":"string","description":"Sanitized reason connected Stripe products could not load."}}}}},"WorkspaceFormWriteInput":{"type":"object","description":"Form write input. POST requires name. PATCH updates only supplied fields.","properties":{"name":{"type":"string"},"slug":{"type":"string","description":"Public form slug."},"description":{"type":"string"},"theme":{"type":"string","enum":["light","dark","paper","skyline","glass","minimal","confetti","graphite","neon","luxe","ink","afterglow"],"description":"Shared public page theme."},"fields_json":{"type":"array","items":{"type":"object"}},"success_message":{"type":"string"},"is_active":{"type":"boolean"},"self_notification_email":{"type":"string","nullable":true,"description":"Email a copy of every submission to this address. Empty string or null stops it."},"send_respondent_confirmation":{"type":"boolean","description":"Email the respondent a receipt of their answers after they submit."},"slack_webhook_url":{"type":"string","nullable":true,"description":"https incoming-webhook URL that receives a summary of every submission."},"logo_url":{"type":"string","nullable":true,"description":"https URL of the logo shown at the top of the public form."},"cover_image_url":{"type":"string","nullable":true,"description":"https URL of the cover image above the public form."},"color_settings":{"type":"object","nullable":true,"description":"Page colors. Keys: background, text, accent, button, buttonText; each a CSS color of at most 32 characters.","properties":{"background":{"type":"string"},"text":{"type":"string"},"accent":{"type":"string"},"button":{"type":"string"},"buttonText":{"type":"string"}}},"submit_button_label":{"type":"string","nullable":true,"maxLength":80},"next_button_label":{"type":"string","nullable":true,"maxLength":80},"back_button_label":{"type":"string","nullable":true,"maxLength":80},"show_form_title":{"type":"boolean","nullable":true,"description":"false hides the title and description on the public page."},"company_id":{"type":"string","description":"PATCH only. Puts the form into the workspace this key is bound to, so its public page presents the company. Only the key workspace id is accepted."}}},"WorkspaceBundleWriteInput":{"type":"object","description":"Bundle write input. POST requires name. Bundle resources can reference forms and hosted events, while registration fields, flow edges, and ticket tiers use the same builder JSON model as the workspace UI.","properties":{"name":{"type":"string"},"slug":{"type":"string","description":"Public bundle slug."},"description":{"type":"string"},"status":{"type":"string","enum":["draft","live","archived"]},"resources_json":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Resource key, for example form:<id> or event:<id>."},"type":{"type":"string","enum":["form","event"]},"unlockConditionIds":{"type":"array","items":{"type":"string"}}}}},"registration_fields_enabled":{"type":"boolean"},"registration_advanced_mode":{"type":"boolean"},"registration_fields":{"type":"array","items":{"type":"object","description":"Registration question. Provide a UUID id when another field or route references it; omit id to let Connections generate one.","properties":{"id":{"type":"string","format":"uuid"},"field_key":{"type":"string","description":"Stable key for answers, for example linkedin or accredited."},"field_type":{"type":"string","description":"Question type such as text, textarea, email, url, yes_no, select, radio, vote, multi_select, checkbox, or link. yes_no/radio are saved as the same choice-field shape the workspace registration builder uses."},"label":{"type":"string"},"helper_text":{"type":"string"},"placeholder":{"type":"string"},"is_required":{"type":"boolean"},"options":{"type":"array","items":{"oneOf":[{"type":"string"},{"type":"object"}]},"description":"Choice options for yes_no/select/radio/vote/multi_select fields. Strings are saved directly; objects use value, then label, then id. For yes/no branching, use the canonical strings Yes and No."},"visibility_field_key":{"type":"string","description":"Show this field only after another field has one of visibility_values."},"visibility_values":{"type":"array","items":{"type":"string"}},"ticket_tier_ids":{"type":"array","items":{"type":"string"},"description":"Product/ticket UUIDs this field routes to or unlocks."},"ticket_tier_routing_rules":{"type":"array","items":{"type":"object"},"description":"Advanced per-answer routing rules."},"sort_order":{"type":"integer"}}}},"registration_flow_edges":{"type":"array","items":{"type":"object","description":"Advanced registration route edge. Use sourceType start/question/ticket and targetType field/tier/end. Legacy sourceId/targetId plus condition.value is accepted, but the full shape matches the workspace builder exactly.","properties":{"sourceType":{"type":"string","enum":["start","question","ticket"]},"sourceId":{"type":"string"},"sourceAnswerValue":{"type":"string","nullable":true,"description":"Answer option for question edges, for example Yes or No. Omit/null for start and ticket edges."},"targetType":{"type":"string","enum":["field","tier","end"]},"targetId":{"type":"string"},"condition":{"type":"object","description":"Legacy shorthand. condition.value is converted into sourceAnswerValue.","deprecated":true}}}},"ticketing_enabled":{"type":"boolean"},"ticket_tiers":{"type":"array","items":{"type":"object","description":"Free or paid product/ticket. Provide a globally unique UUID id when routing references it; omit id to let Connections generate one. Do not reuse sample UUIDs across events.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"price_cents":{"type":"integer","description":"0 for free products."},"currency":{"type":"string","default":"USD"},"quantity_total":{"type":"integer","nullable":true},"visibility":{"type":"string","enum":["public","hidden","internal"],"default":"public"},"sort_order":{"type":"integer"},"stripe_mode":{"type":"string","enum":["platform","imported"],"description":"platform = Connections-created product. imported = product/price from the host connected Stripe account."},"stripe_product_id":{"type":"string","description":"Use for imported Stripe products."},"stripe_price_id":{"type":"string","description":"Use for imported Stripe prices."},"ticket_billing_kind":{"type":"string","enum":["one_time","subscription"]},"billing_interval":{"type":"string","enum":["day","week","month","year","lifetime"],"description":"Use product.defaultPrice.interval from GET /v1/products for imported recurring Stripe prices. Use lifetime for one-time products."},"billing_interval_count":{"type":"integer","default":1,"description":"Use product.defaultPrice.intervalCount from GET /v1/products for imported recurring Stripe prices, for example 4 with billing_interval week."},"metadata":{"type":"object"}}}},"success_message":{"type":"string"}}},"WorkspaceForm":{"type":"object","description":"Workspace form definition.","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"theme":{"type":"string"},"fields_json":{"type":"array","items":{"type":"object"}},"success_message":{"type":"string"},"is_active":{"type":"boolean"},"self_notification_email":{"type":"string","nullable":true,"description":"Email a copy of every submission to this address. Empty string or null stops it."},"send_respondent_confirmation":{"type":"boolean","description":"Email the respondent a receipt of their answers after they submit."},"slack_webhook_url":{"type":"string","nullable":true,"description":"https incoming-webhook URL that receives a summary of every submission."},"logo_url":{"type":"string","nullable":true,"description":"https URL of the logo shown at the top of the public form."},"cover_image_url":{"type":"string","nullable":true,"description":"https URL of the cover image above the public form."},"color_settings":{"type":"object","nullable":true,"description":"Page colors. Keys: background, text, accent, button, buttonText; each a CSS color of at most 32 characters.","properties":{"background":{"type":"string"},"text":{"type":"string"},"accent":{"type":"string"},"button":{"type":"string"},"buttonText":{"type":"string"}}},"submit_button_label":{"type":"string","nullable":true,"maxLength":80},"next_button_label":{"type":"string","nullable":true,"maxLength":80},"back_button_label":{"type":"string","nullable":true,"maxLength":80},"show_form_title":{"type":"boolean","nullable":true,"description":"false hides the title and description on the public page."},"company_id":{"type":"string","nullable":true,"description":"The workspace this form serves; null when it is not assigned to one."},"submission_count":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"}}},"WorkspaceFormSubmission":{"type":"object","description":"One submission of a form: what the respondent answered, and when.","properties":{"id":{"type":"string"},"submitted_at":{"type":"string","format":"date-time"},"answers":{"type":"object","additionalProperties":true,"nullable":true,"description":"The answers, keyed by each field fieldKey. null only when this one submission is larger than a page can carry (over 300 KB); it is listed on a page of its own so paging continues past it."},"contact_id":{"type":"string","nullable":true,"description":"The contact this submission became, when it carried an email or phone."}}},"WorkspaceFormSubmissionPage":{"type":"object","required":["submissions","next_cursor"],"properties":{"submissions":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceFormSubmission"}},"next_cursor":{"type":"string","nullable":true,"description":"Pass as ?cursor= for the next page; null on the last page."}}},"WorkspaceFormListResponse":{"type":"object","required":["forms","next_cursor"],"properties":{"forms":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceForm"}},"next_cursor":{"type":"string","nullable":true,"description":"Pass as ?cursor= for the next page; null on the last page. A page also ends early at a byte budget, and a single row too big for it is listed alone with its large fields null."}}},"WorkspaceFormResponse":{"type":"object","required":["form"],"properties":{"form":{"$ref":"#/components/schemas/WorkspaceForm"}}},"WorkspaceBundle":{"type":"object","description":"Workspace bundle access flow.","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","live","archived"]},"resources_json":{"type":"array","items":{"type":"object"}},"registration_fields_enabled":{"type":"boolean"},"registration_fields":{"type":"array","items":{"type":"object","description":"Registration question. Provide a UUID id when another field or route references it; omit id to let Connections generate one.","properties":{"id":{"type":"string","format":"uuid"},"field_key":{"type":"string","description":"Stable key for answers, for example linkedin or accredited."},"field_type":{"type":"string","description":"Question type such as text, textarea, email, url, yes_no, select, radio, vote, multi_select, checkbox, or link. yes_no/radio are saved as the same choice-field shape the workspace registration builder uses."},"label":{"type":"string"},"helper_text":{"type":"string"},"placeholder":{"type":"string"},"is_required":{"type":"boolean"},"options":{"type":"array","items":{"oneOf":[{"type":"string"},{"type":"object"}]},"description":"Choice options for yes_no/select/radio/vote/multi_select fields. Strings are saved directly; objects use value, then label, then id. For yes/no branching, use the canonical strings Yes and No."},"visibility_field_key":{"type":"string","description":"Show this field only after another field has one of visibility_values."},"visibility_values":{"type":"array","items":{"type":"string"}},"ticket_tier_ids":{"type":"array","items":{"type":"string"},"description":"Product/ticket UUIDs this field routes to or unlocks."},"ticket_tier_routing_rules":{"type":"array","items":{"type":"object"},"description":"Advanced per-answer routing rules."},"sort_order":{"type":"integer"}}}},"registration_flow_edges":{"type":"array","items":{"type":"object","description":"Advanced registration route edge. Use sourceType start/question/ticket and targetType field/tier/end. Legacy sourceId/targetId plus condition.value is accepted, but the full shape matches the workspace builder exactly.","properties":{"sourceType":{"type":"string","enum":["start","question","ticket"]},"sourceId":{"type":"string"},"sourceAnswerValue":{"type":"string","nullable":true,"description":"Answer option for question edges, for example Yes or No. Omit/null for start and ticket edges."},"targetType":{"type":"string","enum":["field","tier","end"]},"targetId":{"type":"string"},"condition":{"type":"object","description":"Legacy shorthand. condition.value is converted into sourceAnswerValue.","deprecated":true}}}},"ticketing_enabled":{"type":"boolean"},"ticket_tiers":{"type":"array","items":{"type":"object","description":"Free or paid product/ticket. Provide a globally unique UUID id when routing references it; omit id to let Connections generate one. Do not reuse sample UUIDs across events.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"price_cents":{"type":"integer","description":"0 for free products."},"currency":{"type":"string","default":"USD"},"quantity_total":{"type":"integer","nullable":true},"visibility":{"type":"string","enum":["public","hidden","internal"],"default":"public"},"sort_order":{"type":"integer"},"stripe_mode":{"type":"string","enum":["platform","imported"],"description":"platform = Connections-created product. imported = product/price from the host connected Stripe account."},"stripe_product_id":{"type":"string","description":"Use for imported Stripe products."},"stripe_price_id":{"type":"string","description":"Use for imported Stripe prices."},"ticket_billing_kind":{"type":"string","enum":["one_time","subscription"]},"billing_interval":{"type":"string","enum":["day","week","month","year","lifetime"],"description":"Use product.defaultPrice.interval from GET /v1/products for imported recurring Stripe prices. Use lifetime for one-time products."},"billing_interval_count":{"type":"integer","default":1,"description":"Use product.defaultPrice.intervalCount from GET /v1/products for imported recurring Stripe prices, for example 4 with billing_interval week."},"metadata":{"type":"object"}}}},"success_message":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}}},"WorkspaceBundleListResponse":{"type":"object","required":["bundles","next_cursor"],"properties":{"bundles":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceBundle"}},"next_cursor":{"type":"string","nullable":true,"description":"Pass as ?cursor= for the next page; null on the last page. A page also ends early at a byte budget, and a single row too big for it is listed alone with its large fields null."}}},"WorkspaceBundleResponse":{"type":"object","required":["bundle"],"properties":{"bundle":{"$ref":"#/components/schemas/WorkspaceBundle"}}},"MyConnectProfile":{"type":"object","description":"MyConnect profile for the current credential. The cards (share_cards, active_share_card_id) are read from the MyConnect plane.","properties":{"id":{"type":"string"},"name":{"type":"string","nullable":true},"handle":{"type":"string","nullable":true},"bio":{"type":"string","nullable":true},"image_url":{"type":"string","nullable":true},"background_image_url":{"type":"string","nullable":true},"share_cards":{"type":"array","items":{"type":"object"}},"active_share_card_id":{"type":"string","nullable":true},"cards_version":{"type":"integer","description":"Pass back as expected_cards_version to save the cards only if unchanged."},"updated_at":{"type":"string","nullable":true}}},"MyConnectResponse":{"type":"object","required":["profile"],"properties":{"profile":{"$ref":"#/components/schemas/MyConnectProfile"}}},"MyConnectWriteInput":{"type":"object","description":"Partial-update payload for the MyConnect profile. Cards are saved through the MyConnect plane (card cap and validation apply).","properties":{"name":{"type":"string"},"handle":{"type":"string"},"bio":{"type":"string"},"image_url":{"type":"string"},"background_image_url":{"type":"string"},"share_cards":{"type":"array","items":{"type":"object"}},"active_share_card_id":{"type":"string","nullable":true},"expected_cards_version":{"type":"integer"}}},"EmailSignature":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"template":{"type":"object"},"rendered_html":{"type":"string","nullable":true},"rendered_text":{"type":"string","nullable":true},"is_default":{"type":"boolean"},"created_at":{"type":"string"},"updated_at":{"type":"string","nullable":true}}},"EmailSignatureListResponse":{"type":"object","required":["emailSignatures","next_cursor"],"properties":{"emailSignatures":{"type":"array","items":{"$ref":"#/components/schemas/EmailSignature"}},"next_cursor":{"type":"string","nullable":true,"description":"Pass as ?cursor= for the next page; null on the last page. A page also ends early at a byte budget, and a single row too big for it is listed alone with its large fields null."}}},"EmailSignatureResponse":{"type":"object","required":["emailSignature"],"properties":{"emailSignature":{"$ref":"#/components/schemas/EmailSignature"}}},"EmailSignatureWriteInput":{"type":"object","description":"Email signature write input. POST requires name.","properties":{"name":{"type":"string"},"template":{"type":"object"},"rendered_html":{"type":"string"},"rendered_text":{"type":"string"},"is_default":{"type":"boolean"}}}}},"security":[{"ApiKey":[]},{"OAuth2":[]}],"paths":{"/me":{"get":{"summary":"Who this credential is","description":"Friendly identity alias of /auth/introspect: returns the same credential introspection document (owner/actor profile IDs, scopes, capabilities, rules) so a key gets the same \"who am I\" answer on every plane (Studio also serves /v1/me).","responses":{"200":{"description":"Credential introspection document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntrospectionResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/introspect":{"get":{"summary":"Introspect the active developer credential","description":"Returns the credential type, owner/actor profile IDs, scopes, capabilities (allowed paths and methods), documentation URLs, accepted auth headers, and developer rules. Call this first to discover what the credential can do without trying each route.","responses":{"200":{"description":"Credential introspection document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntrospectionResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/admin/audit-log":{"get":{"summary":"List admin audit-log entries","description":"Returns recent admin_audit_log rows. Requires admin:read.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"maximum":100}}],"responses":{"200":{"description":"Audit log entries.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLogListResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the admin:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["admin:read"]},{"OAuth2":["admin:read"]}]}},"/contacts":{"get":{"summary":"List contacts","description":"Lists contacts owned by the credential, with tags and relationship signals.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"maximum":100}}],"responses":{"200":{"description":"Contacts visible to the active credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactListResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the contacts:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read"]},{"OAuth2":["contacts:read"]}]},"post":{"summary":"Create contact","description":"Creates a contact owned by the credential. Requires contacts:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactWriteInput"}}}},"responses":{"201":{"description":"Created contact.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the contacts:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:write"]},{"OAuth2":["contacts:write"]},{"memberSession":[]}]}},"/contacts/import":{"post":{"summary":"Batch-import contacts","description":"Runs the SAME dedupe/person-match/provenance pipeline the first-party Google importer uses (app.connections Phase 2). Requires contacts:write and a credential bound to a registered app. Re-POSTing the same externalId converges onto the same contact instead of duplicating it.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportRequest"}}}},"responses":{"201":{"description":"Import summary.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportResponse"}}}},"400":{"description":"Missing/invalid source, empty or oversized contacts array, or an unbound credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the contacts:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"contacts exceeds the per-import cap.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:write"]},{"OAuth2":["contacts:write"]}]}},"/contacts/import-event-guests":{"post":{"summary":"Import an event guest list as contacts","description":"Adds the guests of a host's past event, exported from another event service, to the host's contacts. Nobody on the list is emailed and no guest is linked to anyone else. Rows with no email and no phone are skipped. Re-sending the same list updates the same contacts. Requires contacts:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["platform","contacts"],"properties":{"platform":{"type":"string","description":"Where the list came from (luma, eventbrite, meetup, posh, partiful, other). Lowercase slug."},"contacts":{"type":"array","items":{"$ref":"#/components/schemas/ContactImportRow"},"description":"Up to 5000 rows per call."}}}}}},"responses":{"201":{"description":"Import summary.","content":{"application/json":{"schema":{"type":"object","required":["import"],"properties":{"import":{"type":"object","properties":{"source":{"type":"string","enum":["event_guests"]},"total":{"type":"integer","description":"Rows submitted, including skipped ones."},"imported":{"type":"integer","description":"created + updated."},"created":{"type":"integer"},"updated":{"type":"integer"},"skipped":{"type":"integer","description":"Rows with no email and no phone, plus blank rows."}}}}}}}},"400":{"description":"Missing or invalid platform, or an empty contacts array.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the contacts:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"contacts exceeds the per-import cap.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:write"]},{"OAuth2":["contacts:write"]},{"memberSession":[]}]}},"/contacts/import-own":{"post":{"summary":"Import contacts into your own address book","description":"Adds a batch of contacts to the signed-in member's own address book, through the same dedupe/person-match pipeline every import runs. For the member's own assistant acting with their session or own key; an app imports through POST /contacts/import. A row's externalId is ignored here (there is no app to namespace it under): rows match existing contacts by email and phone. Requires contacts:write.","operationId":"post_contacts_import_own","x-connections-principals":["assistant"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["source","contacts"],"properties":{"source":{"type":"string","pattern":"^[a-z0-9_-]{1,40}$","description":"Where the contacts came from (pasted, google, outlook, linkedin, ...). Lowercase slug."},"contacts":{"type":"array","items":{"$ref":"#/components/schemas/ContactImportRow"},"description":"Up to 5000 rows per call."}}}}}},"responses":{"201":{"description":"Import summary.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportResponse"}}}},"400":{"description":"Missing or invalid source, or an empty contacts array.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The credential is not the member's own session or own key, or is missing the contacts:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"contacts exceeds the per-import cap.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:write"]},{"memberSession":[]}]}},"/contacts/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Contact ID."}],"get":{"summary":"Get contact","responses":{"200":{"description":"Contact returned by ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the contacts:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Contact not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read"]},{"OAuth2":["contacts:read"]},{"memberSession":[]}]},"patch":{"summary":"Update contact","operationId":"patch_contacts_by_id","x-connections-principals":["assistant"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactWriteInput"}}}},"responses":{"200":{"description":"Updated contact.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the contacts:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Contact not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:write"]},{"OAuth2":["contacts:write"]},{"memberSession":[]}]},"delete":{"summary":"Delete contact","description":"Moves the contact to the member's Trash in Connections, with its touches, contact methods, relationships and folder memberships; restoring it from Trash brings all of them back.","responses":{"200":{"description":"Contact moved to Trash: { deleted: true, trashed: true, trashEntryId }.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the contacts:delete scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Contact not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:delete"]},{"OAuth2":["contacts:delete"]}]}},"/contacts/search":{"get":{"summary":"Search contacts","description":"Owner-scoped contact lookup by name, email, phone, or tag: a narrower, agent-friendly sibling of GET /contacts and POST /search. Requires contacts:read.","parameters":[{"name":"q","in":"query","required":false,"description":"Required unless tag is given.","schema":{"type":"string"}},{"name":"tag","in":"query","required":false,"description":"Exact tag name: lists the contacts carrying it (up to 100).","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"maximum":100}}],"responses":{"200":{"description":"Contacts matching the query, owned by the active credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactSearchResponse"}}}},"400":{"description":"Neither q nor tag was given.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the contacts:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read"]},{"OAuth2":["contacts:read"]},{"memberSession":[]}]}},"/contacts/{id}/timeline":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Contact ID."}],"get":{"summary":"Get a contact timeline","description":"That contact's recent relationship touches, owner-scoped. Requires contacts:read and touches:read.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"maximum":100}}],"responses":{"200":{"description":"The contact plus its recent touches.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactTimelineResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the contacts:read or touches:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Contact not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read","touches:read"]},{"OAuth2":["contacts:read","touches:read"]}]}},"/contacts/{id}/calls":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Contact ID."}],"post":{"summary":"Log a recorded call","description":"Puts a recorded phone call on the contact it was with, as a `call` touch that points at the recording in the member’s storage locker. Once per contact and recording: a repeat returns the first touch. The summary fills in once the transcript is ready. Requires touches:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactCallInput"}}}},"responses":{"201":{"description":"The call touch (the existing one when this recording was already logged).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TouchResponse"}}}},"400":{"description":"storage_object_id is missing or not a UUID, or occurred_at is not a timestamp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the touches:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Contact not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["touches:write"]},{"OAuth2":["touches:write"]},{"memberSession":[]}]}},"/contact-folders":{"get":{"summary":"List contact folders and tags","responses":{"200":{"description":"Contact folders visible to the active credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactFolderListResponse"}}}}}}},"/contact-folders/{id}":{"get":{"summary":"Get contact folder","responses":{"200":{"description":"Contact folder returned by ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactFolderResponse"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/touches":{"get":{"summary":"List relationship touches","parameters":[{"name":"contact_id","in":"query","required":false,"schema":{"type":"string"},"description":"Optional contact ID filter."}],"responses":{"200":{"description":"Relationship touches visible to the active credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TouchListResponse"}}}}}},"post":{"summary":"Record a relationship touch","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TouchWriteInput"}}}},"responses":{"201":{"description":"Created relationship touch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TouchResponse"}}}}}}},"/touches/{id}":{"get":{"summary":"Get relationship touch","responses":{"200":{"description":"Relationship touch returned by ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TouchResponse"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/network":{"get":{"summary":"Get your first/second-degree network","description":"The credential owner's confirmed network (first-degree by default, or second-degree with depth=2). Only confirmed identity links are traversed, never probabilistic matcher guesses. Requires graph:read.","parameters":[{"name":"depth","in":"query","required":false,"schema":{"type":"integer","enum":[1,2],"default":1}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"maximum":200}}],"responses":{"200":{"description":"The confirmed network neighborhood rooted at the credential owner.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkNeighborhoodResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the graph:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"This credential has no linked AEGIS identity to scope a network read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["graph:read"]},{"OAuth2":["graph:read"]}]}},"/network/warm-paths":{"get":{"summary":"Find warm-path introductions to a contact","description":"Warmest mutual-connection paths from the credential owner to a target contact in their vault, ranked by relationship strength. Falls back to the first-degree network when the target is not yet linked to a Connections account holder. Requires graph:read and contacts:read.","parameters":[{"name":"to","in":"query","required":true,"schema":{"type":"string"},"description":"Target contact ID (owned by the credential)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"maximum":50}}],"responses":{"200":{"description":"Ranked warm paths (or a first-degree-network fallback) to the target contact.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarmPathsResponse"}}}},"400":{"description":"to (a target contact id) is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the graph:read or contacts:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Contact not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["graph:read","contacts:read"]},{"OAuth2":["graph:read","contacts:read"]}]}},"/search":{"get":{"summary":"Search contacts and relationship memory","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Scoped search results.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}}}},"post":{"summary":"Search contacts and relationship memory","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"query":{"type":"string"},"limit":{"type":"integer"}}}}}},"responses":{"200":{"description":"Scoped search results.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}}}}},"/introduction-requests":{"get":{"summary":"List introduction requests","responses":{"200":{"description":"Consent-preserving introduction requests visible to the active credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntroductionRequestListResponse"}}}}}},"post":{"summary":"Create a pending introduction request","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntroductionRequestWriteInput"}}}},"responses":{"201":{"description":"Created pending introduction request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntroductionRequestResponse"}}}}}}},"/introduction-requests/{id}":{"get":{"summary":"Get introduction request","responses":{"200":{"description":"Consent-preserving introduction request returned by ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntroductionRequestResponse"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/products":{"get":{"summary":"List registration products","description":"Lists active Connections-platform products and products from the connected Stripe account that this workspace can use for imported Stripe tiers or existing-membership bypasses. Requires events:read.","responses":{"200":{"description":"Product catalog visible to the active credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductCatalogResponse"}}}}}}},"/forms":{"get":{"summary":"List forms","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"maximum":100}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"next_cursor from the previous page."}],"responses":{"200":{"description":"Forms visible to the active credential. Newest first; a page ends early once its large fields reach a byte budget, so follow next_cursor until it is null.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceFormListResponse"}}}},"400":{"description":"The cursor was not issued by this endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the forms:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["forms:read"]},{"OAuth2":["forms:read"]}]},"post":{"summary":"Create form","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceFormWriteInput"}}}},"responses":{"201":{"description":"Created form.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceFormResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the forms:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["forms:write"]},{"OAuth2":["forms:write"]}]}},"/forms/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Form ID."}],"get":{"summary":"Get form","responses":{"200":{"description":"Form returned by ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceFormResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the forms:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Form not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["forms:read"]},{"OAuth2":["forms:read"]}]},"patch":{"summary":"Update form","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceFormWriteInput"}}}},"responses":{"200":{"description":"Updated form.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceFormResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the forms:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Form not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["forms:write"]},{"OAuth2":["forms:write"]}]},"delete":{"summary":"Delete form","description":"Moves the form and every submission to the member's Trash in Connections; restoring it from Trash brings both back. A form with more than 5,000 responses answers 409: export them first.","responses":{"200":{"description":"Form moved to Trash: { deleted: true, trashed: true, trashEntryId }.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the forms:delete scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Form not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The form has more responses than Trash can hold; export them, then delete.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["forms:delete"]},{"OAuth2":["forms:delete"]}]}},"/forms/{id}/submissions":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Form ID."}],"get":{"summary":"List form submissions","description":"What respondents answered, newest first, one page at a time. Follow next_cursor until it is null. Reaches only the forms GET /forms returns to the same credential.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"maximum":100}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"next_cursor from the previous page."}],"responses":{"200":{"description":"A page of submissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceFormSubmissionPage"}}}},"400":{"description":"The cursor was not issued by this endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the forms:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Form not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["forms:read"]},{"OAuth2":["forms:read"]}]}},"/bundles":{"get":{"summary":"List bundles","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"maximum":100}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"next_cursor from the previous page."}],"responses":{"200":{"description":"Bundles visible to the active credential. Newest first; a page ends early once its large fields reach a byte budget, so follow next_cursor until it is null.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceBundleListResponse"}}}},"400":{"description":"The cursor was not issued by this endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the bundles:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["bundles:read"]},{"OAuth2":["bundles:read"]}]},"post":{"summary":"Create bundle","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceBundleWriteInput"}}}},"responses":{"201":{"description":"Created bundle.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceBundleResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the bundles:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["bundles:write"]},{"OAuth2":["bundles:write"]}]}},"/bundles/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Bundle ID."}],"get":{"summary":"Get bundle","responses":{"200":{"description":"Bundle returned by ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceBundleResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the bundles:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Bundle not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["bundles:read"]},{"OAuth2":["bundles:read"]}]},"patch":{"summary":"Update bundle","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceBundleWriteInput"}}}},"responses":{"200":{"description":"Updated bundle.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceBundleResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the bundles:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Bundle not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["bundles:write"]},{"OAuth2":["bundles:write"]}]},"delete":{"summary":"Delete bundle","description":"Moves the bundle to the member's Trash in Connections; restoring it from Trash brings it back.","responses":{"200":{"description":"Bundle moved to Trash: { deleted: true, trashed: true, trashEntryId }.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the bundles:delete scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Bundle not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["bundles:delete"]},{"OAuth2":["bundles:delete"]}]}},"/my-connect":{"get":{"summary":"Get My Connect profile","responses":{"200":{"description":"My Connect profile for the current credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyConnectResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the myconnect:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["myconnect:read"]},{"OAuth2":["myconnect:read"]}]},"patch":{"summary":"Update My Connect profile","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyConnectWriteInput"}}}},"responses":{"200":{"description":"Updated My Connect profile.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyConnectResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the myconnect:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["myconnect:write"]},{"OAuth2":["myconnect:write"]}]}},"/email-signatures":{"get":{"summary":"List email signatures","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"maximum":100}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"next_cursor from the previous page."}],"responses":{"200":{"description":"Email signatures visible to the active credential. Newest first; a page ends early once its large fields reach a byte budget, so follow next_cursor until it is null.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSignatureListResponse"}}}},"400":{"description":"The cursor was not issued by this endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the email_signatures:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["email_signatures:read"]},{"OAuth2":["email_signatures:read"]}]},"post":{"summary":"Create email signature","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSignatureWriteInput"}}}},"responses":{"201":{"description":"Created email signature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSignatureResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the email_signatures:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["email_signatures:write"]},{"OAuth2":["email_signatures:write"]}]}},"/email-signatures/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Email signature ID."}],"patch":{"summary":"Update email signature","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSignatureWriteInput"}}}},"responses":{"200":{"description":"Updated email signature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSignatureResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the email_signatures:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Email signature not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["email_signatures:write"]},{"OAuth2":["email_signatures:write"]}]},"delete":{"summary":"Delete email signature","description":"Moves the signature to the member's Trash in Connections; restoring it from Trash brings it back.","responses":{"200":{"description":"Email signature moved to Trash: { deleted: true, trashed: true, trashEntryId }.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the email_signatures:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Email signature not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["email_signatures:write"]},{"OAuth2":["email_signatures:write"]}]}},"/ai-network-search":{"post":{"operationId":"ai_network_search","x-connections-principals":["assistant"],"summary":"AI Network search","description":"Search this member's first-degree network for an introducer to someone matching a natural-language description - \"reveal the introducer, not the target\" (spec §5.1): every result names someone the member already knows (an introducer) paired with a person that introducer could connect them to, with evidence drawn from the introducer's own logged notes. It never returns a stranger's identity directly. DEGRADED-DATA NOTE: `memberReadiness` reflects this member's own activation state and can read as a low/no-signal verdict when their network is too new or too small for a search to be meaningful - report that plainly rather than as \"no results\". Requires a paid tier (personal or higher); a free-tier caller receives 402 tier_required. Rate-limited per member per day, with a stricter cap for personal-sensitive queries; a caller past that cap receives 429.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"query":{"type":"string","description":"The natural-language description of who the member wants to reach."}}}}}},"responses":{"200":{"description":"Ranked introducer/target pairs, or a blocked/degraded verdict - see the description.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Missing/empty query.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"This tier does not include AI Network search.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the graph:read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Daily or burst search rate limit reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["graph:read"]},{"OAuth2":["graph:read"]},{"memberSession":[]}]}},"/agent-tools/draft_contact":{"post":{"operationId":"draft_contact","summary":"Draft Contact","description":"Save a new person to this member's own contacts. Call this when the member tells you about someone they met or want to remember - including in passing prose ('grabbed coffee with Sarah Chen, she runs ops at Northwind, sarah@northwind.co'). Gather what they actually said and propose it; do NOT interrogate them for missing fields, and never invent an email, phone, or employer. The member sees exactly what will be saved and approves it before anything is written, so propose on partial detail rather than asking a second question.","x-agent-tool":"main__draft_contact","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"The person's full name, as the member said it."},"email":{"type":"string","description":"Email address, only if the member actually gave one. Omit otherwise - never guess."},"phone":{"type":"string","description":"Phone number, only if the member actually gave one. Omit otherwise - never guess."},"company":{"type":"string","description":"Employer, if mentioned. Omit when unknown."},"jobTitle":{"type":"string","description":"Role or title, if mentioned. Omit when unknown."},"context":{"type":"string","description":"One or two sentences on who they are and why the member wants to remember them, in the member's own framing. This becomes the note on the contact."},"lastMetLabel":{"type":"string","description":"How or where they met, in a few words ('Coffee at the Northwind offsite'). Omit when the member did not say."}},"required":["name"]}}}},"responses":{"201":{"description":"The write completed - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Missing or invalid arguments.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:write"]},{"OAuth2":["contacts:write"]}]}},"/agent-tools/update_contact_role":{"post":{"operationId":"update_contact_role","summary":"Update Contact Role","description":"Update an existing contact's job title and/or company on this member's own contacts. Call this when the member gives a NEW title or employer for someone already in their contacts - never for a new person (use draft_contact for that). Give at least one of title or company. The member sees exactly what will change and approves it before anything is written.","x-agent-tool":"main__update_contact_role","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contactId":{"type":"string","description":"The id of the existing contact to update."},"title":{"type":"string","description":"Their new role or title. Omit to leave the title unchanged."},"company":{"type":"string","description":"Their new employer. Omit to leave the company unchanged."}},"required":["contactId"]}}}},"responses":{"201":{"description":"The write completed - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Missing or invalid arguments.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:write"]},{"OAuth2":["contacts:write"]}]}},"/agent-tools/list_my_overdue_followups":{"get":{"operationId":"list_my_overdue_followups","summary":"List My Overdue Followups","description":"List the follow-ups this member owes people - the next-step cards they set on their own contacts that are now overdue or due today, oldest first, with how many days late each one is. Call this whenever they ask what they owe anyone, who they are behind on, what is overdue, or what they should clear today. This reads only their own cards and never contacts anyone; naming these people back to them is safe, but never message anyone here without them saying so.","x-agent-tool":"main__list_my_overdue_followups","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"number","description":"How many to return per bucket (default 10, maximum 50). Ask for a small number unless the member wants the whole list."}}],"responses":{"200":{"description":"The tool result - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read"]},{"OAuth2":["contacts:read"]}]}},"/agent-tools/list_contacts_gone_quiet":{"get":{"operationId":"list_contacts_gone_quiet","summary":"List Contacts Gone Quiet","description":"List the people this member asked to keep in touch with but has not spoken to inside the cadence they themselves set, most-important first, with how many days it has been. Call this when they ask who they have lost touch with, who they are neglecting, who they should reconnect with, or who has gone quiet. Only people they explicitly set a check-in cadence on appear here, so this is their own stated intention, not a guess. Read-only - never message anyone here without the member saying so.","x-agent-tool":"main__list_contacts_gone_quiet","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"number","description":"How many to return (default 10, maximum 50). Prefer a small number unless they want the full list."}}],"responses":{"200":{"description":"The tool result - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read"]},{"OAuth2":["contacts:read"]}]}},"/agent-tools/list_upcoming_birthdays":{"get":{"operationId":"list_upcoming_birthdays","summary":"List Upcoming Birthdays","description":"List this member's own contacts whose birthday falls in the next couple of weeks, soonest first. Call this when they ask about upcoming birthdays, whose birthday is coming up, or who they should send something to this month. Only contacts they recorded a birthday for appear. Some entries have a month and day but no year - that means the year was never recorded, not that the age is unknown; say so rather than guessing.","x-agent-tool":"main__list_upcoming_birthdays","parameters":[{"name":"withinDays","in":"query","required":false,"schema":{"type":"number","description":"How far ahead to look, in days (default 14, maximum 90)."}},{"name":"limit","in":"query","required":false,"schema":{"type":"number","description":"How many to return (default 10, maximum 50)."}}],"responses":{"200":{"description":"The tool result - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read"]},{"OAuth2":["contacts:read"]}]}},"/agent-tools/suggest_check_in_cadence":{"get":{"operationId":"suggest_check_in_cadence","summary":"Suggest Check In Cadence","description":"Suggest how often this member should check in with one named contact, derived from the median gap between the conversations they have actually logged with that person, and report the cadence they currently have set. Call this when they ask how often they should talk to someone, whether they are in touch enough, or what a sensible check-in rhythm would be. Returns several matches when the name is ambiguous - ask which one they meant rather than picking. A null suggestion means there is not enough logged history to derive one; say that plainly instead of offering a number.","x-agent-tool":"main__suggest_check_in_cadence","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","description":"The contact's name as the member said it. Partial names are fine."}}],"responses":{"200":{"description":"The tool result - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read"]},{"OAuth2":["contacts:read"]}]}},"/agent-tools/how_am_i_doing_on_followups":{"get":{"operationId":"how_am_i_doing_on_followups","summary":"How Am I Doing On Followups","description":"How the member is doing on the people the product has surfaced to them recently - how many were flagged, how many they have since actually talked to, and who is still waiting. Call this when they ask whether they are keeping up, how they are doing on follow-ups, whether they are getting better, or for a check on their own habits. ⛔ If `hasHistory` is false there is NO baseline yet because the digest has never flagged anyone for them - say 'not enough history yet' and never report that as a zero, a 0%, or 'you are all caught up', which would be a verdict invented from an absent measurement. Read-only.","x-agent-tool":"main__how_am_i_doing_on_followups","parameters":[],"responses":{"200":{"description":"The tool result - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read"]},{"OAuth2":["contacts:read"]}]}},"/agent-tools/list_contacts_who_changed_jobs":{"get":{"operationId":"list_contacts_who_changed_jobs","summary":"List Contacts Who Changed Jobs","description":"List this member's contacts who have changed jobs recently - what role or company they moved from and to, most recent first. Call this when they ask who has moved, who changed jobs, who has a new role, or who is worth congratulating. Only contacts they are confirmed connections with appear, and the change comes from that person's own profile edit, so it is first-party rather than scraped. ⛔ The date is when WE SAW the change, not when they started the role - say 'we saw this recently' or 'they've moved to X', never 'they started on the 3rd', which is a fact we do not have. Read-only; never message anyone here without the member saying so.","x-agent-tool":"main__list_contacts_who_changed_jobs","parameters":[{"name":"withinDays","in":"query","required":false,"schema":{"type":"number","description":"How far back to look (default 90, maximum 365)."}},{"name":"limit","in":"query","required":false,"schema":{"type":"number","description":"How many to return (default 10, maximum 50)."}}],"responses":{"200":{"description":"The tool result - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read","touches:read"]},{"OAuth2":["contacts:read","touches:read"]}]}},"/agent-tools/who_should_i_follow_up_with":{"get":{"operationId":"who_should_i_follow_up_with","summary":"Who Should I Follow Up With","description":"The member's shortlist of people to reach out to today, each with the reason they surfaced - a follow-up that is past due, or a relationship going quiet against the check-in cadence they set. Ranked most-worth-doing first and capped short on purpose; this is a nudge, not the whole board, so `totalCandidates` says how many existed before the cut. Call this when they ask who to contact today, who they are behind on, who they should catch up with, or what their relationship to-dos are. If `noSignalsConfigured` is true the member has no pipeline and no check-in cadences set, so an empty list means there was nothing to look at - say that, never 'you're all caught up'. Read-only.","x-agent-tool":"main__who_should_i_follow_up_with","parameters":[],"responses":{"200":{"description":"The tool result - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read"]},{"OAuth2":["contacts:read"]}]}},"/agent-tools/find_warm_path_to":{"get":{"operationId":"find_warm_path_to","summary":"Find Warm Path To","description":"Find who in this member's own network could introduce them to one named person - the mutual connections they both know, ranked warmest first by how recently and how often the member has actually talked to each mutual. Call this when they ask who can introduce them to someone, how to get to a person, who they know in common, or the warmest way to reach out. If the person is not on Connections there is no path to compute and the result says so; if the name matches several contacts it returns them all and you must ask which one rather than picking. Read-only - it never contacts the mutual or requests the introduction.","x-agent-tool":"main__find_warm_path_to","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","description":"The person to reach, as the member said it. Must be someone already in their contacts."}},{"name":"limit","in":"query","required":false,"schema":{"type":"number","description":"How many routes to return (default 10, maximum 50)."}}],"responses":{"200":{"description":"The tool result - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["graph:read","contacts:read"]},{"OAuth2":["graph:read","contacts:read"]}]}},"/agent-tools/get_relationship_strength":{"get":{"operationId":"get_relationship_strength","summary":"Get Relationship Strength","description":"Report how strong this member's tie to one named contact is - none, light, moderate or strong - and when they last interacted. Call this when they ask how close they are to someone, how well they know them, whether the relationship is warm, or where it stands. Returns several matches when the name is ambiguous; ask which one they meant rather than picking. A contact can come back unscored, which means the tie has never been scored, NOT that it scored zero - say so rather than reporting a weak relationship.","x-agent-tool":"main__get_relationship_strength","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","description":"The contact's name as the member said it. Partial names are fine."}}],"responses":{"200":{"description":"The tool result - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read"]},{"OAuth2":["contacts:read"]}]}},"/agent-tools/get_recent_interactions":{"get":{"operationId":"get_recent_interactions","summary":"Get Recent Interactions","description":"Return the most recent conversations this member logged with one named contact, newest first, with what each one was and when. Call this when they ask what they last talked about with someone, when they last spoke, what they discussed, or to catch up before reaching out again. Only interactions the member themselves logged appear - an empty result means nothing was recorded, not that nothing happened, so never tell them they have not spoken to someone.","x-agent-tool":"main__get_recent_interactions","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","description":"The contact's name as the member said it. Partial names are fine."}},{"name":"limit","in":"query","required":false,"schema":{"type":"number","description":"How many recent interactions per matched contact (default 5, maximum 25). Keep it small - bodies are long."}}],"responses":{"200":{"description":"The tool result - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read","touches:read"]},{"OAuth2":["contacts:read","touches:read"]}]}},"/agent-tools/list_contacts_to_reconnect_with":{"get":{"operationId":"list_contacts_to_reconnect_with","summary":"List Contacts To Reconnect With","description":"List the people this member has real history with but never set a check-in cadence for - the relationships quietly going untended - ranked by how much history there actually is, each with a suggested cadence. Call this when they ask who they should be keeping up with, who is worth tracking, who they are letting slide, or who to add to their follow-up routine. This is the complement of list_contacts_gone_quiet, which covers people they already track. Read-only.","x-agent-tool":"main__list_contacts_to_reconnect_with","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"number","description":"How many to return (default 10, maximum 50)."}}],"responses":{"200":{"description":"The tool result - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read"]},{"OAuth2":["contacts:read"]}]}},"/agent-tools/resolve_contact":{"get":{"operationId":"resolve_contact","summary":"Resolve Contact","description":"Work out which ONE of this member's own contacts a person or company name means, before acting on that person. Matches in tiers - exact name or email, then the name with accents, punctuation and 'Last, First' order ignored (or an exact company), then a partial match, then a close spelling - and stops at the first tier that finds anyone. Read `outcome`: 'resolved' means exactly one exact match, so use `contact`; 'ambiguous' means several matched, so list `candidates` and ask which they meant; 'confirm' means only a partial or near spelling matched, so ask 'did you mean <name>?' and NEVER act on it unconfirmed; 'none' means no contact matches, so say so rather than guessing. `matchedOn` says whether the name, email or company matched. If `scanComplete` is false the read stopped at its bound, so a 'none' means not found among the contacts read, never that the person is absent. Read-only.","x-agent-tool":"main__resolve_contact","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","description":"The person's name, email or company exactly as the member said it."}}],"responses":{"200":{"description":"The tool result - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:read"]},{"OAuth2":["contacts:read"]}]}},"/agent-tools/enrich_contact":{"post":{"operationId":"enrich_contact","summary":"Enrich Contact","description":"Fill in a contact from the member's own data provider keys (work email, phone, title, company, LinkedIn), cheapest vendor first, stopping at the first real answer. Results arrive as suggestions the member reviews on the contact; nothing is overwritten. A phone is looked up only when capabilities includes phone_find.","x-agent-tool":"main__enrich_contact","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contact_id":{"type":"string","description":"The id of the member's own contact to fill in."},"capabilities":{"type":"array","items":{"type":"string","enum":["person_enrich","email_find","phone_find","email_verify"]},"description":"Which lookups to run. Omit for profile, email and email check. Add phone_find only when the member wants a phone."}},"required":["contact_id"]}}}},"responses":{"201":{"description":"The write completed - the same JSON object the chat brain receives calling this tool internally.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Missing or invalid arguments.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Credential is missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"ApiKey":["contacts:write"]},{"OAuth2":["contacts:write"]}]}}}}