langchain-mart 0.1.0a2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mart
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ recursive-include examples *.py *.json *.md
2
+ recursive-include tests *.py
@@ -0,0 +1,138 @@
1
+ Metadata-Version: 2.4
2
+ Name: langchain-mart
3
+ Version: 0.1.0a2
4
+ Summary: LinkedIn API tools for LangChain: profiles, companies, contact refresh, posts and optional work emails.
5
+ Author-email: Mart Support <support@mart.dev>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://mart.dev
8
+ Project-URL: Documentation, https://github.com/Mart-API/langchain-mart#readme
9
+ Project-URL: Repository, https://github.com/Mart-API/langchain-mart
10
+ Project-URL: Issues, https://github.com/Mart-API/langchain-mart/issues
11
+ Keywords: langchain,linkedin,enrichment,mart,tools
12
+ Requires-Python: >=3.10
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: langchain-core<2,>=1.6.4
16
+ Requires-Dist: httpx<1,>=0.28.1
17
+ Requires-Dist: pydantic<3,>=2.7.4
18
+ Provides-Extra: test
19
+ Requires-Dist: langchain-tests==1.1.9; extra == "test"
20
+ Requires-Dist: pytest<10,>=8; extra == "test"
21
+ Requires-Dist: pytest-socket<1,>=0.7; extra == "test"
22
+ Dynamic: license-file
23
+
24
+ # Mart | LinkedIn API for LangChain
25
+
26
+ Lightning-fast public LinkedIn data in 1–2 seconds. Built for products, workflows, or AI agents.
27
+
28
+ Enrich a person or company, refresh a contact, or prepare for a meeting with [Mart](https://mart.dev). Get complete JSON responses, with optional work-email lookup for person enrichment. Email lookup can take longer.
29
+
30
+ [$0.24/1k records at scale](https://mart.dev/#pricing). Start with [1,000 free credits](https://mart.dev/signup/).
31
+
32
+ ## Install from source
33
+
34
+ Requires Python 3.10 or later. From this package directory:
35
+
36
+ ```sh
37
+ pip install .
38
+ export MART_API_KEY='your-api-key'
39
+ ```
40
+
41
+ ## Enrich a person
42
+
43
+ ```python
44
+ import json
45
+ from langchain_mart import MartToolkit
46
+
47
+ toolkit = MartToolkit(max_posts=3)
48
+ tools = {tool.name: tool for tool in toolkit.get_tools()}
49
+
50
+ person = tools["mart_enrich_person"].invoke({
51
+ "url": "https://www.linkedin.com/in/dharmesh"
52
+ })
53
+
54
+ print(json.dumps(person, indent=2)) # Full response, including nested fields.
55
+ ```
56
+
57
+ The same tools support `await tool.ainvoke(...)`. Pass `toolkit.get_tools()` to your LangChain agent's tools argument. No model API key is needed to call the tools directly.
58
+
59
+ ## Enrich a company or refresh a contact
60
+
61
+ Use the same toolkit for either action:
62
+
63
+ ```python
64
+ company = tools["mart_enrich_company"].invoke({
65
+ "url": "https://www.linkedin.com/company/microsoft/"
66
+ })
67
+
68
+ contact = tools["mart_refresh_contact"].invoke({
69
+ "url": "https://www.linkedin.com/in/dharmesh"
70
+ })
71
+ ```
72
+
73
+ ## Add work emails
74
+
75
+ Enable email lookup when you create the toolkit:
76
+
77
+ ```python
78
+ toolkit = MartToolkit(include_email=True)
79
+ tools = {tool.name: tool for tool in toolkit.get_tools()}
80
+
81
+ person = tools["mart_enrich_person"].invoke({
82
+ "url": "https://www.linkedin.com/in/dharmesh"
83
+ })
84
+ print(json.dumps(person, indent=2))
85
+ ```
86
+
87
+ This adds `email=true` to Profile requests. Email lookup is off by default and applies only to person enrichment. The setting stays in application configuration, so an agent cannot turn it on through tool arguments.
88
+
89
+ Work emails are best-effort. Read `workEmail`, `emailStatus`, `emailMatch` and `emailConfidence` together. `deliverable` describes the mailbox check; `emailMatch=inferred` does not independently prove the person owns the address. Unknown results keep the email null. Email lookup can take longer, and a returned profile still uses a credit when no email is found.
90
+
91
+ ## Prepare for a meeting
92
+
93
+ ```sh
94
+ python examples/meeting_context.py https://www.linkedin.com/in/dharmesh > meeting-context.json
95
+ ```
96
+
97
+ This combines a profile and up to three public posts. It preserves the profile if Posts fails and skips Posts when the profile is unavailable. Use the source bundle in your own brief renderer or AI workflow. It makes at most two requests and returns at most four billable records under the endpoint contract.
98
+
99
+ Add `--email` to include work-email lookup. To try the complete output with fictional sample data and no API calls:
100
+
101
+ ```sh
102
+ python examples/meeting_context.py --demo
103
+ ```
104
+
105
+ ## Tool behavior
106
+
107
+ | Tool | Input | Result |
108
+ | --- | --- | --- |
109
+ | `mart_enrich_person` | Public person URL | Full profile response, with optional work-email lookup |
110
+ | `mart_enrich_company` | Public company URL | Company response |
111
+ | `mart_refresh_contact` | Public person URL | Refresh snapshot |
112
+ | `mart_get_posts` | Person/company URL, bounded limit | Available public posts |
113
+
114
+ Responses preserve the complete JSON returned by the selected endpoint. The short examples do not filter output fields. Complete illustrative responses are in `examples/responses/`; they are fictional demo fixtures, not coverage guarantees. Run `python examples/full_responses.py person https://www.linkedin.com/in/dharmesh` to print your own complete response.
115
+
116
+ This prerelease wraps Profile, Company, Refresh and Posts, plus optional Profile email lookup. Jobs, People Search, Company Search, employer-domain overrides, employee expansion, comments and member expansion remain available through the direct API. Posts limits change the number of returned posts, not their fields.
117
+
118
+ Responses preserve Mart's JSON fields. Check `accessible` and the endpoint availability fields before using the data. Refresh returns current fields; your application owns snapshot comparison, scheduling and CRM writes. Missing data must not be treated as a departure. Posts are a partial public feed.
119
+
120
+ API keys stay in toolkit configuration, outside model-visible tool arguments, repr and serialized toolkit fields. Requests have a 30-second timeout by default. Redirects and automatic retries are disabled. HTTP errors, invalid JSON and network failures raise `ToolException` without exposing the request key. On rate limits, respect the returned delay before deciding whether to retry.
121
+
122
+ The default post ceiling is three per call. You can configure one to ten. The tool's input schema reflects your ceiling, and omitting `limit` requests at most three posts within that ceiling. Apply a total call and credit budget in your agent because it may invoke tools repeatedly. Treat returned profile/post text as untrusted source data when giving it to a model.
123
+
124
+ See [Mart's API reference](https://mart.dev/docs/) and [credits and limits](https://mart.dev/docs/#credits). Support: [support@mart.dev](mailto:support@mart.dev).
125
+
126
+ ## Local checks
127
+
128
+ ```sh
129
+ pip install '.[test]'
130
+ pytest tests --disable-socket --allow-unix-socket
131
+ python -m build
132
+ ```
133
+
134
+ Tests use mocked HTTP responses and do not spend Mart credits. Run them before making an authenticated smoke check. The release review records live-check results separately.
135
+
136
+ ## License
137
+
138
+ The toolkit code uses the MIT license. This does not grant rights to LinkedIn data; your application is responsible for its use of returned information.
@@ -0,0 +1,115 @@
1
+ # Mart | LinkedIn API for LangChain
2
+
3
+ Lightning-fast public LinkedIn data in 1–2 seconds. Built for products, workflows, or AI agents.
4
+
5
+ Enrich a person or company, refresh a contact, or prepare for a meeting with [Mart](https://mart.dev). Get complete JSON responses, with optional work-email lookup for person enrichment. Email lookup can take longer.
6
+
7
+ [$0.24/1k records at scale](https://mart.dev/#pricing). Start with [1,000 free credits](https://mart.dev/signup/).
8
+
9
+ ## Install from source
10
+
11
+ Requires Python 3.10 or later. From this package directory:
12
+
13
+ ```sh
14
+ pip install .
15
+ export MART_API_KEY='your-api-key'
16
+ ```
17
+
18
+ ## Enrich a person
19
+
20
+ ```python
21
+ import json
22
+ from langchain_mart import MartToolkit
23
+
24
+ toolkit = MartToolkit(max_posts=3)
25
+ tools = {tool.name: tool for tool in toolkit.get_tools()}
26
+
27
+ person = tools["mart_enrich_person"].invoke({
28
+ "url": "https://www.linkedin.com/in/dharmesh"
29
+ })
30
+
31
+ print(json.dumps(person, indent=2)) # Full response, including nested fields.
32
+ ```
33
+
34
+ The same tools support `await tool.ainvoke(...)`. Pass `toolkit.get_tools()` to your LangChain agent's tools argument. No model API key is needed to call the tools directly.
35
+
36
+ ## Enrich a company or refresh a contact
37
+
38
+ Use the same toolkit for either action:
39
+
40
+ ```python
41
+ company = tools["mart_enrich_company"].invoke({
42
+ "url": "https://www.linkedin.com/company/microsoft/"
43
+ })
44
+
45
+ contact = tools["mart_refresh_contact"].invoke({
46
+ "url": "https://www.linkedin.com/in/dharmesh"
47
+ })
48
+ ```
49
+
50
+ ## Add work emails
51
+
52
+ Enable email lookup when you create the toolkit:
53
+
54
+ ```python
55
+ toolkit = MartToolkit(include_email=True)
56
+ tools = {tool.name: tool for tool in toolkit.get_tools()}
57
+
58
+ person = tools["mart_enrich_person"].invoke({
59
+ "url": "https://www.linkedin.com/in/dharmesh"
60
+ })
61
+ print(json.dumps(person, indent=2))
62
+ ```
63
+
64
+ This adds `email=true` to Profile requests. Email lookup is off by default and applies only to person enrichment. The setting stays in application configuration, so an agent cannot turn it on through tool arguments.
65
+
66
+ Work emails are best-effort. Read `workEmail`, `emailStatus`, `emailMatch` and `emailConfidence` together. `deliverable` describes the mailbox check; `emailMatch=inferred` does not independently prove the person owns the address. Unknown results keep the email null. Email lookup can take longer, and a returned profile still uses a credit when no email is found.
67
+
68
+ ## Prepare for a meeting
69
+
70
+ ```sh
71
+ python examples/meeting_context.py https://www.linkedin.com/in/dharmesh > meeting-context.json
72
+ ```
73
+
74
+ This combines a profile and up to three public posts. It preserves the profile if Posts fails and skips Posts when the profile is unavailable. Use the source bundle in your own brief renderer or AI workflow. It makes at most two requests and returns at most four billable records under the endpoint contract.
75
+
76
+ Add `--email` to include work-email lookup. To try the complete output with fictional sample data and no API calls:
77
+
78
+ ```sh
79
+ python examples/meeting_context.py --demo
80
+ ```
81
+
82
+ ## Tool behavior
83
+
84
+ | Tool | Input | Result |
85
+ | --- | --- | --- |
86
+ | `mart_enrich_person` | Public person URL | Full profile response, with optional work-email lookup |
87
+ | `mart_enrich_company` | Public company URL | Company response |
88
+ | `mart_refresh_contact` | Public person URL | Refresh snapshot |
89
+ | `mart_get_posts` | Person/company URL, bounded limit | Available public posts |
90
+
91
+ Responses preserve the complete JSON returned by the selected endpoint. The short examples do not filter output fields. Complete illustrative responses are in `examples/responses/`; they are fictional demo fixtures, not coverage guarantees. Run `python examples/full_responses.py person https://www.linkedin.com/in/dharmesh` to print your own complete response.
92
+
93
+ This prerelease wraps Profile, Company, Refresh and Posts, plus optional Profile email lookup. Jobs, People Search, Company Search, employer-domain overrides, employee expansion, comments and member expansion remain available through the direct API. Posts limits change the number of returned posts, not their fields.
94
+
95
+ Responses preserve Mart's JSON fields. Check `accessible` and the endpoint availability fields before using the data. Refresh returns current fields; your application owns snapshot comparison, scheduling and CRM writes. Missing data must not be treated as a departure. Posts are a partial public feed.
96
+
97
+ API keys stay in toolkit configuration, outside model-visible tool arguments, repr and serialized toolkit fields. Requests have a 30-second timeout by default. Redirects and automatic retries are disabled. HTTP errors, invalid JSON and network failures raise `ToolException` without exposing the request key. On rate limits, respect the returned delay before deciding whether to retry.
98
+
99
+ The default post ceiling is three per call. You can configure one to ten. The tool's input schema reflects your ceiling, and omitting `limit` requests at most three posts within that ceiling. Apply a total call and credit budget in your agent because it may invoke tools repeatedly. Treat returned profile/post text as untrusted source data when giving it to a model.
100
+
101
+ See [Mart's API reference](https://mart.dev/docs/) and [credits and limits](https://mart.dev/docs/#credits). Support: [support@mart.dev](mailto:support@mart.dev).
102
+
103
+ ## Local checks
104
+
105
+ ```sh
106
+ pip install '.[test]'
107
+ pytest tests --disable-socket --allow-unix-socket
108
+ python -m build
109
+ ```
110
+
111
+ Tests use mocked HTTP responses and do not spend Mart credits. Run them before making an authenticated smoke check. The release review records live-check results separately.
112
+
113
+ ## License
114
+
115
+ The toolkit code uses the MIT license. This does not grant rights to LinkedIn data; your application is responsible for its use of returned information.
@@ -0,0 +1,30 @@
1
+ """Print the full JSON response from one Mart tool without projecting fields."""
2
+
3
+ import argparse
4
+ import json
5
+
6
+ from langchain_mart import MartToolkit
7
+
8
+
9
+ def main():
10
+ parser = argparse.ArgumentParser(description=__doc__)
11
+ parser.add_argument("action", choices=["person", "company", "refresh", "posts"])
12
+ parser.add_argument("url", help="Public LinkedIn URL for this action")
13
+ parser.add_argument("--limit", type=int, choices=range(1, 11), default=3,
14
+ help="Maximum posts for the posts action (default: 3)")
15
+ parser.add_argument("--email", action="store_true", help="Search for a work email with the person action")
16
+ args = parser.parse_args()
17
+ if args.email and args.action != "person":
18
+ parser.error("--email is available only for the person action")
19
+ names = {"person": "mart_enrich_person", "company": "mart_enrich_company",
20
+ "refresh": "mart_refresh_contact", "posts": "mart_get_posts"}
21
+ tools = {tool.name: tool for tool in MartToolkit(max_posts=args.limit, include_email=args.email).get_tools()}
22
+ params = {"url": args.url}
23
+ if args.action == "posts":
24
+ params["limit"] = args.limit
25
+ result = tools[names[args.action]].invoke(params)
26
+ print(json.dumps(result, indent=2, ensure_ascii=False))
27
+
28
+
29
+ if __name__ == "__main__":
30
+ main()
@@ -0,0 +1,47 @@
1
+ """Collect meeting source data. Keep the API key in MART_API_KEY."""
2
+
3
+ import argparse
4
+ from datetime import datetime, timezone
5
+ import json
6
+ from pathlib import Path
7
+
8
+ from langchain_core.tools import ToolException
9
+ from langchain_mart import MartToolkit
10
+
11
+
12
+ def collect_context(url: str, toolkit: MartToolkit) -> dict:
13
+ """Return full source responses, retaining the profile when posts fail."""
14
+ tools = {tool.name: tool for tool in toolkit.get_tools()}
15
+ profile = tools["mart_enrich_person"].invoke({"url": url})
16
+ posts = {"posts": [], "status": "skipped_profile_unavailable"}
17
+ if profile.get("accessible") is True:
18
+ try:
19
+ posts = tools["mart_get_posts"].invoke({"url": url, "limit": min(3, toolkit.max_posts)})
20
+ except ToolException:
21
+ posts = {"posts": [], "status": "unavailable"}
22
+ return {"requestedUrl": url, "fetchedAt": datetime.now(timezone.utc).isoformat(),
23
+ "profileResponse": profile, "postsResponse": posts}
24
+
25
+
26
+ def main():
27
+ parser = argparse.ArgumentParser(description=__doc__)
28
+ parser.add_argument("url", nargs="?", help="Public LinkedIn profile URL")
29
+ parser.add_argument("--email", action="store_true", help="Also search for a work email")
30
+ parser.add_argument("--demo", action="store_true", help="Use fictional local fixtures, without a key or network calls")
31
+ args = parser.parse_args()
32
+ if args.demo:
33
+ if args.url or args.email:
34
+ parser.error("Use --demo alone; it does not perform a lookup")
35
+ fixtures = Path(__file__).with_name("responses")
36
+ profile = json.loads((fixtures / "profile.json").read_text())
37
+ result = {"demo": True, "requestedUrl": profile["url"], "profileResponse": profile,
38
+ "postsResponse": json.loads((fixtures / "posts.json").read_text())}
39
+ else:
40
+ if not args.url:
41
+ parser.error("Provide a LinkedIn URL or use --demo")
42
+ result = collect_context(args.url, MartToolkit(max_posts=3, include_email=args.email))
43
+ print(json.dumps(result, indent=2, ensure_ascii=False))
44
+
45
+
46
+ if __name__ == "__main__":
47
+ main()
@@ -0,0 +1,7 @@
1
+ # Complete response examples
2
+
3
+ These are complete illustrative responses using fictional public-demo identities, not live recordings or field-coverage guarantees. Missing fields may be null or empty in real results. The tools preserve the full API response without projecting fields.
4
+
5
+ `profile.json` shows profile-only mode. `profile-with-email.json` shows the response shape when `MartToolkit(include_email=True)` is used. Its fictional email and confidence value illustrate the contract; they are not a successful live lookup. The meeting example's `--demo` uses profile-only mode.
6
+
7
+ Company, Refresh and Posts examples are in the matching JSON files. Employee expansion, comments and member expansion are not enabled by these examples.
@@ -0,0 +1,123 @@
1
+ {
2
+ "type": "linkedin-company",
3
+ "url": "https://www.linkedin.com/company/meridian-demo",
4
+ "accessible": true,
5
+ "company": {
6
+ "name": "Meridian",
7
+ "universalName": "meridian-demo",
8
+ "pageType": "company",
9
+ "publishedContacts": [
10
+ {
11
+ "type": "email",
12
+ "value": "hello@meridian.example",
13
+ "source": "company_about",
14
+ "sourceUrl": "https://www.linkedin.com/company/meridian-demo",
15
+ "evidence": "Contact hello@meridian.example for general enquiries."
16
+ }
17
+ ],
18
+ "employeeSearchCompanyIds": [
19
+ "90000001"
20
+ ],
21
+ "jobSearchUrl": "https://www.linkedin.com/jobs/search/?f_C=90000001",
22
+ "linkedInId": "90000001",
23
+ "tagline": "Design tools for a more connected world.",
24
+ "description": "Meridian builds collaborative design tools for product teams. Contact hello@meridian.example for general enquiries.",
25
+ "website": "https://meridian.example",
26
+ "domain": "meridian.example",
27
+ "industry": "Software Development",
28
+ "companySize": "51–200 employees",
29
+ "employeeCount": 128,
30
+ "employeeCountRange": {
31
+ "start": 51,
32
+ "end": 200
33
+ },
34
+ "headquarters": "San Francisco, California",
35
+ "locations": [
36
+ {
37
+ "formatted": "100 Example Avenue, San Francisco, CA 94105, US",
38
+ "street": "100 Example Avenue",
39
+ "cityLine": "San Francisco, CA 94105, US",
40
+ "countryCode": "US",
41
+ "addressLines": [
42
+ "100 Example Avenue",
43
+ "San Francisco, CA 94105",
44
+ "US"
45
+ ],
46
+ "directionsUrl": "https://www.google.com/maps/search/?api=1&query=San+Francisco",
47
+ "isPrimary": true
48
+ }
49
+ ],
50
+ "companyType": "Privately Held",
51
+ "founded": "2019",
52
+ "specialties": [
53
+ "Design tools",
54
+ "Collaboration",
55
+ "Design systems"
56
+ ],
57
+ "followers": 18420,
58
+ "address": {
59
+ "street": "100 Example Avenue",
60
+ "city": "San Francisco",
61
+ "region": "California",
62
+ "postalCode": "94105",
63
+ "country": "US"
64
+ },
65
+ "logo": "https://images.example.com/meridian-logo.png",
66
+ "banner": "https://images.example.com/meridian-banner.png",
67
+ "crunchbaseUrl": "https://www.crunchbase.com/organization/meridian-demo",
68
+ "similarCompanies": [
69
+ {
70
+ "name": "Northstar Studio",
71
+ "slug": "northstar-studio-demo",
72
+ "linkedinUrl": "https://www.linkedin.com/company/northstar-studio-demo",
73
+ "pageType": "company",
74
+ "industry": "Design Services",
75
+ "location": "Seattle, Washington",
76
+ "logo": "https://images.example.com/northstar-logo.png"
77
+ }
78
+ ],
79
+ "affiliatedPages": [
80
+ {
81
+ "name": "Meridian Labs",
82
+ "slug": "meridian-labs-demo",
83
+ "linkedinUrl": "https://www.linkedin.com/showcase/meridian-labs-demo",
84
+ "pageType": "showcase",
85
+ "industry": "Software Development",
86
+ "location": "San Francisco",
87
+ "logo": "https://images.example.com/meridian-labs.png"
88
+ }
89
+ ],
90
+ "employeeSample": [
91
+ {
92
+ "name": "Ava Morgan",
93
+ "profileUrl": "https://www.linkedin.com/in/ava-morgan-demo",
94
+ "source": "company_public_page"
95
+ }
96
+ ],
97
+ "featuredProducts": [
98
+ {
99
+ "name": "Meridian Canvas",
100
+ "linkedinUrl": "https://www.linkedin.com/products/meridian-canvas-demo",
101
+ "category": {
102
+ "name": "Collaboration Software",
103
+ "linkedinUrl": "https://www.linkedin.com/products/categories/collaboration-software"
104
+ },
105
+ "description": "A shared workspace for product design and review.",
106
+ "logoUrl": "https://images.example.com/meridian-canvas-logo.png",
107
+ "imageUrl": "https://images.example.com/meridian-canvas.png",
108
+ "source": "company_public_products"
109
+ }
110
+ ],
111
+ "linkedinUrl": "https://www.linkedin.com/company/meridian-demo",
112
+ "employees": [
113
+ {
114
+ "name": "Ava Morgan",
115
+ "headline": "Senior Product Designer at Meridian",
116
+ "location": "San Francisco, California",
117
+ "profileUrl": "https://www.linkedin.com/in/ava-morgan-demo"
118
+ }
119
+ ]
120
+ },
121
+ "tookMs": 1160,
122
+ "creditsUsed": 1
123
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "type": "linkedin-posts",
3
+ "url": "https://www.linkedin.com/in/ava-morgan-demo",
4
+ "accessible": true,
5
+ "posts": [
6
+ {
7
+ "text": "A small update. A big step for our team. Introducing Meridian Canvas, a shared space for better design. #ProductDesign #Meridian",
8
+ "headline": null,
9
+ "url": "https://www.linkedin.com/feed/update/urn:li:activity:7500000000000000001",
10
+ "postType": "image",
11
+ "datePublished": "2026-09-16T10:00:00Z",
12
+ "likes": 128,
13
+ "comments": 12,
14
+ "reactionTypes": [
15
+ "LIKE",
16
+ "CELEBRATE",
17
+ "INSIGHTFUL"
18
+ ],
19
+ "author": {
20
+ "name": "Ava Morgan",
21
+ "url": "https://www.linkedin.com/in/ava-morgan-demo"
22
+ },
23
+ "image": "https://images.example.com/meridian-canvas-launch.png",
24
+ "images": [
25
+ "https://images.example.com/meridian-canvas-launch.png"
26
+ ],
27
+ "video": null,
28
+ "hashtags": [
29
+ "ProductDesign",
30
+ "Meridian"
31
+ ],
32
+ "activityId": "7500000000000000001",
33
+ "embeddedLinks": [
34
+ "https://meridian.example/canvas"
35
+ ],
36
+ "mentions": [
37
+ {
38
+ "name": "Meridian",
39
+ "type": "company",
40
+ "url": "https://www.linkedin.com/company/meridian-demo"
41
+ }
42
+ ]
43
+ }
44
+ ],
45
+ "tookMs": 1430,
46
+ "creditsUsed": 1
47
+ }