Skip to main content
darkship docs
Open console

Reference · REST API v1

REST API

Everything the console does is available over HTTPS and JSON: flags, targeting, environments, segments, keys, tokens and webhooks. Every endpoint below shows its parameters, request body, responses and a copyable curl command.

Updated Oct 28, 202661 min read Edit this page on GitHub (opens in a new tab)

Generated from the OpenAPI document

The endpoint index below is rendered at build time from the OpenAPI 3.1 document published by the API, so it cannot drift from the implementation. To try calls, browse schemas and copy code samples, open the interactive API explorer. The machine-readable spec is served at /openapi.json (on this site and on the API host). Spec: Darkship API v1.0.0.

Overview#

Base URL
https://api.darkship.tech/v1 for management; https://sdk.darkship.tech/v1 for the SDK data plane.
Format
JSON only. Fields are snake_case, timestamps are ISO-8601 in UTC, ids are opaque strings.
Versioning
Breaking changes only ship under a new major path. Additive changes (new fields, new endpoints) happen within /v1, so ignore fields you don't know. Deprecations are announced with Deprecation and Sunset headers and in the changelog.
Spec
/openapi.json: OpenAPI 3.1, linted in CI with Spectral. It covers both hosts (the SDK data plane is the SDK data plane tag), names every request and response schema, and lists the permission each operation needs in x-required-scope. Generate a client in any language from it.

Authentication#

Send a key in the Authorization header. Which key depends on the host and endpoint:

Credentials by use.
CredentialPrefixCallsNotes
API tokends_pat_Management API on apiScoped permissions; personal or service. Created in the console or here.
Server SDK keyds_srv_GET /v1/sdk/snapshot, GET /v1/sdk/stream, POST /v1/telemetry/countersSecret. One environment.
Client SDK keyds_cli_POST /v1/sdk/evaluate onlyPublic by design. Other routes return 403.
Shellterminal
$ curl https://api.darkship.tech/v1/projects/web-app/flags \
    -H "Authorization: Bearer $DARKSHIP_API_TOKEN"
Secrets

Keys are shown once and stored only as a hash. Put ds_pat_ and ds_srv_ values in a secret store, never in source control; the prefixes are registered with secret scanners. A token can never hold more permissions than the person who created it, and stops working if they leave the organisation.

Scopes#

Every operation lists the permission it needs in x-required-scope. An API token carries a subset of these as its scopes; a console member gets them from their role (GET /v1/roles lists the catalogue). Operations marked session only cannot be called with an API token. The table is generated from the spec:

