Skip to main content

Collect

20 operations under /v1/collect (GET POST PATCH PUT): parameters, status codes, refusal bodies, and the same request in curl, HTTP, Python and TypeScript.

35 min read
View MarkdownEdit on GitHub

Base URL: https://api.codespar.dev

Operations below require a Bearer token unless their bar says No credential. See Authentication.

GET /v1/collect/attempts/{attemptId}/artifact

GEThttps://api.codespar.dev/v1/collect/attempts/{attemptId}/artifact

The WhatsApp material of an attempt

What the partner's channel sends: the copia-e-cola, a QR code PNG of it (base64), the amount, the due date and the hosted page URL as the fallback. CodeSpar sends nothing (sent is always false).

NOT BEFORE IT EXISTS. While the attempt is issuing this answers 409 artifact_not_ready with Retry-After and details.retry_after; subscribe to collect.attempt.ready instead of polling if you prefer; a failed attempt emits collect.attempt.failed with its failure_code. An attempt that is no longer payable (paid, superseded, expired, cancelled, failed) answers 410 artifact_unavailable with its state.

Path parameters

NameTypeRequiredDescription
attemptIdstringyes—

Responses

StatusBodyDescription
200objectOK
404objectNo attempt with that id in this project.
409objectNot ready, or the link does not enable WhatsApp.
410objectThe attempt has no payable material any more.

Response 200

FieldTypeRequiredDescription
amount_minorintegeryes—
attempt_idstringyes—
copy_pastestring,nullyesThe Pix copia-e-cola. Null until the attempt is open: it does not exist before the issuer registers it.
currency"BRL"yes—
due_datestringyes—
environment"live" | "test"yesThe link's environment. test: the Pix moves no real money, and the message can say so.
expires_atstringyes—
failure_codestring,nullno—
fallback_urlstringyes—
idstringyes—
link_idstringyes—
object"collect_artifact"yes—
qr_mime_type"image/png"yes—
qr_png_base64stringyes—
ready_atstring,nullyes—
retry_afterintegernoWhile issuing: seconds until the next readiness check.
sentfalseyes—
state"issuing" | "open" | "superseded" | "expired" | "cancelled" | "paid" | "failed"yes—
surface"page" | "whatsapp"yes—
Example request
curl -X GET https://api.codespar.dev/v1/collect/attempts/{attemptId}/artifact \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
GET /v1/collect/attempts/{attemptId}/artifact HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.get(
    "https://api.codespar.dev/v1/collect/attempts/{attemptId}/artifact",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/attempts/{attemptId}/artifact", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.get("/v1/collect/attempts/{attemptId}/artifact", {
  path: {
    attemptId: "attempt_0000000000000000"
  }
});
Example response 200
application/json
{
  "id": "obj_0000000000000000",
  "state": "issuing",
  "surface": "page",
  "amount_minor": 1000,
  "currency": "BRL",
  "due_date": "string",
  "expires_at": "string",
  "copy_paste": "string",
  "ready_at": "string",
  "retry_after": 0,
  "failure_code": "string",
  "object": "collect_artifact",
  "attempt_id": "attempt_0000000000000000",
  "link_id": "link_0000000000000000",
  "environment": "live",
  "qr_png_base64": "string",
  "qr_mime_type": "image/png",
  "fallback_url": "https://example.com/hook",
  "sent": false
}

POST /v1/collect/attempts/{attemptId}/test-pay

POSThttps://api.codespar.dev/v1/collect/attempts/{attemptId}/test-pay
Moves money

pays the attempt's charge FOR REAL at the Celcoin sandbox

Pay a Test attempt's charge from the shared Test payer (the payer button)

"Simular pagamento do cliente": pays the attempt's charge FOR REAL at the Celcoin sandbox, from the operator's Test payer account, the way a customer would pay its copia-e-cola. Test projects only.

No body: the amount and the destination come from the stored attempt and charge. One payment per charge; a second call answers 409 test_pay_already_used whatever happened to the first. Capped per payment and per project per 24 hours. The attempt turns paid the way any payment does (the charge-in, the reconciler, or the hosted page's read), never from this answer.

Path parameters

NameTypeRequiredDescription
attemptIdstringyes—

Responses

StatusBodyDescription
200objectOK
400objectA body was sent, or the credential names no project.
403objectNot a Test credential or project.
404objectNo attempt with that id in this project.
409objectThe attempt is not open, the charge already had its Test payment, or it is above the cap.
429objectThe project used its Test payments for the last 24 hours.
502objectA step at Celcoin failed; the charge keeps its claim.
503objectNo Test payer or Celcoin connection on this deployment.

Response 200

FieldTypeRequiredDescription
amount_minorintegeryes—
attempt_idstringyes—
charge_idstringyes—
end_to_end_idstring,nullyes—
object"collect_test_payment"yes—
statusstringyesCelcoin's answer to the Pix, usually PROCESSING; not a settlement.
Example request
curl -X POST https://api.codespar.dev/v1/collect/attempts/{attemptId}/test-pay \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
POST /v1/collect/attempts/{attemptId}/test-pay HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.post(
    "https://api.codespar.dev/v1/collect/attempts/{attemptId}/test-pay",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/attempts/{attemptId}/test-pay", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const r = await cs.api.response("post", "/v1/collect/attempts/{attemptId}/test-pay", {
  path: {
    attemptId: "attempt_0000000000000000"
  }
});
// r.status is one of the documented statuses (200, 403),
// each with its own body shape in r.data; nothing here throws on 403.
if (r.ok) {
  console.log(r.data);
}
Example response 200
application/json
{
  "object": "collect_test_payment",
  "attempt_id": "attempt_0000000000000000",
  "charge_id": "charge_0000000000000000",
  "amount_minor": 1000,
  "status": "string",
  "end_to_end_id": "endtoend_0000000000000000"
}
GEThttps://api.codespar.dev/v1/collect/links

List this project's Collect links

Newest first. next_cursor is the created_at of the last row, to pass as before.

Query parameters

NameTypeRequiredDescription
beforestring (date-time)no—
limitintegerno—
state"draft" | "published" | "paused" | "archived"no—

Responses

StatusBodyDescription
200objectOK
400objectBad Request.

Response 200

