Get your dream built 10x faster

How to integrate Bear Notes with OpenClaw

We build custom applications 5x faster and cheaper 🚀

Book a Free Consultation
4.9
Clutch rating 🌟
600+
Happy partners
17+
Countries served
190+
Team members
Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Stuck on an error? Book a 30-minute call with an engineer and get a direct fix + next steps. No pressure, no commitment.

How to integrate Bear Notes with OpenClaw

Direct answer: Build a small stateless skill that performs authenticated HTTP calls to Bear Notes’ API (or to whatever Bear exposes) and install it through ClawHub; use OAuth (preferred) or API keys to obtain scoped tokens, store those secrets in ClawHub or an external secret store, and implement an explicit OAuth callback or webhook receiver on an external HTTPS endpoint that the skill calls when invoked by the OpenClaw agent. Keep the agent runtime stateless (calls the Bear API at runtime), put long-term storage or background sync outside the agent, validate webhooks and rate limits, and debug by checking ClawHub/agent logs, inspecting Bear API responses, and verifying tokens/scopes. Replace the placeholder endpoints and scopes in the examples below with the real Bear Notes endpoints and scopes you get from the Bear/third‑party developer docs.

 

What you’ll need up front

 
  • A Bear Notes developer app or API credentials — client_id and client_secret (or an API key) and the list of scopes you’ll request. If Bear has webhooks, obtain webhook secret info.
  • A public HTTPS callback/webhook URL — this is where OAuth redirects and webhooks will post; it can be a separate small web service you deploy (recommended).
  • ClawHub account and skill package — package your skill code and configuration and install it through ClawHub. Use ClawHub to set environment variables or secrets (client_id, client_secret, webhook secret, any service account credentials).
  • Secure storage for tokens — either ClawHub’s secret facility (if available) or your own secrets store (Vault, AWS Secrets Manager) for refresh tokens and long-term credentials. Do not rely on ephemeral agent disk for persistent tokens.

 

Architecture / responsibilities

 
  • What runs inside the agent/skill: pure, short-lived HTTP calls to Bear’s API using tokens available in environment variables or provided at invocation time; minimal transformation/formatting; respond quickly.
  • What lives outside the agent: OAuth callback endpoint that exchanges authorization codes for tokens; long-term token storage and refresh logic (or a safe place to persist refresh tokens); schedulers or background workers for periodic sync; a webhook endpoint (must be externally reachable) and a reliable retry/queue mechanism for incoming webhook events if you need durability.

 

Step-by-step integration (practical)

 
  • Decide auth mode. Prefer OAuth if Bear supports user-level access (so users can authorize their own notes). Use API keys for single-account integrations or service-account style access if Bear exposes that.
  • Register the application. In Bear’s developer console register redirect_uri pointing to your OAuth callback (e.g., https://your-service.example.com/oauth/callback). Record client_id and client_secret and the scopes required (read_notes, write\_notes, etc.).
  • Implement OAuth callback (external service). The callback receives the authorization code, exchanges it for access and refresh tokens, validates the token response, and securely stores tokens (not on the agent runtime). Example Node.js exchange below uses placeholders for Bear’s token endpoint — replace with Bear’s real URL.
// Node.js + express example: OAuth code exchange and token storage
const express = require('express');
const fetch = require('node-fetch');
const app = express();

app.get('/oauth/callback', async (req, res) => {
  const code = req.query.code;
  if (!code) return res.status(400).send('Missing code');
  <b>//</b> Exchange code for tokens at Bear's token endpoint (replace URL)
  const tokenResp = await fetch('https://api.bearnote.example/oauth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type: 'authorization_code',
      code,
      client_id: process.env.BEAR_CLIENT_ID,
      client_secret: process.env.BEAR_CLIENT_SECRET,
      redirect_uri: process.env.BEAR_REDIRECT_URI
    })
  });
  if (!tokenResp.ok) {
    const text = await tokenResp.text();
    return res.status(500).send('Token exchange failed: ' + text);
  }
  const tokenJson = await tokenResp.json();
  <b>//</b> persist tokens to a secure store (DB/Vault). Example: save tokenJson.access_token and tokenJson.refresh_token
  await saveTokensToSecretStore(req.query.state /*owner*/, tokenJson);
  return res.send('Authorization complete');
});

app.listen(3000);
  • Store secrets where ClawHub or your infra can access them. For the skill to make calls at runtime, inject access tokens or short‑lived credentials as environment variables or have the skill call your token service to fetch a token just-in-time. Prefer server-side token retrieval (the skill calls your token service) over baking long-lived secrets into the skill code.
  • Skill runtime code: make authenticated API calls to Bear. Example: fetch a user’s note list using a stored access token. Handle 401 responses by retrieving a fresh token via the refresh\_token flow (performed by your external token service or the skill if you store refresh tokens securely).
// Skill execution example: fetch notes using access token (replace API URL)
const fetch = require('node-fetch');