Permissions required per operation (x-required-scope).
PermissionAPI tokensOperations
api_token:manageno (session only)GET /v1/api-tokens, POST /v1/api-tokens, DELETE /v1/api-tokens/{tokenId}
audit:readyesGET /v1/audit-log
billing:manageno (session only)GET /v1/orgs/{orgId}/billing, POST /v1/orgs/{orgId}/billing/checkout, POST /v1/orgs/{orgId}/billing/portal
environment:manageyesPOST /v1/projects/{projectId}/environments, PUT /v1/projects/{projectId}/environments/order, PATCH /v1/projects/{projectId}/environments/{envId}, DELETE /v1/projects/{projectId}/environments/{envId}
environment:readyesGET /v1/projects/{projectId}/environments, GET /v1/projects/{projectId}/environments/{envId}
flag:deleteyesDELETE /v1/projects/{projectId}/flags/{flagKey}, POST /v1/projects/{projectId}/flags/{flagKey}/archive, POST /v1/projects/{projectId}/flags/{flagKey}/restore
flag:readyesGET /v1/projects/{projectId}/flags, GET /v1/projects/{projectId}/flags/{flagKey}, GET /v1/projects/{projectId}/flags/{flagKey}/history, GET /v1/projects/{projectId}/flags/{flagKey}/history/{historyId}, GET /v1/projects/{projectId}/flags/{flagKey}/environments/{envId}, POST /v1/projects/{projectId}/flags/{flagKey}/environments/{envId}/evaluate-preview, GET /v1/projects/{projectId}/flags/{flagKey}/environments/{envId}/history, GET /v1/projects/{projectId}/segments, GET /v1/projects/{projectId}/segments/{segmentKey}, GET /v1/projects/{projectId}/segments/{segmentKey}/usage
flag:writeyesPOST /v1/projects/{projectId}/flags, PATCH /v1/projects/{projectId}/flags/{flagKey}, POST /v1/projects/{projectId}/flags/{flagKey}/history/{historyId}/restore, PUT /v1/projects/{projectId}/flags/{flagKey}/environments/{envId}, PATCH /v1/projects/{projectId}/flags/{flagKey}/environments/{envId}, POST /v1/projects/{projectId}/flags/{flagKey}/environments/{envId}/toggle, POST /v1/projects/{projectId}/flags/{flagKey}/environments/{envId}/targets/import/preview, POST /v1/projects/{projectId}/flags/{flagKey}/environments/{envId}/targets/import, POST /v1/projects/{projectId}/flags/{flagKey}/environments/{envId}/history/{historyId}/restore
member:manageno (session only)GET /v1/invitations, POST /v1/invitations, DELETE /v1/invitations/{invitationId}, PATCH /v1/members/{memberId}, DELETE /v1/members/{memberId}
member:readno (session only)GET /v1/members
org:manageno (session only)PATCH /v1/organizations/{orgId}, DELETE /v1/organizations/{orgId}, POST /v1/organizations/{orgId}/deletion, POST /v1/organizations/{orgId}/restore
org:readyesGET /v1/organizations/{orgId}
org:transferno (session only)POST /v1/organizations/{orgId}/transfer-ownership
project:manageyesPOST /v1/projects, PATCH /v1/projects/{projectId}, DELETE /v1/projects/{projectId}
project:readyesGET /v1/projects, GET /v1/projects/{projectId}
sdk_key:manageyesPOST /v1/projects/{projectId}/environments/{envId}/sdk-keys, POST /v1/sdk-keys/{keyId}/rotate, DELETE /v1/sdk-keys/{keyId}
sdk_key:readyesGET /v1/sdk-keys, GET /v1/projects/{projectId}/environments/{envId}/sdk-keys
segment:manageyesPOST /v1/projects/{projectId}/segments, PATCH /v1/projects/{projectId}/segments/{segmentKey}, DELETE /v1/projects/{projectId}/segments/{segmentKey}, POST /v1/projects/{projectId}/segments/{segmentKey}/import/preview, POST /v1/projects/{projectId}/segments/{segmentKey}/import
usage:readyesGET /v1/usage, GET /v1/projects/{projectId}/usage, GET /v1/projects/{projectId}/flags/{flagKey}/usage
webhook:manageyesGET /v1/webhooks/event-types, GET /v1/projects/{projectId}/webhooks, POST /v1/projects/{projectId}/webhooks, GET /v1/webhooks/{id}, PATCH /v1/webhooks/{id}, DELETE /v1/webhooks/{id}, POST /v1/webhooks/{id}/rotate-secret, POST /v1/webhooks/{id}/test, GET /v1/webhooks/{id}/deliveries, GET /v1/webhooks/{id}/deliveries/{deliveryId}, POST /v1/webhooks/{id}/deliveries/{deliveryId}/redeliver

Conventions#

Pagination#

List endpoints take limit (1 to 200, default 50) and an opaque cursor, and return data plus next_cursor (null on the last page).

Idempotency#

Mutations accept an Idempotency-Key header. The key is stored for 24 hours with a hash of the request body. Replaying the same request returns the original response; reusing the key with a different body returns 409.

Optimistic concurrency#