FieldTypeRequiredDescription
dataarray of objectyes—
next_cursorstring,nullyes—
Example request
curl -X GET https://api.codespar.dev/v1/collect/links \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
GET /v1/collect/links HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.get(
    "https://api.codespar.dev/v1/collect/links",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/links", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.get("/v1/collect/links");
Example response 200
application/json
{
  "data": [
    {
      "id": "obj_0000000000000000",
      "object": "collect_link",
      "state": "draft",
      "environment": "live",
      "consumer_id": "csm_0000000000000000",
      "receiver": {
        "name": "Example"
      },
      "paid": true,
      "paid_at": "string",
      "current_version": 0,
      "valid_until": "string",
      "url": "https://example.com/hook",
      "payer_prefilled": [
        "name"
      ],
      "payer_document_masked": "string",
      "version": {
        "version": 0,
        "status": "draft",
        "title": "Example",
        "description": "string",
        "success_message": "string",
        "items": [
          {
            "name": "Example",
            "quantity": 0,
            "unit_amount_minor": 1000
          }
        ],
        "total_minor": 1,
        "currency": "BRL",
        "brand": {},
        "surfaces": [
          "page"
        ],
        "due_in_days": 0,
        "payer_fields": {
          "name": "required",
          "contact": "required",
          "external_reference": "required"
        },
        "usdc_price": "string",
        "usdc_price_atomic": "string",
        "usdc_price_confirmed_at": "string",
        "created_at": "string",
        "published_at": "string"
      },
      "draft": {
        "version": 0,
        "status": "draft",
        "title": "Example",
        "description": "string",
        "success_message": "string",
        "items": [
          {
            "name": "Example",
            "quantity": 0,
            "unit_amount_minor": 1000
          }
        ],
        "total_minor": 1,
        "currency": "BRL",
        "brand": {},
        "surfaces": [
          "page"
        ],
        "due_in_days": 0,
        "payer_fields": {
          "name": "required",
          "contact": "required",
          "external_reference": "required"
        },
        "usdc_price": "string",
        "usdc_price_atomic": "string",
        "usdc_price_confirmed_at": "string",
        "created_at": "string",
        "published_at": "string"
      },
      "created_at": "string",
      "updated_at": "string",
      "published_at": "string",
      "paused_at": "string",
      "archived_at": "string",
      "agent": {
        "url": "https://example.com/hook",
        "status": "ready",
        "reason": "string",
        "challenge": {},
        "refusal": {
          "code": "string",
          "message": "string",
          "http_status": 0
        },
        "usdc": {
          "price": "string",
          "amount": "1000",
          "currency": "USDC",
          "network": "string",
          "asset": "string",
          "payable": false,
          "reason": "usdc_pay_to_unavailable",
          "message": "string",
          "statement": "string"
        }
      }
    }
  ],
  "next_cursor": "string"
}

POST /v1/collect/links

POSThttps://api.codespar.dev/v1/collect/links

Create a Collect link with its first draft

Creates a single-use link (one link, one charge, one valid payment) in draft, with version 1 as its draft. Nothing is shown to payers until it is published.

consumer_id is the RECEIVING consumer: the Pix the link issues settles into that consumer's wallet. No Pix key or account is accepted on the link.

payer optionally prefills the payer. document (CPF/CNPJ, check digits verified) and address are the regulated fields a Pix with due date requires; when they are not prefilled, the hosted page collects them. All payer data is stored encrypted and is never returned: the response names which fields are prefilled and shows the document masked.

Collect is off unless the deployment sets COLLECT_ENABLED=true. Off, every /v1/collect path (owner and payer) answers 404 {"error": "collect_disabled", "message": "Collect não está disponível nesta versão. ..."}, never the router's generic 404.

Request body

FieldTypeRequiredDescription
consumer_idstringyes—
payerobjectno—
valid_untilstring (date-time)no—
versionobjectyes—

Responses

StatusBodyDescription
201objectOK
400objectBad Request. The body did not match the schema (invalid_body, with details.issues), or the version breaks a rule the schema cannot state: the items total below the R$5.00 a Pix with due date needs (collect_total_below_minimum), above R$1,000,000.00 (collect_total_above_maximum), or brand colors whose contrast is below 4.5:1 (collect_brand_contrast_insufficient), or a usdc_price on a version without the agent surface (collect_usdc_price_requires_agent). Unknown keys are refused, not dropped: the regulated payer fields (document, address) are never free-text questions.

Response 201

FieldTypeRequiredDescription
agentobject,nullnoThe agent surface (402), on the single-link read: null when the version in force does not enable it.
archived_atstring,nullyes—
consumer_idstringyesThe receiving consumer: the charge settles into its wallet.
created_atstringyes—
current_versioninteger,nullyes—
draftobject,nullyesThe open draft, if any.
environment"live" | "test"yes—
idstringyescl_ + 128 random bits. Minted by the server; never chosen by the caller.
object"collect_link"yes—
paidbooleanyesWhether the link has its paid payment, whenever it settled (not bound to any stats window). A late or duplicate payment is not the link's payment and does not make it paid.
paid_atstring,nullyesWhen the paid payment settled; null while unpaid.
paused_atstring,nullyes—
payer_document_maskedstring,nullyesThe prefilled CPF/CNPJ, last four characters only.
payer_prefilledarray of "name" | "contact" | "external_reference" | "document" | "address"yesWhich payer fields were prefilled at create. Their values are never returned.
published_atstring,nullyes—
receiverobjectyesThe name the payer sees on the hosted page: the consumer's display name, else the organization's name. The same text the public read answers.
state"draft" | "published" | "paused" | "archived"yes—
updated_atstringyes—
urlstringyesThe hosted page for this link.
valid_untilstring,nullyes—
versionobject,nullyesThe published version in force.
Example request
curl -X POST https://api.codespar.dev/v1/collect/links \
  -H "Authorization: Bearer $CODESPAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "consumer_id": "csm_0000000000000000",
       "valid_until": "2026-01-15T12:00:00.000Z",
       "version": {
         "title": "Example",
         "description": "string",
         "success_message": "string",
         "items": [
           {
             "name": "Example",
             "quantity": 0,
             "unit_amount_minor": 1000
           }
         ],
         "brand": {
           "logo_url": "https://example.com/hook",
           "color": "string",
           "text_color": "string",
           "texts": {
             "header": "string",
             "footer": "string"
           }
         },
         "surfaces": [
           "page"
         ],
         "due_in_days": 0,
         "payer_fields": {
           "contact": "optional",
           "external_reference": "off"
         },
         "usdc_price": "string"
       },
       "payer": {
         "name": "Example",
         "contact": "string",
         "external_reference": "string",
         "document": "string",
         "address": {
           "publicArea": "string",
           "number": "string",
           "neighborhood": "string",
           "city": "string",
           "state": "string",
           "postalCode": "string"
         }
       }
     }'
POST /v1/collect/links HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
Content-Type: application/json

{
  "consumer_id": "csm_0000000000000000",
  "valid_until": "2026-01-15T12:00:00.000Z",
  "version": {
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "brand": {
      "logo_url": "https://example.com/hook",
      "color": "string",
      "text_color": "string",
      "texts": {
        "header": "string",
        "footer": "string"
      }
    },
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "contact": "optional",
      "external_reference": "off"
    },
    "usdc_price": "string"
  },
  "payer": {
    "name": "Example",
    "contact": "string",
    "external_reference": "string",
    "document": "string",
    "address": {
      "publicArea": "string",
      "number": "string",
      "neighborhood": "string",
      "city": "string",
      "state": "string",
      "postalCode": "string"
    }
  }
}
import os
import requests

res = requests.post(
    "https://api.codespar.dev/v1/collect/links",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
    json={
      "consumer_id": "csm_0000000000000000",
      "valid_until": "2026-01-15T12:00:00.000Z",
      "version": {
        "title": "Example",
        "description": "string",
        "success_message": "string",
        "items": [
          {
            "name": "Example",
            "quantity": 0,
            "unit_amount_minor": 1000
          }
        ],
        "brand": {
          "logo_url": "https://example.com/hook",
          "color": "string",
          "text_color": "string",
          "texts": {
            "header": "string",
            "footer": "string"
          }
        },
        "surfaces": [
          "page"
        ],
        "due_in_days": 0,
        "payer_fields": {
          "contact": "optional",
          "external_reference": "off"
        },
        "usdc_price": "string"
      },
      "payer": {
        "name": "Example",
        "contact": "string",
        "external_reference": "string",
        "document": "string",
        "address": {
          "publicArea": "string",
          "number": "string",
          "neighborhood": "string",
          "city": "string",
          "state": "string",
          "postalCode": "string"
        }
      }
    },
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/links", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "consumer_id": "csm_0000000000000000",
    "valid_until": "2026-01-15T12:00:00.000Z",
    "version": {
      "title": "Example",
      "description": "string",
      "success_message": "string",
      "items": [
        {
          "name": "Example",
          "quantity": 0,
          "unit_amount_minor": 1000
        }
      ],
      "brand": {
        "logo_url": "https://example.com/hook",
        "color": "string",
        "text_color": "string",
        "texts": {
          "header": "string",
          "footer": "string"
        }
      },
      "surfaces": [
        "page"
      ],
      "due_in_days": 0,
      "payer_fields": {
        "contact": "optional",
        "external_reference": "off"
      },
      "usdc_price": "string"
    },
    "payer": {
      "name": "Example",
      "contact": "string",
      "external_reference": "string",
      "document": "string",
      "address": {
        "publicArea": "string",
        "number": "string",
        "neighborhood": "string",
        "city": "string",
        "state": "string",
        "postalCode": "string"
      }
    }
  }),
});

const data = await res.json();
const result = await cs.api.post("/v1/collect/links", {
  body: {
    consumer_id: "csm_0000000000000000",
    valid_until: "2026-01-15T12:00:00.000Z",
    version: {
      title: "Example",
      description: "string",
      success_message: "string",
      items: [
        {
          name: "Example",
          quantity: 0,
          unit_amount_minor: 1000
        }
      ],
      brand: {
        logo_url: "https://example.com/hook",
        color: "string",
        text_color: "string",
        texts: {
          header: "string",
          footer: "string"
        }
      },
      surfaces: [
        "page"
      ],
      due_in_days: 0,
      payer_fields: {
        contact: "optional",
        external_reference: "off"
      },
      usdc_price: "string"
    },
    payer: {
      name: "Example",
      contact: "string",
      external_reference: "string",
      document: "string",
      address: {
        publicArea: "string",
        number: "string",
        neighborhood: "string",
        city: "string",
        state: "string",
        postalCode: "string"
      }
    }
  }
});
Example response 201
application/json
{
  "id": "obj_0000000000000000",
  "object": "collect_link",
  "state": "draft",
  "environment": "live",
  "consumer_id": "csm_0000000000000000",
  "receiver": {
    "name": "Example"
  },
  "paid": true,
  "paid_at": "string",
  "current_version": 0,
  "valid_until": "string",
  "url": "https://example.com/hook",
  "payer_prefilled": [
    "name"
  ],
  "payer_document_masked": "string",
  "version": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "draft": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "created_at": "string",
  "updated_at": "string",
  "published_at": "string",
  "paused_at": "string",
  "archived_at": "string",
  "agent": {
    "url": "https://example.com/hook",
    "status": "ready",
    "reason": "string",
    "challenge": {},
    "refusal": {
      "code": "string",
      "message": "string",
      "http_status": 0
    },
    "usdc": {
      "price": "string",
      "amount": "1000",
      "currency": "USDC",
      "network": "string",
      "asset": "string",
      "payable": false,
      "reason": "usdc_pay_to_unavailable",
      "message": "string",
      "statement": "string"
    }
  }
}