async function fetchNotesForUser(userId) {
  <b>//</b> Get an access token from secure store or token service
  const accessToken = await getAccessTokenForUser(userId);
  const resp = await fetch('https://api.bearnote.example/v1/notes', {
    headers: { 'Authorization': `Bearer ${accessToken}`, 'Accept': 'application/json' }
  });
  if (resp.status === 401) {
    <b>//</b> Token might be expired. Either refresh here or signal caller to refresh.
    throw new Error('Unauthorized: token expired or invalid');
  }
  if (!resp.ok) {
    const body = await resp.text();
    throw new Error(`Bear API error ${resp.status}: ${body}`);
  }
  return resp.json();
}
  • If Bear provides webhooks: implement an external HTTPS webhook endpoint that validates the incoming signature (HMAC or whatever Bear specifies) and then either push events into a queue for processing or notify the agent/skill via a controlled mechanism. Never trust raw webhook payloads — always verify signature and origin.
// Webhook verification example (HMAC SHA256). Replace header name and secret usage according to Bear docs.
const crypto = require('crypto');
app.post('/webhook', express.json(), (req, res) => {
  const signature = req.headers['x-bear-signature']; <b>//</b> placeholder header name
  const secret = process.env.BEAR_WEBHOOK_SECRET;
  const payload = JSON.stringify(req.body);
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');
  if (!signature || !crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    return res.status(401).send('Invalid signature');
  }
  <b>//</b> enqueue or handle the event
  handleWebhookEvent(req.body);
  res.status(202).send('Accepted');
});

 

Configuring the skill in ClawHub (conceptual)

 
  • Upload skill package: code + small entry point that OpenClaw agent will call. Keep the handler focused: accept invocation payload, call the Bear API, return a compact result.
  • Set secrets and environment variables: client_id, client_secret (if used), redirect URI, webhook secret, or a URL to your token service. Store refresh tokens or service account credentials in a secure secrets store and reference them from ClawHub rather than hardcoding.
  • Define allowed scopes and permissions: configure the skill to only request the Bear scopes it needs. Ensure the agent/service account has minimal permissions.

 

Security and operational best practices

 
  • Least privilege: request only the Bear scopes you need. Limit ClawHub/skill permissions similarly.
  • Secret handling: never commit client\_secret, refresh tokens, or webhook secrets to source control. Use ClawHub secrets or a dedicated secret manager.
  • Token refresh: implement refresh\_token logic on the external service side; if the skill needs to refresh, do so securely and persist new tokens to the secure store.
  • Validate all webhooks and redirect parameters: use HMAC signatures and state parameters on OAuth flow to prevent CSRF.
  • Rate limiting and retries: implement exponential backoff for 429/5xx responses and respect Bear’s rate limit headers if provided.
  • Audit logs: log API responses and errors (avoid logging secrets) so you can debug issues later.

 

Debugging checklist when things break

 
  • Check ClawHub and agent logs for the skill invocation and error traces.
  • Inspect Bear API responses: look for 401 (invalid/expired token), 403 (insufficient scope), 429 (rate limit), and 5xx errors. Log full response bodies (sanitized) for debugging.
  • Verify tokens and scopes: confirm client_id/client_secret, that redirect\_uri matches the registered value, and that refresh tokens are still valid.
  • Confirm webhook delivery: use replay or test endpoints in Bear’s dashboard (if available), and check your webhook endpoint logs for signature validation failures.
  • Check network & TLS: ensure the callback/webhook endpoints are publicly reachable over HTTPS and that TLS certs are valid.
  • Reproduce locally: run the skill locally with environment variables set (or use a tunnel like ngrok for OAuth callbacks) to replicate the flow step-by-step before redeploying.

 

Example end-to-end flow (summary)

 
  • User clicks “Connect Bear” in your UI → redirected to Bear’s OAuth page with client_id, redirect_uri, and state.
  • Bear redirects back to your external /oauth/callback with code and state → your callback exchanges code for access & refresh tokens and stores them securely.
  • ClawHub skill is invoked (user action or agent trigger) → skill asks your token service for a fresh access token for that user, then calls Bear’s REST API to read/write notes and returns the result to the caller.
  • If Bear sends webhooks for note changes → your webhook endpoint validates the signature and then either notifies the skill or writes to a queue/external store so the skill/worker can process it reliably.

Book Your Free 30‑Minute Migration Call

Speak one‑on‑one with a senior engineer about your no‑code app, migration goals, and budget. In just half an hour you’ll leave with clear, actionable next steps—no strings attached.

Book a Free Consultation

Troubleshooting Bear Notes and OpenClaw Integration

1

OpenClaw API OAuth refresh token 401 error when integrating Bear Notes?

Direct answer: A 401 on an OAuth refresh request means the provider rejected the refresh—usually because the refresh token was revoked/expired, the client_id/secret (or Authorization header) is wrong, the token endpoint is incorrect, or the skill’s stored env vars in ClawHub are stale; fix by verifying credentials, token endpoint, headers, logs, and if needed force a user re‑authorization to obtain a new refresh token.

 

