> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scrapengine.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Credential

> Register a named credential that points at a secret in your vault. The credential is referenced by ID from the authenticate task action at run time.

## Overview

Registers a named credential that the `authenticate` task action can resolve at run time. The raw username/password never touch ScrapEngine — only the vault integration ID, the path inside your vault, and the field names to read are stored here. Each credential is scoped to one or more hostnames via `allowedDomains`; the authenticate action refuses to use a credential on any other host.

## Body

<ParamField body="name" type="string" required={true}>
  Human-readable name. 1-100 characters.
</ParamField>

<ParamField body="vaultIntegrationId" type="string" required={true}>
  UUID of the vault integration that will be used to read the secret. Created via `POST /vault-integrations`.
</ParamField>

<ParamField body="vaultPath" type="string" required={true}>
  Path inside your vault. For HashiCorp KV v2 use the logical path (for example `secret/data/login-alice`).
</ParamField>

<ParamField body="fieldMap" type="object" required={true}>
  Maps the field names stored inside the vault secret to the roles the authenticate action understands.

  <Expandable title="fieldMap properties">
    <ParamField body="fieldMap.username" type="string" required={true}>
      Vault field name that holds the username.
    </ParamField>

    <ParamField body="fieldMap.password" type="string" required={true}>
      Vault field name that holds the password.
    </ParamField>

    <ParamField body="fieldMap.totp" type="string">
      Optional vault field name for a TOTP seed (MFA).
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="allowedDomains" type="string[]" required={true}>
  Hostnames this credential may be used on. At least one entry is required. Plain entries match the exact hostname; `*.example.com` matches subdomains but NOT the bare host. Wildcard-only (`*`) is rejected.
</ParamField>

## Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.scrapengine.io/api/v1/credentials" \
    -H "Authorization: Bearer $SCRAPENGINE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Alice @ app.example.com",
      "vaultIntegrationId": "5f8c6a74-5f2e-4f5a-9e58-5b9c3c7d2a11",
      "vaultPath": "secret/data/login-alice",
      "fieldMap": {
        "username": "username",
        "password": "password",
        "totp": "totp_seed"
      },
      "allowedDomains": ["app.example.com", "*.internal.example.com"]
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://api.scrapengine.io/api/v1/credentials", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.SCRAPENGINE_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      name: "Alice @ app.example.com",
      vaultIntegrationId: "5f8c6a74-5f2e-4f5a-9e58-5b9c3c7d2a11",
      vaultPath: "secret/data/login-alice",
      fieldMap: { username: "username", password: "password" },
      allowedDomains: ["app.example.com"],
    }),
  });
  const data = await response.json();
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.scrapengine.io/api/v1/credentials",
      headers={
          "Authorization": f"Bearer {SCRAPENGINE_API_KEY}",
          "Content-Type": "application/json",
      },
      json={
          "name": "Alice @ app.example.com",
          "vaultIntegrationId": "5f8c6a74-5f2e-4f5a-9e58-5b9c3c7d2a11",
          "vaultPath": "secret/data/login-alice",
          "fieldMap": {"username": "username", "password": "password"},
          "allowedDomains": ["app.example.com"],
      },
  )
  data = response.json()
  ```
</CodeGroup>

## Response

### Success Response (201)

<ResponseField name="id" type="string">
  Credential ID (UUID). Reference this from the `authenticate` task action.
</ResponseField>

<ResponseField name="name" type="string">
  The name you provided.
</ResponseField>

<ResponseField name="vaultIntegrationId" type="string">
  The vault integration this credential reads from.
</ResponseField>

<ResponseField name="vaultPath" type="string">
  The vault path this credential reads from.
</ResponseField>

<ResponseField name="fieldMap" type="object">
  The stored field-name mapping, echoed back.
</ResponseField>

<ResponseField name="allowedDomains" type="string[]">
  The stored allow-list of hostnames, echoed back.
</ResponseField>

<ResponseField name="createdAt" type="string">
  ISO 8601 timestamp.
</ResponseField>

<ResponseField name="updatedAt" type="string">
  ISO 8601 timestamp.
</ResponseField>

**Example Response:**

```json theme={null}
{
  "id": "2b5aa4c8-b9e6-4e58-9c80-1d4bfd0a3f01",
  "name": "Alice @ app.example.com",
  "vaultIntegrationId": "5f8c6a74-5f2e-4f5a-9e58-5b9c3c7d2a11",
  "vaultPath": "secret/data/login-alice",
  "fieldMap": {
    "username": "username",
    "password": "password",
    "totp": "totp_seed"
  },
  "allowedDomains": ["app.example.com", "*.internal.example.com"],
  "createdAt": "2026-04-24T09:12:44Z",
  "updatedAt": "2026-04-24T09:12:44Z"
}
```

### Error Responses

| Status | Description                                                                                 |
| ------ | ------------------------------------------------------------------------------------------- |
| `400`  | Invalid body, unknown `vaultIntegrationId`, or disallowed domain pattern (for example `*`). |
| `401`  | Unauthorized — invalid or missing API key.                                                  |