GET /v1/collect/links/stats

GEThttps://api.codespar.dev/v1/collect/links/stats

The project's Collect numbers over the last 30 days

One read for the Collect screen's figures, over [to - 30 days, to) by paid_at. Only paid payments count as received: a late or duplicate payment is credited too, but it is a refund obligation, not revenue. by_surface is the surface of the attempt each payment paid.

previous_received_minor is the same sum over the 30 days before, and null when the project has no paid payment before from (no history to compare against; 0 would read as a real drop). links lists every link with a paid payment or an attempt in the window, most received first; a link with neither is absent.

Query parameters

NameTypeRequiredDescription
window"30d"no—

Responses

StatusBodyDescription
200objectOK
400objectBad Request.

Response 200

FieldTypeRequiredDescription
by_surfaceobjectyes—
currency"BRL"yes—
fromstringyes—
linksarray of objectyes—
paymentsintegeryesPaid payments in the window.
previous_received_minorinteger,nullyes—
received_minorintegeryes—
tostringyes—
window"30d"yes—
Example request
curl -X GET https://api.codespar.dev/v1/collect/links/stats \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
GET /v1/collect/links/stats HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.get(
    "https://api.codespar.dev/v1/collect/links/stats",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/links/stats", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.get("/v1/collect/links/stats");
Example response 200
application/json
{
  "window": "30d",
  "from": "string",
  "to": "string",
  "currency": "BRL",
  "received_minor": 1,
  "previous_received_minor": 1,
  "payments": 0,
  "by_surface": {
    "page": 0,
    "whatsapp": 0
  },
  "links": [
    {
      "link_id": "link_0000000000000000",
      "received_minor": 1,
      "payments": 0,
      "attempts": 0,
      "by_surface": {
        "page": 0,
        "whatsapp": 0
      },
      "paid": true
    }
  ]
}

GET /v1/collect/links/{linkId}

GEThttps://api.codespar.dev/v1/collect/links/{linkId}

Read a Collect link

Path parameters

NameTypeRequiredDescription
linkIdstringyes—

Responses

StatusBodyDescription
200objectOK
404objectNot Found. No link with that id in this project. A link of another project answers identically.

Response 200

FieldTypeRequiredDescription
agentobject,nullnoThe agent surface (402), on the single-link read: null when the version in force does not enable it.
archived_atstring,nullyes—
consumer_idstringyesThe receiving consumer: the charge settles into its wallet.
created_atstringyes—
current_versioninteger,nullyes—
draftobject,nullyesThe open draft, if any.
environment"live" | "test"yes—
idstringyescl_ + 128 random bits. Minted by the server; never chosen by the caller.
object"collect_link"yes—
paidbooleanyesWhether the link has its paid payment, whenever it settled (not bound to any stats window). A late or duplicate payment is not the link's payment and does not make it paid.
paid_atstring,nullyesWhen the paid payment settled; null while unpaid.
paused_atstring,nullyes—
payer_document_maskedstring,nullyesThe prefilled CPF/CNPJ, last four characters only.
payer_prefilledarray of "name" | "contact" | "external_reference" | "document" | "address"yesWhich payer fields were prefilled at create. Their values are never returned.
published_atstring,nullyes—
receiverobjectyesThe name the payer sees on the hosted page: the consumer's display name, else the organization's name. The same text the public read answers.
state"draft" | "published" | "paused" | "archived"yes—
updated_atstringyes—
urlstringyesThe hosted page for this link.
valid_untilstring,nullyes—
versionobject,nullyesThe published version in force.
Example request
curl -X GET https://api.codespar.dev/v1/collect/links/{linkId} \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
GET /v1/collect/links/{linkId} HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.get(
    "https://api.codespar.dev/v1/collect/links/{linkId}",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/links/{linkId}", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.get("/v1/collect/links/{linkId}", {
  path: {
    linkId: "link_0000000000000000"
  }
});
Example response 200
application/json
{
  "id": "obj_0000000000000000",
  "object": "collect_link",
  "state": "draft",
  "environment": "live",
  "consumer_id": "csm_0000000000000000",
  "receiver": {
    "name": "Example"
  },
  "paid": true,
  "paid_at": "string",
  "current_version": 0,
  "valid_until": "string",
  "url": "https://example.com/hook",
  "payer_prefilled": [
    "name"
  ],
  "payer_document_masked": "string",
  "version": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "draft": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "created_at": "string",
  "updated_at": "string",
  "published_at": "string",
  "paused_at": "string",
  "archived_at": "string",
  "agent": {
    "url": "https://example.com/hook",
    "status": "ready",
    "reason": "string",
    "challenge": {},
    "refusal": {
      "code": "string",
      "message": "string",
      "http_status": 0
    },
    "usdc": {
      "price": "string",
      "amount": "1000",
      "currency": "USDC",
      "network": "string",
      "asset": "string",
      "payable": false,
      "reason": "usdc_pay_to_unavailable",
      "message": "string",
      "statement": "string"
    }
  }
}

PATCH /v1/collect/links/{linkId}

PATCHhttps://api.codespar.dev/v1/collect/links/{linkId}

Change a draft link's validity or receiving consumer

Only while the link has never been published (state: draft). Once published, the validity and the receiving consumer are fixed with what payers were shown, and this answers 409 collect_link_published_immutable (an archived link: collect_link_archived); a different charge is a new link.

A new consumer_id is asked the publish gate's question first, in the link's environment, and refused with the same 422 receiving_identity_missing; the link is left as it was. valid_until: null clears the validity. At least one field.

Path parameters

NameTypeRequiredDescription
linkIdstringyes—

Request body

FieldTypeRequiredDescription
consumer_idstringno—
valid_untilstring,null (date-time)no—

Responses

StatusBodyDescription
200objectOK
400objectBad Request. The body did not match the schema (invalid_body, with details.issues), or the version breaks a rule the schema cannot state: the items total below the R$5.00 a Pix with due date needs (collect_total_below_minimum), above R$1,000,000.00 (collect_total_above_maximum), or brand colors whose contrast is below 4.5:1 (collect_brand_contrast_insufficient), or a usdc_price on a version without the agent surface (collect_usdc_price_requires_agent). Unknown keys are refused, not dropped: the regulated payer fields (document, address) are never free-text questions.
404objectNot Found. No link with that id in this project. A link of another project answers identically.
409objectThe link was published (or archived): its settings are fixed.
422objectThe new consumer cannot receive a Pix with due date in the link's environment.

Response 200

FieldTypeRequiredDescription
agentobject,nullnoThe agent surface (402), on the single-link read: null when the version in force does not enable it.
archived_atstring,nullyes—
consumer_idstringyesThe receiving consumer: the charge settles into its wallet.
created_atstringyes—
current_versioninteger,nullyes—
draftobject,nullyesThe open draft, if any.
environment"live" | "test"yes—
idstringyescl_ + 128 random bits. Minted by the server; never chosen by the caller.
object"collect_link"yes—
paidbooleanyesWhether the link has its paid payment, whenever it settled (not bound to any stats window). A late or duplicate payment is not the link's payment and does not make it paid.
paid_atstring,nullyesWhen the paid payment settled; null while unpaid.
paused_atstring,nullyes—
payer_document_maskedstring,nullyesThe prefilled CPF/CNPJ, last four characters only.
payer_prefilledarray of "name" | "contact" | "external_reference" | "document" | "address"yesWhich payer fields were prefilled at create. Their values are never returned.
published_atstring,nullyes—
receiverobjectyesThe name the payer sees on the hosted page: the consumer's display name, else the organization's name. The same text the public read answers.
state"draft" | "published" | "paused" | "archived"yes—
updated_atstringyes—
urlstringyesThe hosted page for this link.
valid_untilstring,nullyes—
versionobject,nullyesThe published version in force.
Example request
curl -X PATCH https://api.codespar.dev/v1/collect/links/{linkId} \
  -H "Authorization: Bearer $CODESPAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "valid_until": "2026-01-15T12:00:00.000Z",
       "consumer_id": "csm_0000000000000000"
     }'
