skills/integrations/attio/attio-connect/SKILL.md
Manage contacts, notes, and lists in Attio CRM. Use when user says: 'add contact', 'update CRM', 'attio', 'create note', 'search contacts', 'add to list', 'look up in CRM', 'manage contacts', or references the Personal CRM project.
npx skillsauth add beam-ai-team/beam-next-skills attio-connectInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Create, read, update, and manage contacts, notes, and lists in Attio CRM via the REST API v2.
| Action | Endpoint | Method |
|--------|----------|--------|
| Create/update person | /v2/objects/people/records | PUT (assert) |
| Create person | /v2/objects/people/records | POST |
| Get person | /v2/objects/people/records/{id} | GET |
| Search people | /v2/objects/people/records/query | POST |
| Create note | /v2/notes | POST |
| List notes | /v2/notes | GET |
| List attributes | /v2/objects/people/attributes | GET |
| Create attribute | /v2/objects/people/attributes | POST |
| Create select option | /v2/objects/people/attributes/{attr}/options | POST |
| List all lists | /v2/lists | GET |
| Create list | /v2/lists | POST |
| Add to list | /v2/lists/{list_id}/entries | POST |
| Query list entries | /v2/lists/{list_id}/entries/query | POST |
Base URL: https://api.attio.com
Auth: Authorization: Bearer $ATTIO_API_KEY
API Key Location: 02-projects/Personal/projects/04-personal-crm/.env
The most important endpoint. Creates a new person OR updates an existing one, matched by email.
When to use: Adding a contact, importing from another source, updating stale data.
curl -X PUT "https://api.attio.com/v2/objects/people/records?matching_attribute=email_addresses" \
-H "Authorization: Bearer $ATTIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": {
"values": {
"email_addresses": ["[email protected]"],
"name": [{ "first_name": "Jane", "last_name": "Smith", "full_name": "Jane Smith" }],
"job_title": ["Staff Engineer"],
"description": ["Met at YC dinner 2024, works on AI infra"],
"linkedin": ["https://linkedin.com/in/janesmith"],
"twitter": ["@janesmith"],
"primary_location": [{
"locality": "San Francisco",
"region": "California",
"country_code": "US"
}],
"CUSTOM_ATTRIBUTE_SLUG": ["value"]
}
}
}'
Key points:
matching_attribute is a query parameter (not in the body)name requires full_name field alongside first_name/last_namelinkedin (not linkedin_url)avatar_url cannot be set via APICustom attributes use their slug (e.g., relationship_type, proximity_tier). Discover slugs with the List Attributes endpoint.
Find contacts by filtering on any attribute.
curl -X POST https://api.attio.com/v2/objects/people/records/query \
-H "Authorization: Bearer $ATTIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filter": {
"name": { "contains": "Jane" }
},
"sorts": [
{ "attribute": "name", "field": "last_name", "direction": "asc" }
],
"limit": 25,
"offset": 0
}'
Filter examples:
// Filter by custom select attribute
{ "ATTRIBUTE_SLUG": { "contains": "value" } }
// Filter by email
{ "email_addresses": { "contains": "[email protected]" } }
Pagination: Use limit and offset. Response includes next_page_offset if more results.
curl -X GET https://api.attio.com/v2/objects/people/records/{record_id} \
-H "Authorization: Bearer $ATTIO_API_KEY"
Rich text notes attached to a person record.
curl -X POST https://api.attio.com/v2/notes \
-H "Authorization: Bearer $ATTIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": {
"parent_object": "people",
"parent_record_id": "RECORD_ID",
"title": "Meeting Notes - Feb 2026",
"format": "plaintext",
"content": "Discussed AI infrastructure roadmap. Jane is interested in Beam for document processing automation. Follow up in 2 weeks with demo."
}
}'
Note fields:
parent_object: "people" or "companies"parent_record_id: The record ID to attach the note totitle: Note titleformat: "plaintext" or "html"content: The note bodycurl -X GET "https://api.attio.com/v2/notes?parent_object=people&parent_record_id=RECORD_ID" \
-H "Authorization: Bearer $ATTIO_API_KEY"
Run this first to learn what custom attributes exist and their slugs.
curl -X GET https://api.attio.com/v2/objects/people/attributes \
-H "Authorization: Bearer $ATTIO_API_KEY"
Returns all attributes on the People object with their:
api_slug — use this in API callstitle — human-readable nametype — text, select, number, date, etc.is_multiselect — true/falseconfig.options — for select/status attributes, the available optionscurl -X POST https://api.attio.com/v2/objects/people/attributes \
-H "Authorization: Bearer $ATTIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": {
"title": "Relationship Type",
"api_slug": "relationship_type",
"type": "select",
"is_multiselect": true
}
}'
Attribute types: text, number, checkbox, currency, date, timestamp, select, status, rating, location, domain, email-address, phone-number, record-reference
After creating a select attribute, add its options:
curl -X POST https://api.attio.com/v2/objects/people/attributes/relationship_type/options \
-H "Authorization: Bearer $ATTIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": {
"title": "Investor"
}
}'
Repeat for each option (Customer, Founder/Peer, Team, Advisor, Friend, Date).
List all lists:
curl -X GET https://api.attio.com/v2/lists \
-H "Authorization: Bearer $ATTIO_API_KEY"
Create a new list:
curl -X POST https://api.attio.com/v2/lists \
-H "Authorization: Bearer $ATTIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": {
"name": "Weekly Ping Queue",
"parent_object": "people",
"workspace_access": "full-access"
}
}'
Add a person to a list:
curl -X POST https://api.attio.com/v2/lists/{list_id}/entries \
-H "Authorization: Bearer $ATTIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": {
"parent_record_id": "RECORD_ID",
"attribute_values": {
"ATTRIBUTE_SLUG": "value"
}
}
}'
Query list entries:
curl -X POST https://api.attio.com/v2/lists/{list_id}/entries/query \
-H "Authorization: Bearer $ATTIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filter": {},
"limit": 50
}'
These are the custom attributes to create for the Personal CRM (see plan.md):
| Attribute | Slug | Type | Options |
|-----------|------|------|---------|
| Relationship Type | relationship_type | multi-select | Investor, Customer, Founder/Peer, Team, Advisor, Friend, Date |
| Status | crm_status | select | Active, Prospect, Dormant, Stale |
| Proximity Tier | proximity_tier | select | T1-Inner Circle, T2-Active, T3-Warm, T4-Network, T5-Archive |
| Relationship Quality | relationship_quality | select | ⭐ High, Neutral, 🚩 Low |
| Source | contact_source | multi-select | LinkedIn, WhatsApp, Instagram, Notion, Event, Intro, Google |
| City | city_tags | multi-select | Berlin, Munich, SF, NYC, London, Dubai |
| Context | context_tags | multi-select | Beam, YC, University, Hyrox, Conference |
| Special | special_tags | multi-select | Bridge, Aspirational, Lifeline, Dormant-Reconnect |
| Attribute | Slug | Type |
|-----------|------|------|
| Connection Story | connection_story | text |
| How Can I Help | how_can_i_help | text |
| Last Interaction | last_interaction | date |
| Last Helped | last_helped | date |
| List | Parent Object | Purpose | |------|---------------|---------| | Weekly Ping Queue | People | Contacts to reach out to this week | | Dormant Reconnect | People | High-value dormant ties to re-engage | | Aspirational | People | People to build relationships with |
1. Assert person (PUT /v2/objects/people/records)
- Set: name, email, phone, linkedin, company, title, location
- Set: relationship_type, crm_status, proximity_tier, relationship_quality
- Set: connection_story, how_can_i_help, contact_source, city_tags, context_tags
- Set: last_interaction = today
2. Create note (POST /v2/notes)
- Add detailed context: how you met, topics discussed, personal details
3. Add to list if applicable (POST /v2/lists/{list_id}/entries)
- Weekly Ping Queue if T1-T2
- Aspirational if they're a target connection
1. Query people (POST /v2/objects/people/records/query)
- Filter by proximity_tier + city_tags = "T1 friends in Berlin"
- Filter by relationship_type + crm_status = "Active investors"
- Filter by special_tags = "Bridge contacts"
- Sort by last_interaction (ascending) = "Who haven't I talked to recently?"
1. Research via happenstance-connect (get current job, company, etc.)
2. Update person (PUT /v2/objects/people/records, match by email)
- Update: job_title, company, location
- Set: crm_status from "Stale" to "Active"
- Set: last_interaction = today
3. Add note: "Updated info via Happenstance on [date]. Was at [old company], now at [new company]."
1. Query Weekly Ping Queue list entries
2. For each entry, get the parent person record
3. Check: How Can I Help? Last Interaction? Connection Story?
4. After sending pings, update: last_interaction, last_helped
5. Remove from queue (or mark done)
| Status | Meaning | Action | |--------|---------|--------| | 400 | Bad request | Check payload format, attribute slugs | | 401 | Unauthorized | Check API key | | 403 | Forbidden | Check token scopes or billing plan | | 404 | Not found | Check record_id, list_id, attribute slug | | 409 | Conflict | Record with same unique attribute exists — use assert (PUT) instead of create (POST) | | 422 | Validation error | Check attribute types and values | | 429 | Rate limited | Back off and retry |
"people" for this CRMnext_page_offsethappenstance-connect — Search/research people before adding to Attiolead-research — Full lead research workflow using Attio as destinationtesting
Audit registry.yaml against disk, validate SKILL.md frontmatter, find duplicates and orphans. Load when user says 'audit skills registry', 'validate beam-next-skills', 'registry drift', 'skills catalog audit', 'check registry yaml'.
tools
All Workable ATS operations — fetch JDs, search candidates, post assessments/reviews. Load when user says "fetch JD", "search workable", "push to workable", "post review", "rate candidate", "workable", "push assessment", "list jobs", or after interview-coach completes an evaluation. Replaces workable-fetch-jd and workable-push-assessment.
data-ai
Load when user mentions "tavily research", "market intelligence", "competitive research", "GTM research", or needs real-time market data for sales, marketing, or vertical strategy.
development
Shared resource library for Slack integration skills. DO NOT load directly - provides common references (setup, API docs, error handling, authentication) and scripts used by slack-connect and individual Slack skills.