API authentication and quickstart

Create an OAuth service account, send an authenticated request, and understand the customer-facing API boundary.

Dureach provides customer API resources under versioned /api/ routes. The application also has internal /api/v1/ and /api/v2/ routes. An internal route is not automatically part of the public API; use only the paths listed in the API reference.

Create a key

  1. Open Settings → Integrations in the app.
  2. Open the OAuth service account area and create a key with the minimum required access.
  3. Give the key a clear name, select only the scopes the integration needs, copy it once into a server-side secret manager, and use YOUR_OAUTH_ACCESS_TOKEN in documentation and examples.
  4. If the key is exposed, revoke it and create a replacement; never paste it into a browser bundle, URL, screenshot, issue, or log.

Authenticate

Send the key in the Authorization: Bearer YOUR_OAUTH_ACCESS_TOKEN header. Keep it out of browser bundles, URLs, screenshots, issues, and logs. Requests are scoped to the active workspace that created the key.

curl --fail-with-body 'https://app.dureach.com/api/v2/webhooks?limit=25' \
  -H 'Authorization: Bearer YOUR_OAUTH_ACCESS_TOKEN' \
  -H 'Accept: application/json'

The OAuth service-account and webhook management resources are available under /oauth/service-accounts, /api/v2/webhooks, and /api/v2/webhook-events. Check access and entitlements in your workspace before building an integration.

Request and response shape

Create a key with a JSON body containing name and a non-empty scopes array. The create response includes id, name, scopes, key, workspace_id, timestamp_created, and timestamp_updated. The full key is returned once; later reads expose only a safe prefix.

{
  "name": "Reporting integration",
  "scopes": ["campaigns:read"]
}

List responses use an items array and may include next_starting_after. Preserve that cursor exactly when requesting the next page. OAuth service-account and webhook list endpoints default to 25 records; webhook and webhook-event pages are bounded to 100 records. Webhook records include campaign, name, target_hook_url, event_type, and custom_interest_value; webhook event records include delivery status and retry fields.

Operational checklist

  1. Use the exact documented method and path; private application and runner routes are not customer API endpoints.
  2. Keep page sizes bounded and follow the endpoint’s cursor or pagination fields.
  3. Handle 401 as invalid or revoked authentication and 403 as permission or entitlement failure.
  4. Retry only transient server failures, with bounded backoff and an idempotency strategy for writes. Do not blindly retry 400, 401, 403, 404, 409, or 429 responses.
  5. Store request IDs and redacted error codes for support, never the key or private payload.

Make webhook consumers idempotent: store the event identifier before acknowledging it, validate signatures where configured, and tolerate delivery retries.

Errors

OAuth service-account errors use JSON with statusCode, error, and message; newer endpoints may also include a machine-readable code. Treat 400 as invalid input, 401 as an authentication failure, 403 as an authorization or entitlement failure, 404 as an unknown resource, 409 as a state conflict, and 429 as a rate or usage limit. Do not retry a 4xx response blindly.

See API webhooks and usage limits.

Authentication failure table

HTTP statusMeaningFix
400Invalid JSON, field, cursor, or limit.Validate the request and use the documented enum/value.
401Missing, invalid, or revoked bearer key.Send Authorization: Bearer YOUR_OAUTH_ACCESS_TOKEN; replace a revoked key.
403Scope, role, workspace, or plan does not permit the operation.Add the required scope or ask a workspace admin to enable access.
404Resource or path does not exist.Confirm the version, UUID, and public endpoint list.
429Rate or usage limit.Honor the response guidance and retry with bounded backoff.

Safe verification

Run a read-only request first, confirm the response workspace and items shape, and store the next_starting_after cursor exactly as returned. For a write, log only the HTTP status, redacted error code, and request ID. Never log the bearer key or webhook payload.