PATCH /v1/collect/links/{linkId} HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
Content-Type: application/json

{
  "valid_until": "2026-01-15T12:00:00.000Z",
  "consumer_id": "csm_0000000000000000"
}
import os
import requests

res = requests.patch(
    "https://api.codespar.dev/v1/collect/links/{linkId}",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
    json={
      "valid_until": "2026-01-15T12:00:00.000Z",
      "consumer_id": "csm_0000000000000000"
    },
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/links/{linkId}", {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "valid_until": "2026-01-15T12:00:00.000Z",
    "consumer_id": "csm_0000000000000000"
  }),
});

const data = await res.json();
const r = await cs.api.response("patch", "/v1/collect/links/{linkId}", {
  path: {
    linkId: "link_0000000000000000"
  },
  body: {
    valid_until: "2026-01-15T12:00:00.000Z",
    consumer_id: "csm_0000000000000000"
  }
});
// r.status is one of the documented statuses (200, 422),
// each with its own body shape in r.data; nothing here throws on 422.
if (r.ok) {
  console.log(r.data);
}
Example response 200
application/json
{
  "id": "obj_0000000000000000",
  "object": "collect_link",
  "state": "draft",
  "environment": "live",
  "consumer_id": "csm_0000000000000000",
  "receiver": {
    "name": "Example"
  },
  "paid": true,
  "paid_at": "string",
  "current_version": 0,
  "valid_until": "string",
  "url": "https://example.com/hook",
  "payer_prefilled": [
    "name"
  ],
  "payer_document_masked": "string",
  "version": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "draft": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "created_at": "string",
  "updated_at": "string",
  "published_at": "string",
  "paused_at": "string",
  "archived_at": "string",
  "agent": {
    "url": "https://example.com/hook",
    "status": "ready",
    "reason": "string",
    "challenge": {},
    "refusal": {
      "code": "string",
      "message": "string",
      "http_status": 0
    },
    "usdc": {
      "price": "string",
      "amount": "1000",
      "currency": "USDC",
      "network": "string",
      "asset": "string",
      "payable": false,
      "reason": "usdc_pay_to_unavailable",
      "message": "string",
      "statement": "string"
    }
  }
}

POST /v1/collect/links/{linkId}/archive

POSThttps://api.codespar.dev/v1/collect/links/{linkId}/archive

Archive a Collect link

Terminal. The link takes no new version and issues nothing.

Path parameters

NameTypeRequiredDescription
linkIdstringyes—

Responses

StatusBodyDescription
200objectOK
404objectNot Found. No link with that id in this project. A link of another project answers identically.

Response 200

FieldTypeRequiredDescription
agentobject,nullnoThe agent surface (402), on the single-link read: null when the version in force does not enable it.
archived_atstring,nullyes—
changedbooleanyesFalse when the link was already in the requested state (the call was a no-op).
consumer_idstringyesThe receiving consumer: the charge settles into its wallet.
created_atstringyes—
current_versioninteger,nullyes—
draftobject,nullyesThe open draft, if any.
environment"live" | "test"yes—
idstringyescl_ + 128 random bits. Minted by the server; never chosen by the caller.
object"collect_link"yes—
paidbooleanyesWhether the link has its paid payment, whenever it settled (not bound to any stats window). A late or duplicate payment is not the link's payment and does not make it paid.
paid_atstring,nullyesWhen the paid payment settled; null while unpaid.
paused_atstring,nullyes—
payer_document_maskedstring,nullyesThe prefilled CPF/CNPJ, last four characters only.
payer_prefilledarray of "name" | "contact" | "external_reference" | "document" | "address"yesWhich payer fields were prefilled at create. Their values are never returned.
published_atstring,nullyes—
receiverobjectyesThe name the payer sees on the hosted page: the consumer's display name, else the organization's name. The same text the public read answers.
state"draft" | "published" | "paused" | "archived"yes—
updated_atstringyes—
urlstringyesThe hosted page for this link.
valid_untilstring,nullyes—
versionobject,nullyesThe published version in force.
Example request
curl -X POST https://api.codespar.dev/v1/collect/links/{linkId}/archive \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
POST /v1/collect/links/{linkId}/archive HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.post(
    "https://api.codespar.dev/v1/collect/links/{linkId}/archive",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/links/{linkId}/archive", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.post("/v1/collect/links/{linkId}/archive", {
  path: {
    linkId: "link_0000000000000000"
  }
});
Example response 200
application/json
{
  "id": "obj_0000000000000000",
  "object": "collect_link",
  "state": "draft",
  "environment": "live",
  "consumer_id": "csm_0000000000000000",
  "receiver": {
    "name": "Example"
  },
  "paid": true,
  "paid_at": "string",
  "current_version": 0,
  "valid_until": "string",
  "url": "https://example.com/hook",
  "payer_prefilled": [
    "name"
  ],
  "payer_document_masked": "string",
  "version": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "draft": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "created_at": "string",
  "updated_at": "string",
  "published_at": "string",
  "paused_at": "string",
  "archived_at": "string",
  "agent": {
    "url": "https://example.com/hook",
    "status": "ready",
    "reason": "string",
    "challenge": {},
    "refusal": {
      "code": "string",
      "message": "string",
      "http_status": 0
    },
    "usdc": {
      "price": "string",
      "amount": "1000",
      "currency": "USDC",
      "network": "string",
      "asset": "string",
      "payable": false,
      "reason": "usdc_pay_to_unavailable",
      "message": "string",
      "statement": "string"
    }
  },
  "changed": true
}

GET /v1/collect/links/{linkId}/attempts

GEThttps://api.codespar.dev/v1/collect/links/{linkId}/attempts

List a Collect link's attempts

Newest first. No payer data and no copia-e-cola: an attempt's state, charge, amount and due date only.

Path parameters

NameTypeRequiredDescription
linkIdstringyes—

Responses

StatusBodyDescription
200objectOK
404objectNot Found. No link with that id in this project. A link of another project answers identically.

Response 200

FieldTypeRequiredDescription
dataarray of objectyes—
Example request
curl -X GET https://api.codespar.dev/v1/collect/links/{linkId}/attempts \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
GET /v1/collect/links/{linkId}/attempts HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.get(
    "https://api.codespar.dev/v1/collect/links/{linkId}/attempts",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/links/{linkId}/attempts", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.get("/v1/collect/links/{linkId}/attempts", {
  path: {
    linkId: "link_0000000000000000"
  }
});
Example response 200
application/json
{
  "data": [
    {
      "id": "obj_0000000000000000",
      "object": "collect_attempt",
      "link_id": "link_0000000000000000",
      "version": 0,
      "surface": "page",
      "state": "issuing",
      "charge_id": "charge_0000000000000000",
      "amount_minor": 1000,
      "currency": "BRL",
      "due_date": "string",
      "expires_at": "string",
      "ready_at": "string",
      "superseded_by": "string",
      "failure_code": "string",
      "created_at": "string",
      "closed_at": "string"
    }
  ]
}

POST /v1/collect/links/{linkId}/attempts

POSThttps://api.codespar.dev/v1/collect/links/{linkId}/attempts

Issue a Pix attempt for the partner's channel

Issues a payable Pix with due date on a published link, for the partner's own channel (surface whatsapp by default). Same rules as the hosted page's POST: the amount is the published version's, the payer fields not prefilled are sent here, one live attempt per link (collect_attempt_exists), and renew: true replaces the open attempt only after its charge was cancelled at the issuer. idempotency_key (or the Idempotency-Key header) makes a retry answer the same attempt.

The attempt starts issuing: the copia-e-cola appears 30 s to 60 min later. Read it with the artifact route, or subscribe to collect.attempt.ready.

Path parameters

NameTypeRequiredDescription
linkIdstringyes—

Request body

FieldTypeRequiredDescription
idempotency_keystringno—
payerobjectno—
renewbooleanno—
surface"whatsapp" | "page"no—

Responses

StatusBodyDescription
200objectOK
201objectOK
400objectBad Request.
404objectNot Found. No link with that id in this project. A link of another project answers identically.
409objectConflict.
410objectThe link is past its validity.
422objectThe issuer refused the charge before it existed; details.failure_code says why.

Response 200