Flags and rulesets return an ETag. Send it back in If-Match when updating; if someone else changed the resource, you get 412 precondition_failed instead of silently overwriting their edit.

Errors#

Errors share one envelope. code is stable and machine-readable; message is for humans and may change. The request_id is also returned in the X-Request-Id header; include it when you contact support.

JSON404 Not Found
{
  "error": {
    "code": "flag_not_found",
    "message": "Flag 'checkout-v2' does not exist in project 'web-app'.",
    "request_id": "req_01J9ZK3Q8M4V",
    "details": [{ "field": "flag", "issue": "not_found" }],
    "docs_url": "https://docs.darkship.tech/errors/flag_not_found"
  }
}
HTTP status codes.
StatusMeaning
400Malformed request, e.g. invalid JSON.
401Missing or invalid credentials.
403Valid credentials, not allowed: insufficient scope, or wrong key type for the endpoint.
404Resource does not exist (or you cannot see it).
409Conflict: duplicate key, or Idempotency-Key reused with a different body.
412If-Match did not match the current ETag.
422Validation failed. See details for each field.
429Rate limited. Honour Retry-After.
5xxOur fault. Retry idempotent requests with exponential backoff and jitter.
Plans never break evaluation

Over-quota or past-due states restrict creating new things through this API (you'd see 402 plan_limit_reached on create calls). Evaluation endpoints keep serving in every state.

Rate limits#

Limits are per token (or per SDK key on the data plane) and per plan, and use separate buckets for management, ruleset fetch, evaluation and telemetry. Every response includes:

HTTPresponse headers
RateLimit-Limit: 600
RateLimit-Remaining: 598
RateLimit-Reset: 41

HTTP/1.1 429 Too Many Requests
Retry-After: 17

RateLimit-Reset is the number of seconds until the window resets. The numbers shown are placeholders until load data sets the plan limits. Data-plane limits are generous because a hit is a cache read.

Endpoints#

A searchable index of every operation, rendered at build time (it also works without JavaScript). For the full interactive reference with schemas, a request console and code samples, use the API explorer.

Account 7 endpoints#

The signed-in user (console session).

Organizations 8 endpoints#

Organizations you belong to: create, rename, delete and transfer ownership.

Projects 5 endpoints#

Projects group flags, segments and environments. Creating one adds dev, staging and prod.

Environments 6 endpoints#

Environments of a project (dev, staging, prod, ...). Each has its own flag configuration and SDK keys.

Flags 10 endpoints#

Typed feature flags. The type and key are fixed at creation; variations, name and tags can change.

Flag environments 9 endpoints#

Per-environment state of a flag: on/off, individual targets, rules, fallthrough and rollout.

Segments 8 endpoints#

Reusable audiences, project-wide. Every environment snapshot embeds them.

SDK keys 5 endpoints#

Server (`ds_srv_`) and client (`ds_cli_`) keys for the data plane. Secrets are shown once.

API tokens 3 endpoints#

Scoped `ds_pat_` tokens for this API. Secrets are shown once.

Members 4 endpoints#

Organization members, their roles and scopes, and the role catalogue.

Invitations 4 endpoints#

Invite people by email; they join with the role and scope you choose.

Webhooks 11 endpoints#

Signed HTTP callbacks for flag, segment and environment changes, with a delivery log.

Audit log 1 endpoint#

Who changed what and when, newest first.

Usage 3 endpoints#

Requests and evaluations over time, per organization, project and flag.

Billing 5 endpoints#

Plan, subscription, Stripe Checkout and Customer Portal, and the public plan catalogue.

Platform 1 endpoint#

Public platform status: maintenance, announcements, read-only mode.

SDK data plane 6 endpoints#

Served by the evaluation service (`eval` host), not the management API. Server keys download the ruleset snapshot (or subscribe to changes) and evaluate in-process; client keys ask for evaluated values only. Use these routes to write an SDK for a language we do not ship.

Was this helpful?