---
title: "Propose which credentials a package uses: org default mappings (defaults), your own defaults (mine), per-trigger mapp..."
method: POST
path: "/v1/credential-proposals"
tags: ["secrets"]
---

# Propose which credentials a package uses: org default mappings (defaults), your own defaults (mine), per-trigger mapp...

`POST /v1/credential-proposals`

## Request

- Base URL: `https://api.kody.codes`
- URL: `https://api.kody.codes/v1/credential-proposals`
- Auth: HTTP bearer

Propose which credentials a package uses: org default mappings (defaults), your own defaults (mine), per-trigger mappings for your instance of a cron job, subscription, or webhook (triggers), and triggers to turn on with no mapping (enable). Never writes a mapping. Returns an approval URL to send to the person; nothing changes until they review it and click Approve, which applies every change at once and turns on every trigger it maps or enables. A webhook URL must be minted before it can be approved; minting alone does not turn it on. email.message.received and email.message.quarantined run only for a sender: pass sender (kind member, address, domain, or any_authenticated, and value except for any_authenticated) so the approval link names who it runs for. view.canApprove false lists what to fix first in view.changes[].error, view.enable[].error, and view.errors (unknown need or trigger, unminted webhook, missing or ambiguous credential with a createUrl, kind or provider mismatch, org defaults without package:write). Once the person approves, credentialTriggerPickSet can set those trigger picks again later. Needs package:execute on the package.

Org permission: none (touches no org data).

## Request body

- object
  - `packageId` string: Saved-package UUID. Use when the scoped name is not known, or for a stable ref.
  - `kodyId` string: Package name (`@owner/leaf` or the name leaf). Prefer this when you know the name.
  - `defaults` object: Org default mappings, keyed by need key.
  - `mine` object: Your own default mappings, keyed by need key.
  - `triggers` object[]
    - `kind` 'cron' | 'subscription' | 'webhook', required
    - `name` string, required: Job name, subscription topic, or webhook name.
    - `credentials` object, required: Mappings for your instance of this trigger, keyed by need key.
  - `enable` object[]: Triggers to turn on for the approver even though they map nothing, such as a webhook with no credential needs.
    - `kind` 'cron' | 'subscription' | 'webhook', required
    - `name` string, required: Job name, subscription topic, or webhook name.
  - `reason` string: Shown to the approver as an untrusted note.
  - `sender` object: Sender an inbound-email subscription runs for. Required when enabling email.message.received or email.message.quarantined.
    - `kind` 'member' | 'address' | 'domain' | 'any_authenticated', required
    - `value` string, nullable: Person id, email address, or bare domain. Omit for any_authenticated.

## Response `200`

Success.

- object
  - `approvalUrl` string, required
  - `view` object, required
    - `ok` true, required
    - `package` object, required
      - `id` string, required
      - `kodyId` string, required
    - `reason` string, nullable, required
    - `canApprove` boolean, required
    - `fingerprint` string, required
    - `changes` object[], required
      - `target` union, required
        - object
          - `type` 'default', required
          - `layer` 'org' | 'mine', required
        - object
          - `type` 'trigger', required
          - `trigger` object, required
            - `kind` 'cron' | 'subscription' | 'webhook', required
            - `name` string, required
      - `needKey` string, required
      - `need` object, nullable, required
        - `kind` 'secret' | 'oauth' | 'mcp' | 'url' | 'login' | 'signing', nullable, required
        - `provider` string, required
        - `description` string, required
        - `multiple` boolean, required
      - `before` object[], nullable, required: The stored override today; null means it inherits.
        - `id` string, required
        - `name` string, required
        - `scope` 'org' | 'personal', required
        - `kind` 'secret' | 'oauth' | 'mcp' | 'url' | 'login' | 'signing', required
      - `beforeUnusableIds` string[], required: Stored credential ids left out of before because you can no longer use them (deleted or Use revoked).
      - `after` object[], required
        - `id` string, required
        - `name` string, required
        - `scope` 'org' | 'personal', required
        - `kind` 'secret' | 'oauth' | 'mcp' | 'url' | 'login' | 'signing', required
      - `willEnable` boolean, required: Approving turns this trigger on for the approver.
      - `error` object, nullable, required
        - `code` 'need_unknown' | 'trigger_unknown' | 'credential_not_found' | 'credential_ambiguous' | 'kind_mismatch' | 'provider_mismatch' | 'too_many' | 'not_allowed' | 'webhook_not_minted' | 'webhook_other_enabler' | 'email_approval_required', required
        - `message` string, required
        - `createUrl` string
    - `sender` object, nullable, required: Sender stored when this proposal turns on an inbound-email subscription. Null when the link names no sender.
      - `kind` 'member' | 'address' | 'domain' | 'any_authenticated', required
      - `value` string, nullable, required
    - `enable` object[], required
      - `trigger` object, required
        - `kind` 'cron' | 'subscription' | 'webhook', required
        - `name` string, required
      - `willEnable` boolean, required: False when it is already on for the approver.
      - `error` object, nullable, required
        - `code` 'need_unknown' | 'trigger_unknown' | 'credential_not_found' | 'credential_ambiguous' | 'kind_mismatch' | 'provider_mismatch' | 'too_many' | 'not_allowed' | 'webhook_not_minted' | 'webhook_other_enabler' | 'email_approval_required', required
        - `message` string, required
    - `errors` string[], required
  - `message` string, required

## Other responses

- `400`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `401`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `403`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `404`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `409`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `413`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `429`: Too many requests (edge IP/token limit) or an entitlement / plan-cap limit. Wait at least `Retry-After` seconds before retrying.
- `500`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `503`: Error envelope `{ "error": { "code", "message", "details"? } }`.
- `default`: Error envelope `{ "error": { "code", "message", "details"? } }`.

---

[API](https://skmtc.dev/kody/apis/kody-api.md) · [All operations](https://skmtc.dev/kody/apis/kody-api/llms.txt) · [OpenAPI document](https://skmtc.dev/kody/apis/kody-api/revisions/a020ecedb82b?raw)