FieldTypeRequiredDescription
amount_minorintegeryes—
charge_idstring,nullyes—
closed_atstring,nullyes—
created_atstringyes—
currency"BRL"yes—
due_datestringyes—
expires_atstringyes—
failure_codestring,nullyes—
idstringyescla_ + 128 random bits. The charge is created under idempotency_key = collect:<id>.
link_idstringyes—
object"collect_attempt"yes—
ready_atstring,nullyes—
replaytrueyes—
state"issuing" | "open" | "superseded" | "expired" | "cancelled" | "paid" | "failed"yesissuing until the copia-e-cola exists (30 s to 60 min after the charge is created); open once it does; failed when it never did (failure_code).
supersededstring,nullyes—
superseded_bystring,nullyes—
surface"page" | "whatsapp"yes—
versionintegeryes—
Example request
curl -X POST https://api.codespar.dev/v1/collect/links/{linkId}/attempts \
  -H "Authorization: Bearer $CODESPAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "surface": "whatsapp",
       "payer": {},
       "renew": false,
       "idempotency_key": "string"
     }'
POST /v1/collect/links/{linkId}/attempts HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
Content-Type: application/json

{
  "surface": "whatsapp",
  "payer": {},
  "renew": false,
  "idempotency_key": "string"
}
import os
import requests

res = requests.post(
    "https://api.codespar.dev/v1/collect/links/{linkId}/attempts",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
    json={
      "surface": "whatsapp",
      "payer": {},
      "renew": False,
      "idempotency_key": "string"
    },
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/links/{linkId}/attempts", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "surface": "whatsapp",
    "payer": {},
    "renew": false,
    "idempotency_key": "string"
  }),
});

const data = await res.json();
const r = await cs.api.response("post", "/v1/collect/links/{linkId}/attempts", {
  path: {
    linkId: "link_0000000000000000"
  },
  body: {
    surface: "whatsapp",
    payer: {},
    renew: false,
    idempotency_key: "string"
  }
});
// r.status is one of the documented statuses (200, 422),
// each with its own body shape in r.data; nothing here throws on 422.
if (r.ok) {
  console.log(r.data);
}
Example response 200
application/json
{
  "id": "obj_0000000000000000",
  "object": "collect_attempt",
  "link_id": "link_0000000000000000",
  "version": 0,
  "surface": "page",
  "state": "issuing",
  "charge_id": "charge_0000000000000000",
  "amount_minor": 1000,
  "currency": "BRL",
  "due_date": "string",
  "expires_at": "string",
  "ready_at": "string",
  "superseded_by": "string",
  "failure_code": "string",
  "created_at": "string",
  "closed_at": "string",
  "replay": true,
  "superseded": "string"
}

PUT /v1/collect/links/{linkId}/draft

PUThttps://api.codespar.dev/v1/collect/links/{linkId}/draft

Replace the draft of a Collect link

Replaces the open draft, or opens a new draft after the last publish. A published version never changes. Refused on an archived link, and on a link that already issued a Pix to a payer (collect_link_version_locked): a single-use link keeps the version it was issued under.

Path parameters

NameTypeRequiredDescription
linkIdstringyes—

Request body

FieldTypeRequiredDescription
brandobjectno—
descriptionstringno—
due_in_daysintegeryes—
itemsarray of objectyes—
payer_fieldsobjectno—
success_messagestringno—
surfacesarray of "page" | "whatsapp" | "agent"yes—
titlestringyes—
usdc_pricestringno—

Responses

StatusBodyDescription
200objectOK
400objectBad Request. The body did not match the schema (invalid_body, with details.issues), or the version breaks a rule the schema cannot state: the items total below the R$5.00 a Pix with due date needs (collect_total_below_minimum), above R$1,000,000.00 (collect_total_above_maximum), or brand colors whose contrast is below 4.5:1 (collect_brand_contrast_insufficient), or a usdc_price on a version without the agent surface (collect_usdc_price_requires_agent). Unknown keys are refused, not dropped: the regulated payer fields (document, address) are never free-text questions.
404objectNot Found. No link with that id in this project. A link of another project answers identically.
409objectConflict.

Response 200

FieldTypeRequiredDescription
agentobject,nullnoThe agent surface (402), on the single-link read: null when the version in force does not enable it.
archived_atstring,nullyes—
consumer_idstringyesThe receiving consumer: the charge settles into its wallet.
created_atstringyes—
current_versioninteger,nullyes—
draftobject,nullyesThe open draft, if any.
environment"live" | "test"yes—
idstringyescl_ + 128 random bits. Minted by the server; never chosen by the caller.
object"collect_link"yes—
paidbooleanyesWhether the link has its paid payment, whenever it settled (not bound to any stats window). A late or duplicate payment is not the link's payment and does not make it paid.
paid_atstring,nullyesWhen the paid payment settled; null while unpaid.
paused_atstring,nullyes—
payer_document_maskedstring,nullyesThe prefilled CPF/CNPJ, last four characters only.
payer_prefilledarray of "name" | "contact" | "external_reference" | "document" | "address"yesWhich payer fields were prefilled at create. Their values are never returned.
published_atstring,nullyes—
receiverobjectyesThe name the payer sees on the hosted page: the consumer's display name, else the organization's name. The same text the public read answers.
state"draft" | "published" | "paused" | "archived"yes—
updated_atstringyes—
urlstringyesThe hosted page for this link.
valid_untilstring,nullyes—
versionobject,nullyesThe published version in force.
Example request
curl -X PUT https://api.codespar.dev/v1/collect/links/{linkId}/draft \
  -H "Authorization: Bearer $CODESPAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "title": "Example",
       "description": "string",
       "success_message": "string",
       "items": [
         {
           "name": "Example",
           "quantity": 0,
           "unit_amount_minor": 1000
         }
       ],
       "brand": {
         "logo_url": "https://example.com/hook",
         "color": "string",
         "text_color": "string",
         "texts": {
           "header": "string",
           "footer": "string"
         }
       },
       "surfaces": [
         "page"
       ],
       "due_in_days": 0,
       "payer_fields": {
         "contact": "optional",
         "external_reference": "off"
       },
       "usdc_price": "string"
     }'
PUT /v1/collect/links/{linkId}/draft HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
Content-Type: application/json

{
  "title": "Example",
  "description": "string",
  "success_message": "string",
  "items": [
    {
      "name": "Example",
      "quantity": 0,
      "unit_amount_minor": 1000
    }
  ],
  "brand": {
    "logo_url": "https://example.com/hook",
    "color": "string",
    "text_color": "string",
    "texts": {
      "header": "string",
      "footer": "string"
    }
  },
  "surfaces": [
    "page"
  ],
  "due_in_days": 0,
  "payer_fields": {
    "contact": "optional",
    "external_reference": "off"
  },
  "usdc_price": "string"
}
import os
import requests

res = requests.put(
    "https://api.codespar.dev/v1/collect/links/{linkId}/draft",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
    json={
      "title": "Example",
      "description": "string",
      "success_message": "string",
      "items": [
        {
          "name": "Example",
          "quantity": 0,
          "unit_amount_minor": 1000
        }
      ],
      "brand": {
        "logo_url": "https://example.com/hook",
        "color": "string",
        "text_color": "string",
        "texts": {
          "header": "string",
          "footer": "string"
        }
      },
      "surfaces": [
        "page"
      ],
      "due_in_days": 0,
      "payer_fields": {
        "contact": "optional",
        "external_reference": "off"
      },
      "usdc_price": "string"
    },
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/links/{linkId}/draft", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "brand": {
      "logo_url": "https://example.com/hook",
      "color": "string",
      "text_color": "string",
      "texts": {
        "header": "string",
        "footer": "string"
      }
    },
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "contact": "optional",
      "external_reference": "off"
    },
    "usdc_price": "string"
  }),
});

const data = await res.json();
const result = await cs.api.put("/v1/collect/links/{linkId}/draft", {
  path: {
    linkId: "link_0000000000000000"
  },
  body: {
    title: "Example",
    description: "string",
    success_message: "string",
    items: [
      {
        name: "Example",
        quantity: 0,
        unit_amount_minor: 1000
      }
    ],
    brand: {
      logo_url: "https://example.com/hook",
      color: "string",
      text_color: "string",
      texts: {
        header: "string",
        footer: "string"
      }
    },
    surfaces: [
      "page"
    ],
    due_in_days: 0,
    payer_fields: {
      contact: "optional",
      external_reference: "off"
    },
    usdc_price: "string"
  }
});
Example response 200
application/json
{
  "id": "obj_0000000000000000",
  "object": "collect_link",
  "state": "draft",
  "environment": "live",
  "consumer_id": "csm_0000000000000000",
  "receiver": {
    "name": "Example"
  },
  "paid": true,
  "paid_at": "string",
  "current_version": 0,
  "valid_until": "string",
  "url": "https://example.com/hook",
  "payer_prefilled": [
    "name"
  ],
  "payer_document_masked": "string",
  "version": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "draft": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "created_at": "string",
  "updated_at": "string",
  "published_at": "string",
  "paused_at": "string",
  "archived_at": "string",
  "agent": {
    "url": "https://example.com/hook",
    "status": "ready",
    "reason": "string",
    "challenge": {},
    "refusal": {
      "code": "string",
      "message": "string",
      "http_status": 0
    },
    "usdc": {
      "price": "string",
      "amount": "1000",
      "currency": "USDC",
      "network": "string",
      "asset": "string",
      "payable": false,
      "reason": "usdc_pay_to_unavailable",
      "message": "string",
      "statement": "string"
    }
  }
}