Debug checklist

 
  • Inspect provider response body and logs for error codes/messages.
  • Verify client_id/client_secret and token URL stored in ClawHub env vars.
  • Check Authorization header (Basic base64(client_id:client_secret)) and Content-Type.
  • If revoked, prompt full OAuth flow to get a new refresh token.
// curl example
curl -X POST https://auth.example.com/token \
 -H "Content-Type: application/x-www-form-urlencoded" \
 -u "CLIENT_ID:CLIENT_SECRET" \
 -d "grant_type=refresh_token&refresh_token=REFRESH_TOKEN"

2

OpenClaw webhook signature verification failing for Bear Notes webhooks (X-OpenClaw-Signature mismatch)?

Direct answer: X-OpenClaw-Signature mismatches almost always come from using a parsed JSON body instead of the raw HTTP payload, using the wrong secret or hash encoding (hex vs base64), or a different HMAC algorithm/timestamp canonicalization. Confirm Bear Notes’ signing scheme, fetch the raw request bytes in OpenClaw, compute the HMAC with the exact secret and encoding, and compare using a constant-time check.

 

Debug checklist

 
  • Capture raw body (no JSON parsing).
  • Confirm algorithm and encoding (HMAC SHA256, hex/base64).
  • Verify secret from ClawHub env var.
  • Log computed vs header and use constant-time compare.

 

Example (Node.js)

 
// express with raw-body middleware
const crypto = require('crypto');
// rawBody is the raw Buffer from the HTTP request
const sig = crypto.createHmac('sha256', process.env.BEAR_SECRET)
  .update(rawBody) // use raw bytes
  .digest('hex'); // or 'base64' per docs
// constant-time compare
if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(req.headers['x-openclaw-signature']))) {
  // reject
}

3

OpenClaw Sync Engine conflict: ETag/If-Match mismatch when syncing edits from Bear Notes?

 

Direct answer

 

Cause: an ETag mismatch means Bear (server) changed the note after your agent read it; the PATCH with If-Match is rejected (412). Fix: before writing, fetch the latest note/ETag, merge or prompt the user, then retry the update with the fresh ETag; log and surface conflicts from the skill.

 

Practical steps

 
  • Fetch latest resource and ETag immediately before edit.
  • Handle 412 by re-fetching, merging, and retrying (or returning a conflict to user).
  • Persist last-known ETag outside the runtime if you need cross-run durability.
// fetch latest note
const res = await fetch(noteUrl, { headers: { Authorization: `Bearer ${token}` } });
// patch with If-Match
const patch = await fetch(noteUrl, {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${token}`,
    'If-Match': currentEtag,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ content: newContent })
});
if (patch.status === 412) {
  // re-fetch, merge, retry or surface conflict
}

4

OpenClaw attachment upload 415 Unsupported Media Type when sending inline images from Bear Notes (Base64 vs multipart/form-data)?

 

Direct answer

 

415 Unsupported Media Type means the OpenClaw endpoint is rejecting the Content-Type you send. Inline Base64 inside JSON often causes this; the fix is to send the image as a real file upload (multipart/form-data) or match the API’s accepted content-type exactly.

 

How to fix (practical)

 
  • Convert Base64 to binary and send as multipart/form-data with proper filename and image/type.
  • Ensure headers include Authorization and form.getHeaders() (no application/json).
//<b>//</b> build multipart from base64
const form = new (require('form-data'))()
form.append('file', Buffer.from(base64, 'base64'), { filename:'img.png', contentType:'image/png' })
fetch(url, { method:'POST', headers:{ Authorization:`Bearer ${TOKEN}`, ...form.getHeaders() }, body: form })
Book a Free Consultation

Still stuck?
Copy this prompt into ChatGPT and get a clear, personalized explanation.

This prompt helps an AI assistant understand your setup and guide you through the fix step by step, without assuming technical knowledge.

AI AI Prompt


Recognized by the best

Trusted by 600+ businesses globally

From startups to enterprises and everything in between, see for yourself our incredible impact.

RapidDev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with.

They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

Arkady
CPO, Praction
Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost.

He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Donald Muir
Co-Founder, Arc
RapidDev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space.

They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Mat Westergreen-Thorne
Co-CEO, Grantify
RapidDev is an excellent developer for custom-code solutions.

We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Emmanuel Brown
Co-Founder, Church Real Estate Marketplace
Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 

This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Samantha Fekete
Production Manager, Media Production Company
The pSEO strategy executed by RapidDev is clearly driving meaningful results.

Working with RapidDev has delivered measurable, year-over-year growth. Comparing the same period, clicks increased by 129%, impressions grew by 196%, and average position improved by 14.6%. Most importantly, qualified contact form submissions rose 350%, excluding spam.

Appreciation as well to Matt Graham for championing the collaboration!

Michael W. Hammond
Principal Owner, OCD Tech

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We’ll discuss your project and provide a custom quote at no cost.Â