{"id":"af71a283-3e59-414f-8009-09a45ab9ee72","entityType":"agent","slug":"clawhub-nts-signalhire-skill","name":"The SignalHire skill integrates the full SignalHire API into OpenClaw, enabling you to search for prospects and enrich their contact details without leaving your workflow. It exposes three core actions: a credits check, a search-by-query for prospecting, ","canonicalUrl":"https://www.xpersona.co/agent/clawhub-nts-signalhire-skill","canonicalPath":"/agent/clawhub-nts-signalhire-skill","generatedAt":"2026-10-10T03:22:13.238Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T09:14:21.709Z","emptyReason":null},"description":"Interact with the SignalHire API to enrich and verify professional contacts. Use this skill when asked to find email addresses, phone numbers, or search for professional profiles and companies using SignalHire. Supports Person API for comprehensive profile/contact data and Search API for lead genera","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 3.2K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s1734hwesw25qg9zgm62rgbyfx8en03g:signalhire-skill","sourceUrl":"https://clawhub.ai/nts/signalhire-skill","homepage":"https://clawhub.ai/nts/skills/signalhire-skill","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/nts/signalhire-skill","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/nts/skills/signalhire-skill","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":70,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"The SignalHire skill integrates the full SignalHire API into OpenClaw, enabling you to search for prospects and enrich their contact details without leaving you"},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T09:14:21.709Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T09:14:21.709Z","emptyReason":null},"stars":null,"forks":null,"downloads":3188,"packageName":null,"latestVersion":"1.0.1","tractionLabel":"3.2K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T09:14:21.709Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T09:14:21.709Z","lastCrawledAt":"2026-10-09T09:14:21.709Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T09:14:21.709Z","lastVerifiedAt":null,"highlights":[{"version":"1.0.1","createdAt":"2026-09-18T20:38:19.090Z","changelog":"Removed: README.md and connector code Skill-card documentation Detailed rate limits, concurrency rules, and credits compliance sections Replaced: The full operational SKILL.md was swapped for a concise guide focused on three things: API endpoints, authentication, and callback setup Added: The minimal Flask webhook example is now the canonical callback setup reference — inline in SKILL.md, no external docs needed","fileCount":3,"zipByteSize":4109},{"version":"1.0.0","createdAt":"2026-02-04T09:55:03.542Z","changelog":"The SignalHire skill integrates the full SignalHire API into OpenClaw, enabling you to search for prospects and enrich their contact details without leaving your workflow. It exposes three core actions: a credits check, a search-by-query for prospecting, and an asynchronous contact enrichment call. The credits check invokes SignalHire’s /api/v1/credits endpoint to report how many credits you have left, while the search action uses the searchByQuery endpoint to filter candidates by title, location, industry and other fields. Access to the search API requires contacting SignalHire and is limited to three concurrent requests. The enrichment action calls the Person API (/api/v1/candidate/search) with up to 100 identifiers and a callback URL. SignalHire returns results asynchronously to your callback; your server must reply with HTTP 200 within a 10‑second window or SignalHire will retry and eventually discard the request. Each callback object includes a status (success, failed, credits_are_over, timeout_exceeded or duplicate_query) and, on success, a candidate with fields like fullName, emails, phones and locations. The skill includes a small Flask connector that listens on the callback endpoint, writes results into per‑job and consolidated CSV files, and exposes a job-status API so your agent knows when to proceed.","fileCount":6,"zipByteSize":11398}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s1734hwesw25qg9zgm62rgbyfx8en03g:signalhire-skill","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s1734hwesw25qg9zgm62rgbyfx8en03g:signalhire-skill` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/nts/signalhire-skill before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-nts-signalhire-skill/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-nts-signalhire-skill/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-nts-signalhire-skill/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-nts-signalhire-skill/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-nts-signalhire-skill/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-nts-signalhire-skill/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T03:22:13.237Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-nts-signalhire-skill/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-nts-signalhire-skill/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-nts-signalhire-skill/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-nts-signalhire-skill/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T09:14:21.709Z","emptyReason":null},"readme":"Skill: The SignalHire skill integrates the full SignalHire API into OpenClaw, enabling you to search for prospects and enrich their contact details without leaving your workflow. It exposes three core actions: a credits check, a search-by-query for prospecting, and an asynchronous contact enrichment call\n\nOwner: nts\n\nSummary: Interact with the SignalHire API to enrich and verify professional contacts. Use this skill when asked to find email addresses, phone numbers, or search for professional profiles and companies using SignalHire. Supports Person API for comprehensive profile/contact data and Search API for lead genera\n\nTags: latest:1.0.1\n\nVersion history:\n\nv1.0.1 | 2026-09-18T20:38:19.090Z | user\n\nRemoved:\n\nREADME.md and connector code\nSkill-card documentation\nDetailed rate limits, concurrency rules, and credits compliance sections\n\nReplaced:\n\nThe full operational SKILL.md was swapped for a concise guide focused on three things: API endpoints, authentication, and callback setup\n\nAdded:\n\nThe minimal Flask webhook example is now the canonical callback setup reference — inline in SKILL.md, no external docs needed\n\nv1.0.0 | 2026-02-04T09:55:03.542Z | user\n\nThe SignalHire skill integrates the full SignalHire API into OpenClaw, enabling you to search for prospects and enrich their contact details without leaving your workflow. It exposes three core actions: a credits check, a search-by-query for prospecting, and an asynchronous contact enrichment call. The credits check invokes SignalHire’s /api/v1/credits endpoint to report how many credits you have left, while the search action uses the searchByQuery endpoint to filter candidates by title, location, industry and other fields. Access to the search API requires contacting SignalHire and is limited to three concurrent requests.\n\nThe enrichment action calls the Person API (/api/v1/candidate/search) with up to 100 identifiers and a callback URL. SignalHire returns results asynchronously to your callback; your server must reply with HTTP 200 within a 10‑second window or SignalHire will retry and eventually discard the request. Each callback object includes a status (success, failed, credits_are_over, timeout_exceeded or duplicate_query) and, on success, a candidate with fields like fullName, emails, phones and locations. The skill includes a small Flask connector that listens on the callback endpoint, writes results into per‑job and consolidated CSV files, and exposes a job-status API so your agent knows when to proceed.\n\nArchive index:\n\nArchive v1.0.1: 3 files, 4109 bytes\n\nFiles: skill-card.md (2236b), SKILL.md (5596b), _meta.json (135b)\n\nFile v1.0.1:SKILL.md\n\n---\nname: signalhire\ndescription: Interact with the SignalHire API to enrich and verify professional contacts. Use this skill when asked to find email addresses, phone numbers, or search for professional profiles and companies using SignalHire. Supports Person API for comprehensive profile/contact data and Search API for lead generation.\n---\n\n# SignalHire API Skill\n\nThis skill provides context and instructions for using the SignalHire API to retrieve contact information (emails, phone numbers, social media profiles) from a global database of professionals.\n\n## Authentication\nTo access the SignalHire API, an API key is required. The API key must be included in the `apikey` request header.\n\nIf the user hasn't provided their SignalHire API key in their request or environment, ask them to provide it before making API calls. Ensure it is kept secure and not exposed publicly.\n\n## Endpoints\n\n### 1. Person API\nRetrieves comprehensive profile and full contact details about a specific individual based on unique identifiers (e.g., LinkedIn® profile links, email addresses, phone numbers, or ID).\n- **Use Case:** Find a specific person's contact info.\n- **Rate Limit:** 600 items per minute.\n- **Callback URL:** The Person API is asynchronous — SignalHire POSTs the result to a callback URL you provide. See **Callback Setup** below.\n\n### 2. Search API\nSearches for individuals or companies using various filters (e.g., job title, location, industry). Returns a brief overview of information **without** contact details.\n- **Use Case:** Lead generation, talent acquisition, market research.\n- **Rate Limit:** 1 concurrent request.\n\n---\n\n## Callback Setup\n\nThe Person API is asynchronous: you submit a request with a `callbackUrl`, and SignalHire POSTs the enriched result to that URL when ready.\n\n### Requirements\n- A publicly reachable HTTPS endpoint that accepts POST requests with JSON body.\n- A **shared secret** in the callback URL as a query parameter (e.g. `?k=<secret>`), because SignalHire controls the outbound request and cannot set custom headers.\n\n### Step 1 — Deploy a webhook receiver\nYou need an HTTP server that:\n1. Accepts `POST /signalhire/callback?k=<secret>`\n2. Validates the `k` parameter against your stored secret\n3. Saves the JSON payload to a known file (e.g. `signalhire_result.json`) so the agent can read it back\n\nA minimal Flask example:\n```python\nimport hmac, os\nfrom flask import Flask, request, jsonify\nimport json\n\napp = Flask(__name__)\nSECRET = os.environ[\"SIGNALHIRE_WEBHOOK_SECRET\"]\n\n@app.before_request\ndef auth():\n    if request.method == \"POST\":\n        k = request.args.get(\"k\", \"\")\n        if not hmac.compare_digest(k, SECRET):\n            return jsonify({\"error\": \"unauthorized\"}), 403\n\n@app.route(\"/signalhire/callback\", methods=[\"POST\"])\ndef callback():\n    payload = request.get_json()\n    with open(\"signalhire_result.json\", \"w\") as f:\n        json.dump(payload, f, indent=2)\n    return jsonify({\"status\": \"accepted\"}), 200\n\nif __name__ == \"__main__\":\n    app.run(host=\"127.0.0.1\", port=8000)\n```\n\n### Step 2 — Generate a shared secret\n```bash\npython3 -c \"import secrets; print(secrets.token_urlsafe(32))\"\n```\nStore this value as `SIGNALHIRE_WEBHOOK_SECRET` in your server's environment.\n\n### Step 3 — Set `SIGNALHIRE_CALLBACK_URL`\nConstruct the full callback URL including the secret:\n```\nhttps://<your-domain>/signalhire/callback?k=<your-secret>\n```\nStore it as the environment variable `SIGNALHIRE_CALLBACK_URL`, or in a config file your agent reads. **Never hardcode it in source files** — rotate the secret by updating it in one place.\n\nExample (shell / `.env` file):\n```\nSIGNALHIRE_CALLBACK_URL=https://your-domain.com/signalhire/callback?k=your-secret-here\nSIGNALHIRE_WEBHOOK_SECRET=your-secret-here\n```\n\n### Step 4 — Use it in requests\nRead `SIGNALHIRE_CALLBACK_URL` from the environment at runtime and pass it as `callbackUrl` in every Person API request body. Do **not** hardcode the URL.\n\n```python\nimport os\ncallback_url = os.environ[\"SIGNALHIRE_CALLBACK_URL\"]\n```\n\n### Step 5 — Read the result\nAfter submitting the enrichment request, poll or wait for `signalhire_result.json` to be written by your webhook server, then read and return the data to the user.\n\n---\n\n## Handling Responses & Credits\n\n### Credits\nThe HTTP response headers provide the total remaining credits in the `X-Credits-Left` header. Always keep track of this if possible and alert the user if they are running low.\n\n### Common HTTP Status Codes\n- **200**: Request is completed successfully, data collected.\n- **201**: Request is accepted, server started collecting data.\n- **204**: Request is still in progress.\n- **401**: Authentication failed (invalid API key).\n- **402**: Out of credit limit.\n- **403**: Account disabled or querying unauthorized request status.\n- **406**: Requested more than the maximum allowed items (limit is 100).\n- **422**: Incorrect or malformed parameters.\n- **429**: Rate limit exceeded.\n\n## Execution Pattern\nWhen the user asks you to search for a contact or company using SignalHire:\n1. Verify you have the `apikey`.\n2. Determine if the goal is enrichment (Person API) or discovery (Search API).\n3. For Person API: read `SIGNALHIRE_CALLBACK_URL` from the environment; if unset, prompt the user to complete Callback Setup above before proceeding.\n4. Use the `exec` tool to run a `curl` or `fetch` script passing the `apikey` header (`-H \"apikey: $API_KEY\"`) and the `callbackUrl` in the request body.\n5. Wait for the callback to arrive, then read `signalhire_result.json` and return the findings to the user cleanly.\n\nFile v1.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn776naxw6eehs7q16s8b9yh5d8091xn\",\n  \"slug\": \"signalhire-skill\",\n  \"version\": \"1.0.1\",\n  \"publishedAt\": 1789763899090\n}\n\nFile v1.0.1:skill-card.md\n\n## Description:\n\nThe SignalHire skill guides agents in using the SignalHire API to search professional profiles and companies, enrich contact details, and handle asynchronous callback-based results.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[nts](https://clawhub.ai/user/nts)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to search for prospects or companies and request contact enrichment through SignalHire. It is intended for workflows that have a legitimate SignalHire account and a lawful basis for handling personal contact data.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill handles personal contact data returned by SignalHire.\n\nMitigation: Use it only with a legitimate SignalHire account and a lawful basis for contact lookup, and avoid unnecessary storage or sharing of enrichment results.\n\nRisk: Callback-based enrichment can expose webhook endpoints and callback secrets.\n\nMitigation: Prefer a presecured callback service, validate shared secrets, use HTTPS, and rotate callback secrets when exposure is suspected.\n\nRisk: API keys and callback URLs may be exposed through shell commands, logs, or command history.\n\nMitigation: Keep credentials in environment variables or a managed secret store and avoid echoing sensitive values into logs or persistent command history.\n\n## Reference(s):\n\n- [ClawHub SignalHire Skill Page](https://clawhub.ai/nts/skills/signalhire-skill)\n\n## Skill Output:\n\n**Output Type(s):** [guidance, markdown, code, shell commands, configuration]\n\n**Output Format:** [Markdown guidance with inline Python, shell, and environment configuration examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include API request instructions, callback setup steps, status handling guidance, and notes about remaining credits.]\n\n## Skill Version(s):\n\n1.0.1 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.0.0: 6 files, 11398 bytes\n\nFiles: connector/__init__.py (340b), connector/main.py (9476b), README.md (6486b), skill-card.md (2006b), SKILL.md (7170b), _meta.json (135b)\n\nFile v1.0.0:SKILL.md\n\n---\nname: signalhire\ndescription: Prospect and enrich contacts via the SignalHire API (Search, Person and Credits)\nmetadata:\n  openclaw:\n    # The skill only loads when a valid API key and callback URL are provided.  The\n    # primary environment variable is used to inject the secret without ever\n    # exposing it in the instructions.  The callback URL should point to the\n    # connector service exposed publicly via a tunnel or reverse proxy.\n    requires:\n      env: SIGNALHIRE_API_KEY,SIGNALHIRE_CALLBACK_URL\n    primaryEnv: SIGNALHIRE_API_KEY\n---\n\n# SignalHire skill instructions\n\nThis skill exposes three high‑level capabilities to an OpenClaw agent.  Each\ncapability corresponds to one of the REST endpoints documented by SignalHire.\nThe agent should never call these endpoints directly; instead it must invoke\none of the defined skill actions.  The following guidance summarises how the\nAPI works, including rate limits, concurrency limits and the asynchronous\ncallback workflow.  All factual statements below are supported by the official\nSignalHire API documentation.\n\n## 1. Check remaining credits\n\nUse this action to determine how many credits remain on the account.  The\nSignalHire API exposes a dedicated endpoint `GET /api/v1/credits` which returns\nthe number of available credits as a JSON payload.  A valid API key must be\nincluded in the request headers.  When invoked successfully, the response\ncontains a field called `credits` with the number of credits remaining【821841938681143†L505-L529】.  If the\naccount is configured for “profiles without contacts”, the same endpoint can\nbe called with a `withoutContacts=true` query parameter【821841938681143†L559-L566】.  Credits are also\nreturned in the `X-Credits-Left` response header for every Person API call【821841938681143†L559-L566】.\n\nThe agent **must call this action** before launching large enrichment jobs to\navoid running out of credits mid‑operation.  If the number of remaining\ncredits is lower than the number of items to be enriched, the job should be\nsplit or aborted gracefully.\n\n## 2. Search for profiles\n\nUse this action to find prospective candidates in the SignalHire database\nwithout consuming contact credits.  The Search API endpoint is\n`POST /api/v1/candidate/searchByQuery`【21055727237259†L100-L109】 and returns a list of profile summaries\nalong with a `scrollId`.  The scrollId can be used to fetch additional pages\nvia the Scroll Search endpoint (not shown here) until all results are\nexhausted.  Access to the Search API is granted only after contacting\nSignalHire support and is subject to a strict concurrency limit of **three\nsimultaneous requests**【21055727237259†L110-L116】.  The agent must ensure that no more than three\nsearchByQuery calls are inflight at any time.\n\nWhen performing a search, the request body should include fields such as\n`currentTitle`, `location`, `keywords`, `industry` and other filters as\ndescribed in the documentation【21055727237259†L120-L177】.  The `size` parameter controls how many\nprofiles are returned per page (default 10, maximum 100).  After retrieving the\nfirst page, the agent should immediately follow up with a scroll request\nwithin 15 seconds to avoid expiration of the `scrollId`.  The response from\nsearch is synchronous and will return immediately; no callback is needed.\n\n## 3. Enrich contacts (Person API)\n\nThis action retrieves full contact information (emails, phones and social\nprofiles) for up to 100 items per request.  The endpoint is\n`POST /api/v1/candidate/search`【821841938681143†L126-L134】.  Each item may be a LinkedIn profile URL,\nan email address, a phone number or a SignalHire profile UID【821841938681143†L120-L124】.  The\nrequest body **must** include a `callbackUrl` parameter; once the data is\nprocessed the API posts the results to this URL【821841938681143†L126-L134】.  A valid server\nlistening on the callbackUrl must return HTTP status 200 to acknowledge\nsuccessful receipt.  SignalHire retries up to three times if the callback\nendpoint cannot be reached or if it does not respond within a ten‑second\ntimeout【821841938681143†L187-L198】.  Processing is complete only when all callback payloads have\nbeen received.\n\nThe callback payload contains an array of objects, each with a `status` field\nindicating the outcome for that item: `success`, `failed`, `credits_are_over`,\n`timeout_exceeded` or `duplicate_query`【821841938681143†L239-L249】.  When the status is\n`success`, the payload also includes a `candidate` object with fields such as\n`fullName`, `emails`, `phones`, `location`, etc.  These results are\npersisted by the connector service into a CSV file; the agent should wait\nuntil the connector reports that the job is ready before consuming the data.\n\nThe Person API is subject to rate limits: a maximum of **600 elements\nprocessed per minute**【821841938681143†L490-L503】.  The agent must implement throttling to ensure that the\ncombined number of items in all Person API calls does not exceed this limit.\nRequests exceeding the limit will be rejected with HTTP status 429\n`Too Many Requests`【821841938681143†L500-L503】.  To maximise throughput, batch up to 100 items per\nrequest but do not exceed the global per‑minute quota.\n\n## General guidance for agents\n\n1. **Do not hard‑code the API key or callback URL.**  Use the environment\n   variables injected by OpenClaw: `SIGNALHIRE_API_KEY` for authentication and\n   `SIGNALHIRE_CALLBACK_URL` for the Person API.  These values are supplied at\n   runtime and must not be echoed or leaked.\n\n2. **Always check remaining credits** before starting a large enrichment job.\n   Abort or split the job if credits are insufficient.\n\n3. **Respect rate and concurrency limits.**  No more than three concurrent\n   Search API requests【21055727237259†L110-L116】.  Do not send more than 600 items through the\n   Person API per minute【821841938681143†L490-L503】.  Implement exponential backoff on HTTP 429\n   responses.\n\n4. **Always include a valid callbackUrl** when calling the Person API and\n   ensure the connector service is reachable and responsive.  The callback\n   must return HTTP 200 within ten seconds or the result may be discarded【821841938681143†L187-L198】.\n\n5. **Wait for job completion**.  After submitting a Person API request, the\n   agent should poll the connector’s job endpoint (described in the README)\n   until it indicates that all results have been received.  Only then should\n   the agent proceed to process the CSV data.\n\n6. **Handle all status values** from the callback.  For `failed`, `credits_are_over`,\n   `timeout_exceeded` and `duplicate_query`, no candidate data will be\n   available; log these cases and move on.\n\n7. **Comply with legal and privacy requirements.**  SignalHire ties API usage to\n   their Terms, Privacy and GDPR pages.  Always respect data‑subject rights\n   and opt‑out requests when storing or using contact data【821841938681143†L559-L566】.\n\nBy following the above instructions, the agent can safely integrate SignalHire’s\nprospecting and enrichment capabilities into an OpenClaw workflow.\n\nFile v1.0.0:README.md\n\n# SignalHire OpenClaw skill\n\nThis repository contains everything needed to run a complete SignalHire\nintegration as an OpenClaw skill.  It includes a concise set of agent\ninstructions (`SKILL.md`) and a small **connector** service that handles\nasynchronous callbacks from the SignalHire Person API.  The connector writes\nresults into CSV files on the local filesystem so you can import them into\nyour CRM or analysis pipeline.\n\n## Prerequisites\n\n* **Operating system:** Ubuntu or any Linux distribution with Python 3.8+.\n* **Python packages:** The connector depends on `flask` only.  Install it with\n  `pip install flask`.\n* **Environment variables:**\n  * `SIGNALHIRE_API_KEY` – your SignalHire API key.  Required for all API\n    calls.\n  * `SIGNALHIRE_CALLBACK_URL` – a publicly reachable HTTPS endpoint that\n    forwards to the local connector.  SignalHire posts results to this\n    address after processing Person API requests.  It must respond with HTTP\n    status 200 within ten seconds to be considered successful【821841938681143†L187-L198】.\n  * `SIGNALHIRE_OUTPUT_DIR` – the directory where CSV files will be written.\n    Defaults to `./data/signalhire` if not set.\n\nYou will also need a way to expose your local connector to the internet.  A\nfree Cloudflare Tunnel is the simplest option: it creates a secure public URL\nand forwards requests to your local machine without opening firewall ports.\n\n## Running the connector\n\n1. **Install dependencies:**\n\n   ```bash\n   python3 -m pip install flask\n   ```\n\n2. **Start the connector:**\n\n   ```bash\n   export SIGNALHIRE_OUTPUT_DIR=/opt/openclaw/data/signalhire\n   python3 -m signalhire.connector.main --port 8787\n   ```\n\n   The connector listens on the port you specify (default 8787) and exposes\n   two endpoints:\n\n   * `POST /signalhire/callback` – receives callback payloads from\n     SignalHire.  It writes or appends rows to a CSV file named\n     `results_<requestId>.csv` in the output directory.  The callback\n     endpoint must be mapped to your public `SIGNALHIRE_CALLBACK_URL` (e.g.,\n     via a Cloudflare Tunnel or reverse proxy).  SignalHire will retry up\n     to three times if the callback fails or times out【821841938681143†L187-L198】.\n   * `GET /signalhire/jobs/<requestId>` – returns a JSON object describing\n     whether the job has produced any rows and how many.  Once the row\n     count matches the number of items you submitted, the job is ready and\n     the CSV can be processed.\n\n3. **Expose the callback:**\n\n   If you use Cloudflare Tunnel, run something like:\n\n   ```bash\n   cloudflared tunnel run my-signalhire\n   # This prints a public URL such as https://red-example.trycloudflare.com\n   ```\n\n   Set `SIGNALHIRE_CALLBACK_URL` to `https://red-example.trycloudflare.com/signalhire/callback`.\n\n## CSV output schema\n\nThe connector writes one CSV per Person API request.  A consolidated\n`results_all.csv` is also maintained in the same directory.  Each row in the\nCSV includes the following fields:\n\n| column          | description |\n|-----------------|-------------|\n| `request_id`    | Unique ID returned by the Person API and sent back in the callback header【821841938681143†L200-L208】. |\n| `input_type`    | Type of the input: `linkedin`, `email`, `phone` or `uid`. |\n| `input_value`   | The identifier you requested. |\n| `status`        | One of `success`, `failed`, `credits_are_over`, `timeout_exceeded` or `duplicate_query`【821841938681143†L239-L249】. |\n| `full_name`     | Candidate’s full name (empty if status is not `success`). |\n| `title`         | Current job title (if available). |\n| `company_name`  | Current company (if available). |\n| `location`      | Candidate’s primary location. |\n| `linkedin_url`  | LinkedIn profile URL (if present). |\n| `emails`        | Semicolon‑separated list of email addresses. |\n| `phones`        | Semicolon‑separated list of phone numbers. |\n| `source`        | Always set to `signalhire`. |\n| `received_at_utc` | Timestamp when the callback was processed. |\n\nThe per‑request CSV is named `results_<requestId>.csv`, where `<requestId>`\ncomes from the Person API response.  A global file `results_all.csv` is\nupdated with every callback for convenience.\n\n## Usage in an OpenClaw workflow\n\n1. **Agent loads the skill:** When OpenClaw starts, it reads `SKILL.md`.  If\n   `SIGNALHIRE_API_KEY` and `SIGNALHIRE_CALLBACK_URL` are present in the\n   environment, the skill is enabled and the agent can call its actions.\n\n2. **Check credits:** The agent calls `signalhire_check_credits` to determine\n   how many credits remain【821841938681143†L505-L529】.  If the account has too few credits for the\n   upcoming job, it should warn the user or split the job.\n\n3. **Search:** To identify prospects without spending credits, the agent\n   invokes `signalhire_search_by_query` with filters such as job title,\n   location and keywords【21055727237259†L120-L177】.  Only three concurrent search requests are\n   allowed【21055727237259†L110-L116】, so the agent must throttle itself.  The search action returns a\n   list of UIDs or LinkedIn URLs that can be passed to the Person API.\n\n4. **Enrich:** The agent invokes `signalhire_enrich_contacts` with up to 100\n   identifiers and waits for a `requestId` response【821841938681143†L126-L134】.  The agent then polls\n   `GET /signalhire/jobs/<requestId>` until the CSV is ready.  Once ready,\n   the agent reads the CSV from disk and uses it to populate leads in your\n   downstream system.\n\n5. **Respect rate limits:** Do not submit more than 600 items per minute\n   through the Person API【821841938681143†L490-L503】 and no more than three concurrent Search API\n   requests【21055727237259†L110-L116】.  Implement exponential backoff on HTTP 429 responses.\n\n## Legal and privacy considerations\n\nSignalHire ties API usage to its Terms, Privacy Policy and GDPR pages.\nRetrieved contact information must be handled responsibly and used only for\nlegitimate purposes.  Always honour opt‑out and removal requests.  The\ndocumentation emphasises the importance of a valid callback server and a\nprompt 200 OK response to avoid data loss【821841938681143†L187-L198】.\n\n## Contact\n\nFor more information about the SignalHire API, please refer to the official\ndocumentation at <https://www.signalhire.com/api/person>.  If you require\nassistance integrating this skill into your OpenClaw deployment, please open\nan issue or contact your system administrator.\n\nFile v1.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn776naxw6eehs7q16s8b9yh5d8091xn\",\n  \"slug\": \"signalhire-skill\",\n  \"version\": \"1.0.0\",\n  \"publishedAt\": 1770198903542\n}\n\nFile v1.0.0:skill-card.md\n\n## Description:\n\nProspect and enrich contacts via the SignalHire API (Search, Person and Credits).\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[ms-youssef](https://clawhub.ai/user/ms-youssef)\n\n### License/Terms of Use:\n\n\n## Use Case:\n\nExternal users and developers use this skill in OpenClaw to check SignalHire credits, search for prospects, and enrich contact details through asynchronous callbacks and CSV output.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The connector exposes public callback and status endpoints for enrichment jobs.\n\nMitigation: Deploy only in a controlled environment and protect the callback route with a secret, signature validation, rate limits, schema validation, and restricted public routing.\n\nRisk: The connector stores enriched contact data in plaintext CSV files.\n\nMitigation: Store output in a locked-down directory, define retention and deletion rules, and treat CSV files as sensitive personal data before opening or importing them.\n\n## Reference(s):\n\n- [SignalHire API documentation](https://www.signalhire.com/api/person)\n- [ClawHub skill page](https://clawhub.ai/ms-youssef/skills/signalhire-skill)\n- [ClawHub publisher profile](https://clawhub.ai/user/ms-youssef)\n\n## Skill Output:\n\n**Output Type(s):** [guidance, shell commands, configuration, code, API calls, CSV files]\n\n**Output Format:** [Markdown guidance with inline shell commands, JSON API responses, and CSV output files]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Requires SIGNALHIRE_API_KEY and SIGNALHIRE_CALLBACK_URL; generated CSV files may contain sensitive contact data.]\n\n## Skill Version(s):\n\n1.0.0 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.","readmeExcerpt":"Skill: The SignalHire skill integrates the full SignalHire API into OpenClaw, enabling you to search for prospects and enrich their contact details without leaving your workflow. It exposes three core actions: a credits check, a search-by-query for prospecting, and an asynchronous contact enrichment call Owner: nts Summary: Interact with the SignalHire API to enrich and verify professional contacts. Use this skill wh","codeSnippets":[],"executableExamples":[{"language":"python","snippet":"import hmac, os\nfrom flask import Flask, request, jsonify\nimport json\n\napp = Flask(__name__)\nSECRET = os.environ[\"SIGNALHIRE_WEBHOOK_SECRET\"]\n\n@app.before_request\ndef auth():\n    if request.method == \"POST\":\n        k = request.args.get(\"k\", \"\")\n        if not hmac.compare_digest(k, SECRET):\n            return jsonify({\"error\": \"unauthorized\"}), 403\n\n@app.route(\"/signalhire/callback\", methods=[\"POST\"])\ndef callback():\n    payload = request.get_json()\n    with open(\"signalhire_result.json\", \"w\") as f:\n        json.dump(payload, f, indent=2)\n    return jsonify({\"status\": \"accepted\"}), 200\n\nif __name__ == \"__main__\":\n    app.run(host=\"127.0.0.1\", port=8000)"},{"language":"bash","snippet":"python3 -c \"import secrets; print(secrets.token_urlsafe(32))\""},{"language":"text","snippet":"https://<your-domain>/signalhire/callback?k=<your-secret>"},{"language":"text","snippet":"SIGNALHIRE_CALLBACK_URL=https://your-domain.com/signalhire/callback?k=your-secret-here\nSIGNALHIRE_WEBHOOK_SECRET=your-secret-here"},{"language":"python","snippet":"import os\ncallback_url = os.environ[\"SIGNALHIRE_CALLBACK_URL\"]"},{"language":"bash","snippet":"python3 -m pip install flask"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: signalhire\ndescription: Interact with the SignalHire API to enrich and verify professional contacts. Use this skill when asked to find email addresses, phone numbers, or search for professional profiles and companies using SignalHire. Supports Person API for comprehensive profile/contact data and Search API for lead generation.\n---\n\n# SignalHire API Skill\n\nThis skill provides context and instructions for using the SignalHire API to retrieve contact information (emails, phone numbers, social media profiles) from a global database of professionals.\n\n## Authentication\nTo access the SignalHire API, an API key is required. The API key must be included in the `apikey` request header.\n\nIf the user hasn't provided their SignalHire API key in their request or environment, ask them to provide it before making API calls. Ensure it is kept secure and not exposed publicly.\n\n## Endpoints\n\n### 1. Person API\nRetrieves comprehensive profile and full contact details about a specific individual based on unique identifiers (e.g., LinkedIn® profile links, email addresses, phone numbers, or ID).\n- **Use Case:** Find a specific person's contact info.\n- **Rate Limit:** 600 items per minute.\n- **Callback URL:** The Person API is asynchronous — SignalHire POSTs the result to a callback URL you provide. See **Callback Setup** below.\n\n### 2. Search API\nSearches for individuals or companies using various filters (e.g., job title, location, industry). Returns a brief overview of information **without** contact details.\n- **Use Case:** Lead generation, talent acquisition, market research.\n- **Rate Limit:** 1 concurrent request.\n\n---\n\n## Callback Setup\n\nThe Person API is asynchronous: you submit a request with a `callbackUrl`, and SignalHire POSTs the enriched result to that URL when ready.\n\n### Requirements\n- A publicly reachable HTTPS endpoint that accepts POST requests with JSON body.\n- A **shared secret** in the callback URL as a query parameter (e.g. `?k=<secret>`), because SignalHire controls the outbound request and cannot set custom headers.\n\n### Step 1 — Deploy a webhook receiver\nYou need an HTTP server that:\n1. Accepts `POST /signalhire/callback?k=<secret>`\n2. Validates the `k` parameter against your stored secret\n3. Saves the JSON payload to a known file (e.g. `signalhire_result.json`) so the agent can read it back\n\nA minimal Flask example:\n```python\nimport hmac, os\nfrom flask import Flask, request, jsonify\nimport json\n\napp = Flask(__name__)\nSECRET = os.environ[\"SIGNALHIRE_WEBHOOK_SECRET\"]\n\n@app.before_request\ndef auth():\n    if request.method == \"POST\":\n        k = request.args.get(\"k\", \"\")\n        if not hmac.compare_digest(k, SECRET):\n            return jsonify({\"error\": \"unauthorized\"}), 403\n\n@app.route(\"/signalhire/callback\", methods=[\"POST\"])\ndef callback():\n    payload = request.get_json()\n    with open(\"signalhire_result.json\", \"w\") as f:\n        json.dump(payload, f, indent=2)\n    return jsonify({\"status\": \"accepted\"}), 200\n\nif __name__ == \"__main_"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn776naxw6eehs7q16s8b9yh5d8091xn\",\n  \"slug\": \"signalhire-skill\",\n  \"version\": \"1.0.1\",\n  \"publishedAt\": 1789763899090\n}"},{"path":"skill-card.md","content":"## Description:\n\nThe SignalHire skill guides agents in using the SignalHire API to search professional profiles and companies, enrich contact details, and handle asynchronous callback-based results.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[nts](https://clawhub.ai/user/nts)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to search for prospects or companies and request contact enrichment through SignalHire. It is intended for workflows that have a legitimate SignalHire account and a lawful basis for handling personal contact data.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill handles personal contact data returned by SignalHire.\n\nMitigation: Use it only with a legitimate SignalHire account and a lawful basis for contact lookup, and avoid unnecessary storage or sharing of enrichment results.\n\nRisk: Callback-based enrichment can expose webhook endpoints and callback secrets.\n\nMitigation: Prefer a presecured callback service, validate shared secrets, use HTTPS, and rotate callback secrets when exposure is suspected.\n\nRisk: API keys and callback URLs may be exposed through shell commands, logs, or command history.\n\nMitigation: Keep credentials in environment variables or a managed secret store and avoid echoing sensitive values into logs or persistent command history.\n\n## Reference(s):\n\n- [ClawHub SignalHire Skill Page](https://clawhub.ai/nts/skills/signalhire-skill)\n\n## Skill Output:\n\n**Output Type(s):** [guidance, markdown, code, shell commands, configuration]\n\n**Output Format:** [Markdown guidance with inline Python, shell, and environment configuration examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include API request instructions, callback setup steps, status handling guidance, and notes about remaining credits.]\n\n## Skill Version(s):\n\n1.0.1 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1739,"uniquenessScore":37,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T09:14:21.709Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T09:14:21.709Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T03:22:13.238Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}