POST /v1/collect/links/{linkId}/pause

POSThttps://api.codespar.dev/v1/collect/links/{linkId}/pause

Pause a Collect link

No new attempt is issued while paused, and payers see the link as paused. An attempt already issued can still be paid; that payment is credited. Emits collect.link.paused.

Path parameters

NameTypeRequiredDescription
linkIdstringyes—

Responses

StatusBodyDescription
200objectOK
404objectNot Found. No link with that id in this project. A link of another project answers identically.
409objectConflict: the link is not published.

Response 200

FieldTypeRequiredDescription
agentobject,nullnoThe agent surface (402), on the single-link read: null when the version in force does not enable it.
archived_atstring,nullyes—
changedbooleanyesFalse when the link was already in the requested state (the call was a no-op).
consumer_idstringyesThe receiving consumer: the charge settles into its wallet.
created_atstringyes—
current_versioninteger,nullyes—
draftobject,nullyesThe open draft, if any.
environment"live" | "test"yes—
idstringyescl_ + 128 random bits. Minted by the server; never chosen by the caller.
object"collect_link"yes—
paidbooleanyesWhether the link has its paid payment, whenever it settled (not bound to any stats window). A late or duplicate payment is not the link's payment and does not make it paid.
paid_atstring,nullyesWhen the paid payment settled; null while unpaid.
paused_atstring,nullyes—
payer_document_maskedstring,nullyesThe prefilled CPF/CNPJ, last four characters only.
payer_prefilledarray of "name" | "contact" | "external_reference" | "document" | "address"yesWhich payer fields were prefilled at create. Their values are never returned.
published_atstring,nullyes—
receiverobjectyesThe name the payer sees on the hosted page: the consumer's display name, else the organization's name. The same text the public read answers.
state"draft" | "published" | "paused" | "archived"yes—
updated_atstringyes—
urlstringyesThe hosted page for this link.
valid_untilstring,nullyes—
versionobject,nullyesThe published version in force.
Example request
curl -X POST https://api.codespar.dev/v1/collect/links/{linkId}/pause \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
POST /v1/collect/links/{linkId}/pause HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.post(
    "https://api.codespar.dev/v1/collect/links/{linkId}/pause",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/links/{linkId}/pause", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.post("/v1/collect/links/{linkId}/pause", {
  path: {
    linkId: "link_0000000000000000"
  }
});
Example response 200
application/json
{
  "id": "obj_0000000000000000",
  "object": "collect_link",
  "state": "draft",
  "environment": "live",
  "consumer_id": "csm_0000000000000000",
  "receiver": {
    "name": "Example"
  },
  "paid": true,
  "paid_at": "string",
  "current_version": 0,
  "valid_until": "string",
  "url": "https://example.com/hook",
  "payer_prefilled": [
    "name"
  ],
  "payer_document_masked": "string",
  "version": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "draft": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "created_at": "string",
  "updated_at": "string",
  "published_at": "string",
  "paused_at": "string",
  "archived_at": "string",
  "agent": {
    "url": "https://example.com/hook",
    "status": "ready",
    "reason": "string",
    "challenge": {},
    "refusal": {
      "code": "string",
      "message": "string",
      "http_status": 0
    },
    "usdc": {
      "price": "string",
      "amount": "1000",
      "currency": "USDC",
      "network": "string",
      "asset": "string",
      "payable": false,
      "reason": "usdc_pay_to_unavailable",
      "message": "string",
      "statement": "string"
    }
  },
  "changed": true
}

GET /v1/collect/links/{linkId}/payments

GEThttps://api.codespar.dev/v1/collect/links/{linkId}/payments

List a Collect link's payments

Every payment of the link's charges: the one paid (a single-use link has at most one) and any exceptions. Each is recorded in the same transaction as the wallet credit, keyed on the charge id, and carries its signed receipt once minted.

Path parameters

NameTypeRequiredDescription
linkIdstringyes—

Responses

StatusBodyDescription
200objectOK
404objectNot Found. No link with that id in this project. A link of another project answers identically.

Response 200

FieldTypeRequiredDescription
dataarray of objectyes—
Example request
curl -X GET https://api.codespar.dev/v1/collect/links/{linkId}/payments \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
GET /v1/collect/links/{linkId}/payments HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.get(
    "https://api.codespar.dev/v1/collect/links/{linkId}/payments",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/links/{linkId}/payments", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.get("/v1/collect/links/{linkId}/payments", {
  path: {
    linkId: "link_0000000000000000"
  }
});
Example response 200
application/json
{
  "data": [
    {
      "id": "obj_0000000000000000",
      "object": "collect_payment",
      "kind": "paid",
      "exception": "late",
      "link_id": "link_0000000000000000",
      "attempt_id": "attempt_0000000000000000",
      "surface": "page",
      "version": 0,
      "charge_id": "charge_0000000000000000",
      "amount_minor": 1000,
      "currency": "BRL",
      "paid_at": "string",
      "rail": "pix",
      "end_to_end_id": "endtoend_0000000000000000",
      "ledger_entry_id": "ledgerentry_0000000000000000",
      "simulated": true,
      "receipt": {
        "id": "obj_0000000000000000",
        "object": "collect_receipt",
        "document": {
          "v": 1,
          "receipt_id": "receipt_0000000000000000",
          "issuer": "string",
          "charge_id": "charge_0000000000000000",
          "link_id": "link_0000000000000000",
          "link_version": 0,
          "amount_minor": 1000,
          "currency": "BRL",
          "paid_at": "string",
          "rail": "pix",
          "end_to_end_id": "endtoend_0000000000000000",
          "ledger_entry_id": "ledgerentry_0000000000000000"
        },
        "digest": "string",
        "sig": "string",
        "kid": "string",
        "recipe": {}
      }
    }
  ]
}

POST /v1/collect/links/{linkId}/publish

POSThttps://api.codespar.dev/v1/collect/links/{linkId}/publish

Publish a Collect link

Freezes the draft as the version in force and puts the link in front of payers; emits collect.link.published.

GATED ON THE RECEIVER. The owner's consumer must be able to receive a Pix with due date in the link's environment: its own receiving identity, or, in a test project, the shared-sandbox receiver seeded on this deployment. Otherwise the publish is refused with 422 receiving_identity_missing before anything is written, and the link stays a draft. A link already published with no new draft answers 200 with changed: false.

CONFIRMED USDC PRICE (N12). A draft with a usdc_price publishes only when the body confirms that exact price (confirm_usdc_price); the confirmation is stored with the version (usdc_price_confirmed_at). A missing or different price, or a price confirmed for a draft that has none, answers 409 collect_usdc_price_unconfirmed with the draft's price and the statement the tenant confirms, and nothing is published. A different price is a new version and asks again.

Path parameters

NameTypeRequiredDescription
linkIdstringyes—

Request body

FieldTypeRequiredDescription
confirm_usdc_pricestring,nullno—

Responses

StatusBodyDescription
200objectOK
400objectBad Request. The body did not match the schema (invalid_body, with details.issues), or the version breaks a rule the schema cannot state: the items total below the R$5.00 a Pix with due date needs (collect_total_below_minimum), above R$1,000,000.00 (collect_total_above_maximum), or brand colors whose contrast is below 4.5:1 (collect_brand_contrast_insufficient), or a usdc_price on a version without the agent surface (collect_usdc_price_requires_agent). Unknown keys are refused, not dropped: the regulated payer fields (document, address) are never free-text questions.
404objectNot Found. No link with that id in this project. A link of another project answers identically.
409objectConflict.
422objectThe owner's consumer has no receiving identity in this environment.

Response 200

FieldTypeRequiredDescription
agentobject,nullnoThe agent surface (402), on the single-link read: null when the version in force does not enable it.
archived_atstring,nullyes—
changedbooleanyesFalse when the link was already in the requested state (the call was a no-op).
consumer_idstringyesThe receiving consumer: the charge settles into its wallet.
created_atstringyes—
current_versioninteger,nullyes—
draftobject,nullyesThe open draft, if any.
environment"live" | "test"yes—
idstringyescl_ + 128 random bits. Minted by the server; never chosen by the caller.
object"collect_link"yes—
paidbooleanyesWhether the link has its paid payment, whenever it settled (not bound to any stats window). A late or duplicate payment is not the link's payment and does not make it paid.
paid_atstring,nullyesWhen the paid payment settled; null while unpaid.
paused_atstring,nullyes—
payer_document_maskedstring,nullyesThe prefilled CPF/CNPJ, last four characters only.
payer_prefilledarray of "name" | "contact" | "external_reference" | "document" | "address"yesWhich payer fields were prefilled at create. Their values are never returned.
published_atstring,nullyes—
receiverobjectyesThe name the payer sees on the hosted page: the consumer's display name, else the organization's name. The same text the public read answers.
state"draft" | "published" | "paused" | "archived"yes—
updated_atstringyes—
urlstringyesThe hosted page for this link.
valid_untilstring,nullyes—
versionobject,nullyesThe published version in force.
Example request
curl -X POST https://api.codespar.dev/v1/collect/links/{linkId}/publish \
  -H "Authorization: Bearer $CODESPAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "confirm_usdc_price": "string"
     }'
POST /v1/collect/links/{linkId}/publish HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
Content-Type: application/json

{
  "confirm_usdc_price": "string"
}
import os
import requests

res = requests.post(
    "https://api.codespar.dev/v1/collect/links/{linkId}/publish",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
    json={
      "confirm_usdc_price": "string"
    },
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/links/{linkId}/publish", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "confirm_usdc_price": "string"
  }),
});

const data = await res.json();
const r = await cs.api.response("post", "/v1/collect/links/{linkId}/publish", {
  path: {
    linkId: "link_0000000000000000"
  },
  body: {
    confirm_usdc_price: "string"
  }
});
// r.status is one of the documented statuses (200, 422),
// each with its own body shape in r.data; nothing here throws on 422.
if (r.ok) {
  console.log(r.data);
}
Example response 200
application/json
{
  "id": "obj_0000000000000000",
  "object": "collect_link",
  "state": "draft",
  "environment": "live",
  "consumer_id": "csm_0000000000000000",
  "receiver": {
    "name": "Example"
  },
  "paid": true,
  "paid_at": "string",
  "current_version": 0,
  "valid_until": "string",
  "url": "https://example.com/hook",
  "payer_prefilled": [
    "name"
  ],
  "payer_document_masked": "string",
  "version": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "draft": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "created_at": "string",
  "updated_at": "string",
  "published_at": "string",
  "paused_at": "string",
  "archived_at": "string",
  "agent": {
    "url": "https://example.com/hook",
    "status": "ready",
    "reason": "string",
    "challenge": {},
    "refusal": {
      "code": "string",
      "message": "string",
      "http_status": 0
    },
    "usdc": {
      "price": "string",
      "amount": "1000",
      "currency": "USDC",
      "network": "string",
      "asset": "string",
      "payable": false,
      "reason": "usdc_pay_to_unavailable",
      "message": "string",
      "statement": "string"
    }
  },
  "changed": true
}

GET /v1/collect/links/{linkId}/refunds

GEThttps://api.codespar.dev/v1/collect/links/{linkId}/refunds

The refund obligations of a link's exception payments

A payment that is not the link's one valid payment (late or duplicate) is never kept as credit by default. Its refund obligation is recorded in the same transaction as the credit. A duplicate is due for refund at once. A late payment waits for the collector until decide_by (COLLECT_LATE_REFUND_DECISION_DAYS, 3 by default), and is due for refund if not honored. Events: collect.refund.awaiting_decision, collect.refund.required (with refund_method and manual), collect.refund.honored. No money moves yet: a Pix refund waits in awaiting_pix_rail, and a boleto one is manual_refund_required.

Path parameters

NameTypeRequiredDescription
linkIdstringyes—

Responses

StatusBodyDescription
200objectOK
404objectNot Found. No link with that id in this project. A link of another project answers identically.

Response 200

FieldTypeRequiredDescription
dataarray of objectyes—
Example request
curl -X GET https://api.codespar.dev/v1/collect/links/{linkId}/refunds \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
GET /v1/collect/links/{linkId}/refunds HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.get(
    "https://api.codespar.dev/v1/collect/links/{linkId}/refunds",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/links/{linkId}/refunds", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.get("/v1/collect/links/{linkId}/refunds", {
  path: {
    linkId: "link_0000000000000000"
  }
});
Example response 200
application/json
{
  "data": [
    {
      "id": "obj_0000000000000000",
      "object": "collect_refund",
      "payment_id": "payment_0000000000000000",
      "link_id": "link_0000000000000000",
      "charge_id": "charge_0000000000000000",
      "reason": "late",
      "refund_method": "pix",
      "state": "awaiting_collector",
      "amount_minor": 1000,
      "currency": "BRL",
      "decide_by": "string",
      "decided_at": "string",
      "created_at": "string"
    }
  ]
}

POST /v1/collect/links/{linkId}/resume

POSThttps://api.codespar.dev/v1/collect/links/{linkId}/resume

Resume a paused Collect link

Publishes the link again, re-checking the receiving identity first; emits collect.link.published with resumed: true.

Path parameters

NameTypeRequiredDescription
linkIdstringyes—

Responses

StatusBodyDescription
200objectOK
404objectNot Found. No link with that id in this project. A link of another project answers identically.
409objectConflict: the link is not paused.
422objectThe owner's consumer has no receiving identity in this environment.

Response 200

FieldTypeRequiredDescription
agentobject,nullnoThe agent surface (402), on the single-link read: null when the version in force does not enable it.
archived_atstring,nullyes—
changedbooleanyesFalse when the link was already in the requested state (the call was a no-op).
consumer_idstringyesThe receiving consumer: the charge settles into its wallet.
created_atstringyes—
current_versioninteger,nullyes—
draftobject,nullyesThe open draft, if any.
environment"live" | "test"yes—
idstringyescl_ + 128 random bits. Minted by the server; never chosen by the caller.
object"collect_link"yes—
paidbooleanyesWhether the link has its paid payment, whenever it settled (not bound to any stats window). A late or duplicate payment is not the link's payment and does not make it paid.
paid_atstring,nullyesWhen the paid payment settled; null while unpaid.
paused_atstring,nullyes—
payer_document_maskedstring,nullyesThe prefilled CPF/CNPJ, last four characters only.
payer_prefilledarray of "name" | "contact" | "external_reference" | "document" | "address"yesWhich payer fields were prefilled at create. Their values are never returned.
published_atstring,nullyes—
receiverobjectyesThe name the payer sees on the hosted page: the consumer's display name, else the organization's name. The same text the public read answers.
state"draft" | "published" | "paused" | "archived"yes—
updated_atstringyes—
urlstringyesThe hosted page for this link.
valid_untilstring,nullyes—
versionobject,nullyesThe published version in force.
Example request
curl -X POST https://api.codespar.dev/v1/collect/links/{linkId}/resume \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
POST /v1/collect/links/{linkId}/resume HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.post(
    "https://api.codespar.dev/v1/collect/links/{linkId}/resume",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/links/{linkId}/resume", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const r = await cs.api.response("post", "/v1/collect/links/{linkId}/resume", {
  path: {
    linkId: "link_0000000000000000"
  }
});
// r.status is one of the documented statuses (200, 422),
// each with its own body shape in r.data; nothing here throws on 422.
if (r.ok) {
  console.log(r.data);
}
Example response 200
application/json
{
  "id": "obj_0000000000000000",
  "object": "collect_link",
  "state": "draft",
  "environment": "live",
  "consumer_id": "csm_0000000000000000",
  "receiver": {
    "name": "Example"
  },
  "paid": true,
  "paid_at": "string",
  "current_version": 0,
  "valid_until": "string",
  "url": "https://example.com/hook",
  "payer_prefilled": [
    "name"
  ],
  "payer_document_masked": "string",
  "version": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "draft": {
    "version": 0,
    "status": "draft",
    "title": "Example",
    "description": "string",
    "success_message": "string",
    "items": [
      {
        "name": "Example",
        "quantity": 0,
        "unit_amount_minor": 1000
      }
    ],
    "total_minor": 1,
    "currency": "BRL",
    "brand": {},
    "surfaces": [
      "page"
    ],
    "due_in_days": 0,
    "payer_fields": {
      "name": "required",
      "contact": "required",
      "external_reference": "required"
    },
    "usdc_price": "string",
    "usdc_price_atomic": "string",
    "usdc_price_confirmed_at": "string",
    "created_at": "string",
    "published_at": "string"
  },
  "created_at": "string",
  "updated_at": "string",
  "published_at": "string",
  "paused_at": "string",
  "archived_at": "string",
  "agent": {
    "url": "https://example.com/hook",
    "status": "ready",
    "reason": "string",
    "challenge": {},
    "refusal": {
      "code": "string",
      "message": "string",
      "http_status": 0
    },
    "usdc": {
      "price": "string",
      "amount": "1000",
      "currency": "USDC",
      "network": "string",
      "asset": "string",
      "payable": false,
      "reason": "usdc_pay_to_unavailable",
      "message": "string",
      "statement": "string"
    }
  },
  "changed": true
}

POST /v1/collect/payments/{paymentId}/honor

POSThttps://api.codespar.dev/v1/collect/payments/{paymentId}/honor

Keep a late payment instead of refunding it

The collector confirms they honor a LATE payment, before its decide_by. Idempotent: honoring an honored refund answers it again. A duplicate cannot be honored, and a late payment past its window is already due for refund.

Path parameters

NameTypeRequiredDescription
paymentIdstringyes—

Responses

StatusBodyDescription
200objectOK
404objectNo payment with a refund decision under that id in this project.
409objectNot honorable.

Response 200

FieldTypeRequiredDescription
amount_minorintegeryes—
charge_idstringyes—
created_atstringyes—
currency"BRL"yes—
decide_bystring,nullyes—
decided_atstring,nullyes—
idstringyes—
link_idstringyes—
object"collect_refund"yes—
payment_idstringyes—
reason"late" | "duplicate"yes—
refund_method"pix" | "manual"yespix when the payment was a Pix; manual when it was a boleto or the channel is unknown.
state"awaiting_collector" | "honored" | "awaiting_pix_rail" | "manual_refund_required"yesawaiting_collector: a late payment the collector may honor until decide_by. honored: kept by the collector. awaiting_pix_rail: due for refund by Pix, waiting for the Pix refund of Collect charges, which is not wired yet; no money has moved. manual_refund_required: due for refund and there is no Pix to return, so a person refunds it outside CodeSpar.
Example request
curl -X POST https://api.codespar.dev/v1/collect/payments/{paymentId}/honor \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
POST /v1/collect/payments/{paymentId}/honor HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.post(
    "https://api.codespar.dev/v1/collect/payments/{paymentId}/honor",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/payments/{paymentId}/honor", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.post("/v1/collect/payments/{paymentId}/honor", {
  path: {
    paymentId: "payment_0000000000000000"
  }
});
Example response 200
application/json
{
  "id": "obj_0000000000000000",
  "object": "collect_refund",
  "payment_id": "payment_0000000000000000",
  "link_id": "link_0000000000000000",
  "charge_id": "charge_0000000000000000",
  "reason": "late",
  "refund_method": "pix",
  "state": "awaiting_collector",
  "amount_minor": 1000,
  "currency": "BRL",
  "decide_by": "string",
  "decided_at": "string",
  "created_at": "string"
}

GET /v1/collect/receivers

GEThttps://api.codespar.dev/v1/collect/receivers

The consumers that could receive a Collect charge in this project

The accounts a link may name as consumer_id, each decided by the publish gate's own rule in this project's environment: the consumer's own active Celcoin receiving identity (identity: own), or, in a test project only, the deployment's shared-sandbox receiver (identity: shared_sandbox). An ineligible consumer carries reason: receiving_identity_missing, the code a publish would answer.

The candidates are the consumers this project already knows: an active directed-pay wallet in the project, a Pix (Celcoin) funding source attached to it, or one of its Collect links. At most 200, by consumer id.

Responses

StatusBodyDescription
200objectOK
400objectBad Request.

Response 200

FieldTypeRequiredDescription
dataarray of objectyes—
environment"live" | "test"yesThe environment eligibility was decided for: this project's.
object"list"yes—
Example request
curl -X GET https://api.codespar.dev/v1/collect/receivers \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
GET /v1/collect/receivers HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.get(
    "https://api.codespar.dev/v1/collect/receivers",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/receivers", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.get("/v1/collect/receivers");
Example response 200
application/json
{
  "object": "list",
  "environment": "live",
  "data": [
    {
      "consumer_id": "csm_0000000000000000",
      "label": "Example",
      "eligible": true,
      "identity": "own",
      "reason": "receiving_identity_missing"
    }
  ]
}

GET /v1/collect/{linkId}

GEThttps://api.codespar.dev/v1/collect/{linkId}
No credential

The hosted page's read of a Collect link (public)

No credential: the link id is the only thing the payer holds. Returns what a payer needs to pay and nothing else: the receiver's display name, items and total, brand, state, which payer fields the page must ask for (payer_form; a prefilled field reads prefilled and its value is never returned), the current attempt (its copia-e-cola only once open) and, once paid, the payment with its signed receipt. environment (live or test) is the link's: a test link moves no real money, and the page says so only when this field does. Rate limited per client IP and per link. A draft link answers 404; an archived, unpaid one 410.

Path parameters

NameTypeRequiredDescription
linkIdstringyes—

Responses

StatusBodyDescription
200objectOK
400objectThe id is not a collect link id (cl_ + 22 characters).
404objectNo published link with that id.
410objectThe owner withdrew the link.
429objectToo Many Requests. Per client IP and per link, shared by every API replica; Retry-After and details.retry_after give the wait, details.scope names which bucket refused.
Example request
curl -X GET https://api.codespar.dev/v1/collect/{linkId} \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
GET /v1/collect/{linkId} HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.get(
    "https://api.codespar.dev/v1/collect/{linkId}",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/{linkId}", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.get("/v1/collect/{linkId}", {
  path: {
    linkId: "link_0000000000000000"
  }
});

POST /v1/collect/{linkId}/attempts

POSThttps://api.codespar.dev/v1/collect/{linkId}/attempts
No credential

Ask a Collect link for a payable Pix (public)

The hosted page's POST. No credential. The body is strict: page_session (the page's idempotency key: the same session answers the same attempt, 200 with replay: true), the payer fields the page collected (never a field the charger prefilled), and renew. There is no amount field: the charge carries the published version's total. Payer data goes in this body only, never in a URL. Rate limited per client IP and per link, more tightly than the read, because every new attempt is a charge at the issuer.

Path parameters

NameTypeRequiredDescription
linkIdstringyes—

Request body

FieldTypeRequiredDescription
page_sessionstringyes—
payerobjectno—
renewbooleanno—

Responses

StatusBodyDescription
200objectOK
201objectOK
400objectBad Request.
404objectNo published link with that id.
409objectConflict.
410objectThe link is past its validity.
422objectThe issuer refused the charge before it existed.
429objectToo Many Requests. Per client IP and per link, shared by every API replica; Retry-After and details.retry_after give the wait, details.scope names which bucket refused.
503objectThe rate-limit store could not answer, and this route fails closed because its limit bounds charges created at the issuer. Retry-After gives the wait.

Response 200

FieldTypeRequiredDescription
amount_minorintegeryes—
copy_pastestring,nullyesThe Pix copia-e-cola. Null until the attempt is open: it does not exist before the issuer registers it.
currency"BRL"yes—
due_datestringyes—
expires_atstringyes—
failure_codestring,nullno—
idstringyes—
ready_atstring,nullyes—
replaytrueyes—
retry_afterintegernoWhile issuing: seconds until the next readiness check.
state"issuing" | "open" | "superseded" | "expired" | "cancelled" | "paid" | "failed"yes—
surface"page" | "whatsapp"yes—
Example request
curl -X POST https://api.codespar.dev/v1/collect/{linkId}/attempts \
  -H "Authorization: Bearer $CODESPAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "page_session": "string",
       "payer": {},
       "renew": false
     }'
POST /v1/collect/{linkId}/attempts HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
Content-Type: application/json

{
  "page_session": "string",
  "payer": {},
  "renew": false
}
import os
import requests

res = requests.post(
    "https://api.codespar.dev/v1/collect/{linkId}/attempts",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
    json={
      "page_session": "string",
      "payer": {},
      "renew": False
    },
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/v1/collect/{linkId}/attempts", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "page_session": "string",
    "payer": {},
    "renew": false
  }),
});

const data = await res.json();
const r = await cs.api.response("post", "/v1/collect/{linkId}/attempts", {
  path: {
    linkId: "link_0000000000000000"
  },
  body: {
    page_session: "string",
    payer: {},
    renew: false
  }
});
// r.status is one of the documented statuses (200, 422),
// each with its own body shape in r.data; nothing here throws on 422.
if (r.ok) {
  console.log(r.data);
}
Example response 200
application/json
{
  "id": "obj_0000000000000000",
  "state": "issuing",
  "surface": "page",
  "amount_minor": 1000,
  "currency": "BRL",
  "due_date": "string",
  "expires_at": "string",
  "copy_paste": "string",
  "ready_at": "string",
  "retry_after": 0,
  "failure_code": "string",
  "replay": true
}
Collect | CodeSpar