openapi: 3.0.0 info: title: Goodstack Services Activities Donations API version: v1 x-logo: url: https://docs.goodstack.io/img/logo.png altText: Goodstack logo x-dark-logo: url: https://docs.goodstack.io/img/icons/Logo-white.svg altText: Goodstack logo contact: email: engineering-support@goodstack.io name: Api support description: "# Introduction\n\nGoodstack API allows you to build good into your product by facilitating charitable donations. We achieve this through the API's listed and specified in this documentation.\n\nFor all donations using the Goodstack API, Goodstack handles the vetting and validation of the good causes and onward the disbursement of the donation.\n\nThe Goodstack API is organised around REST. All API responses, including errors, return JSON and use standard HTTP response codes. In all API requests you must specify the content-type HTTP header as application/json. All API requests must be made over HTTPS.\n\n# Authentication\n\nAuthenticate your API requests by setting your live secret API key in the Authorization header.\n\nTwo keys are provided to you, a publishable key prefixed with `pk_` and a secret key prefixed with `sk_`.\n\nPublishable API keys are meant solely to identify your goodstack account. These can safely be published in places like your JavaScript code, or in an Android or iPhone app and are meant for usage with our SDKs.\n\nSecret API keys should be kept confidential and only used in secure server environments.\n\nAnywhere that accepts a Publishable key will also accept a Secret key, but routes marked to accept a Secret key will not accept a Publishable key.\n\n# Formats\n\n## Dates\n\nDates are encoded as strings following the ISO 8601 standard `2021-08-01T12:00:00.000Z`.\n\n## Pagination\n\nA maximum of 100 objects can be returned per request and the limit can be specified by using the pageSize query parameter. By default, the pageSize is set to 25.\n\n## Metadata\n\nSome objects have a metadata parameter that you can use to store key-value data.\n\nYou can specify up to 20 keys, with key names up to 40 characters long and values up to 250 characters long.\n\n## Errors\n\nThe API returns standard HTTP response codes to indicate success or failure of API requests. Errors may include a custom error message.\nError objects have these attributes, an `id`, a `message` corresponding to the HTTP response phrase of the error,\nan optional `invalid-params` attribute detailing issues with the request.\n\nAn example error object returned from the API:\n```json\n{\n error: {\n code: 'bad_request',\n title: 'Bad request',\n message: 'Something is wrong with your request, please check any parameters and try again',\n reasons: ['amount is a required field']\n }\n}\n```\n\nA summary of the HTTP status codes returned from the api is listed in the table below.\n\n| Code | Title | Description |\n| ------------- |-------------| -----|\n| 200 | Success | Request successful |\n| 204 | No Content | Request successful with no content returned |\n| 400 | Bad Request | Request was invalid |\n| 401 | Unauthorised | Authorization header is invalid |\n| 403 | Forbidden | Insufficient permissions |\n| 404 | Not Found | Resource does not exist |\n| 429 | Too Many Requests | Rate Limited |\n| 500s | Internal Server Error | Something went wrong with the Goodstack API |\n\n# Retry recommendations\n\nAlthough rare, network requests may fail due to their inherent unreliability. To ensure a robust integration with Goodstack we recommend that you implement a retry mechanism, so that if a network request fails you are able to retry the request.\nGoodstacks API supports idempotency for safely retrying requests through usage of idempotency keys.\n\nFor some POST endpoints we allow clients to specify an idempotency key in the Idempotency-Key header. This allows the client to retry requests without accidentally performing the same operation twice.\n\nIf the same idempotency key is used for multiple requests, only the first successful request will be actioned and subsequent calls will return the result of the first request. Failed requests may be retried with the same idempotency key.\n\nRequests with the same idempotency key and different payload will fail.\n\nThe idempotency key expires after 21 days. After this time, a new request with the same idempotency key will be treated as a new request.\n\n# Webhooks\n\nUse webhooks to subscribe to updates on particular events that occur in Goodstack. Each time an event that you have subscribed to occurs, Goodstack submits a POST request to the designated webhook URL with information about the event.\n\nTo receive webhook notifications, use the [webhook subscriptions API](list-webhook-subscriptions).\n\n## Attributes\n\nAt the top level Webhook payloads will contain `object` and `data` fields. The data record contains the following fields:\n\n| Parameter | Type | Description |\n| ------------- |-------------| -----|\n| id | string | Id of the event |\n| createdAt | string | Timestamp of when the event was created |\n| eventType | string | The type of the event e.g. `validation_request.approved` |\n| eventData | record | Data associated with the event |\n\n## Webhook notifications\n\nThe full list of IP addresses that webhook notifications may come from.\n\nProduction environment:\n\n```\n54.76.67.168\n34.248.188.89\n34.243.152.218\n```\n\nSandbox environment:\n\n```\n54.76.168.240\n99.81.243.145\n54.220.118.167\n```\n\n## Webhook responses\n\nTo acknowledge receipt of a webhook notification, your endpoint must return a 2xx HTTP status code.\n\nIf the webhook is not received successfully then Goodstack will resend the webhook 4 times over the next 14 hours with increasing delays between retries.\n\nThe id of the event can be used to uniquely identify the event. We recommend making the processing of these events idempotent. While rare it is possible for multiple webhooks to be sent for the same event.\n\n## Verifying webhooks\n\nTo verify that the webhook payload is sent from Goodstack, a header `Goodstack-Signature` is included in the request, this signature is generated using HMAC with SHA-256 hashing algorithm and Hex encoded. The webhook subscription secret is used as the key.\n\nYou can compute this signature using HMAC with the SHA-256 hash function, using the webhook subscription secret as the key, and the request body as the message. You can then check that the `Goodstack-Signature` value matches the computed value, verifying that the webhook was sent from Goodstack.\n\n## Validation Request events\n\n| Event | Description |\n| ------------- |-------------|\n| validation_request.approved | Validation request was approved |\n| validation_request.rejected | Validation request was rejected |\n\n```json\n{\n \"object\": \"event\",\n \"data\": {\n \"id\": \"event_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"eventType\": \"validation_request.approved\",\n \"createdAt\": \"2021-08-01T12:00:00.000Z\",\n \"eventData\": {\n \"id\": \"validationrequest_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"organisationId\": \"organisation_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"organisationTypes\": [\"nonprofit\", \"social_impact\"],\n \"name\": \"example charity\",\n \"registryName\": \"National Charities Registry\",\n \"registryId\": \"I34324\",\n \"email\": \"example@example.com\",\n \"addressLine1\": \"example street 15\",\n \"addressLine2\": null,\n \"city\": \"Katowice\",\n \"postal\": \"44-100\",\n \"state\": \"Silesia\",\n \"website\": \"https://example.com\",\n \"countryCode\": \"POL\",\n \"createdAt\": \"2021-08-01T12:00:00.000Z\",\n \"deletedAt\": null,\n \"acceptedAt\": \"2021-08-01T12:00:00.000Z\",\n \"rejectedAt\": null,\n \"(deprecated) rejectionReason\": null,\n \"rejectionReasonCode\": null\n }\n }\n}\n```\n## Agent Verification events\n\n| Event | Description |\n| ------------- |-------------|\n| agent_verification.pending_user_verification | Agent has passed Goodstack review, and is awaiting email verification. |\n| agent_verification.pending_review | Agent has passed email verification and is awaiting Goodstack review. |\n| agent_verification.approved | Agent verification was approved. |\n| agent_verification.rejected | Agent verification was rejected. |\n\n```json\n{\n \"object\": \"event\",\n \"data\": {\n \"id\": \"event_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"eventType\": \"agent_verification.approved\",\n \"createdAt\": \"2021-08-01T12:00:00.000Z\",\n \"eventData\": {\n \"id\": \"agentverification_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"firstName\": \"Max\",\n \"lastName\": \"Plank\",\n \"organisationId\": \"organisation_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"email\": \"example@example.com\",\n \"language\": \"en-GB\",\n \"validationRequestId\": \"validationRequest_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"title\": \"Board Member\",\n \"(deprecated) rejectionReason\": \"Identity check failed\",\n \"rejectionReasonCode\": \"user_failed_percent_review\",\n \"metadata\": {},\n \"createdAt\": \"2021-08-01T12:00:00.000Z\",\n \"status\": \"approved\"\n }\n }\n}\n```\n## Monitoring Subscription events\n\n| Event | Description |\n| ------------- |-------------|\n| monitoring_subscription.updated | Monitoring Subscription was updated. |\n\n```json\n{\n \"object\": \"event\",\n \"data\": {\n \"id\": \"event_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"eventType\": \"monitoring_subscription.updated\",\n \"createdAt\": \"2021-08-07T11:00:00.000Z\",\n \"eventData\": {\n \"id\": \"monitoringsubscription_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"organisationId\": \"organisation_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"validationRequestId\": null,\n \"status\": \"live\",\n \"createdAt\": \"2021-08-02T11:00:00.000Z\",\n \"results\": {\n \"complianceStatus\": \"fail\",\n \"warning\": { \"status\": \"clear\" },\n \"sanction\": { \"status\": \"flag\" },\n \"hateSpeech\": { \"status\": \"clear\" },\n \"commercial\": { \"status\": \"clear\" },\n \"adverseMedia\": { \"status\": \"clear\" },\n \"controversial\": { \"status\": \"flag\" },\n \"registration\": { \"active\": \"yes\" }\n }\n }\n }\n}\n```\n## Eligibility Subscription events\n\n| Event | Description |\n| ------------- |-------------|\n| eligibility_subscription.updated | Eligibility Subscription was updated. |\n\n```json\n{\n \"object\": \"event\",\n \"data\": {\n \"id\": \"event_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"eventType\": \"eligibility_subscription.updated\",\n \"createdAt\": \"2021-08-07T11:00:00.000Z\",\n \"eventData\": {\n \"id\": \"eligibilitysubscription_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"organisationId\": \"organisation_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"validationRequestId\": null,\n \"status\": \"live\",\n \"suggestedActivitySubTags\": [\n {\n \"id\": \"activitysubtag_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"name\": \"Primary School\"\n \"description\": \"Includes all primary schools\",\n \"tag\": {\n \"id\": \"activitytag_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"name\": \"Educational\"\n \"description\": \"Includes all educational institutions\"\n }\n }\n ]\n \"createdAt\": \"2021-08-02T11:00:00.000Z\",\n \"updatedAt\": \"2021-08-02T11:00:00.000Z\",\n \"results\": {\n \"eligibilityStatus\": \"fail\",\n \"confirmedActivitySubTags\": [\n {\n \"id\": \"activitysubtag_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"name\": \"Primary School\"\n \"description\": \"Includes all primary schools\",\n \"tag\": {\n \"id\": \"activitytag_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"name\": \"Educational\"\n \"description\": \"Includes all educational institutions\"\n }\n }\n ],\n \"rejectedActivitySubTags\": [\n {\n \"id\": \"activitysubtag_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"name\": \"Primary School\"\n \"description\": \"Includes all primary schools\",\n \"tag\": {\n \"id\": \"activitytag_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"name\": \"Educational\"\n \"description\": \"Includes all educational institutions\"\n }\n }\n ]\n }\n }\n }\n}\n```\n## Validation Submission events\n\n| Event | Description |\n| ------------- |-------------|\n| validation_submission.created | Validation Submission was created. |\n| validation_submission.succeeded | Validation Submission has passed all checks |\n| validation_submission.failed | Validation Submission has failed |\n| validation_submission.updated | Validation Submission status has updated |\n\n\n```json\n{\n \"object\": \"event\",\n \"data\": {\n \"id\": \"event_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"eventType\": \"validation_submission.created\",\n \"createdAt\": \"2021-08-07T11:00:00.000Z\",\n \"eventData\": {\n \"id\": \"validationsubmission_xxxxx\",\n \"agentVerificationId\": \"agentverification_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"agentVerification\": {\n \"id\": \"agentverification_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"firstName\": \"Max\",\n \"lastName\": \"Plank\",\n \"email\": \"example@example.com\",\n \"(deprecated) rejectionReason\": null,\n \"rejectionReasonCode\": null,\n \"status\": \"pending\"\n },\n \"createdAt\": \"2021-08-02T11:00:00.000Z\",\n \"eligibilitySubscriptionId\": \"eligibilitysubscription_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"monitoringSubscriptionId\": \"monitoringsubscription_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"organisationId\": \"organisation_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"partnerFields\": {},\n \"validationSubmissionHostedConfigurationId\": \"hostedconfiguration_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"metadata\": {},\n \"status\": \"pending\",\n \"validationInviteId\": \"validationinvite_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"validationRequestId\": \"validationrequest_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"validationRequest\": {\n \"id\": \"validationrequest_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"name\": \"Charity\",\n \"acceptedAt\": null,\n \"rejectedAt\": null,\n \"organisationTypes\": []\n }\n }\n }\n}\n```\n\nN.B. Please be aware that the \"Validation Submission Failure\" event consists of a property named failureReasons. In the given example, we have included all possible reasons that may be encountered. It is important to note that only one of these reasons will be received when encountering this event.\n\n```json\n{\n \"object\": \"event\",\n \"data\": {\n \"id\": \"event_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"eventType\": \"validation_submission.failed\",\n \"createdAt\": \"2021-08-07T11:00:00.000Z\",\n \"eventData\": {\n \"id\": \"validationsubmission_xxxxx\",\n \"agentVerificationId\": \"agentverification_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"agentVerification\": {\n \"id\": \"agentverification_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"firstName\": \"Max\",\n \"lastName\": \"Plank\",\n \"email\": \"example@example.com\",\n \"(deprecated) rejectionReason\": \"Other\",\n \"rejectionReasonCode\": \"other\",\n \"status\": \"rejected\"\n },\n \"createdAt\": \"2021-08-02T11:00:00.000Z\",\n \"eligibilitySubscriptionId\": \"eligibilitysubscription_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"monitoringSubscriptionId\": \"monitoringsubscription_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"organisationId\": \"organisation_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"partnerFields\": {},\n \"validationSubmissionHostedConfigurationId\": \"hostedconfiguration_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"metadata\": {},\n \"status\": \"failed\",\n \"validationInviteId\": \"validationinvite_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"validationRequestId\": \"validationrequest_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"validationRequest\": {\n \"id\": \"validationrequest_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"name\": \"Charity\",\n \"acceptedAt\": \"2021-08-01T12:00:00.000Z\",\n \"rejectedAt\": null,\n \"organisationTypes\": [\"nonprofit\"]\n },\n \"failureReasons\": [\n {\n \"check\": \"validation_request\",\n \"reason\": {\n \"rejectionReasonCode\": \"other\"\n }\n },\n {\n \"check\": \"agent_verification\",\n \"reason\": {\n \"rejectionReasonCode\": \"fake_email_used\"\n }\n },\n {\n \"check\": \"compliance\",\n \"reason\": {\n \"results\": {\n \"complianceStatus\": \"fail\",\n \"warning\": {\n \"status\": \"flag\"\n },\n \"sanction\": {\n \"status\": \"flag\"\n },\n \"hateSpeech\": {\n \"status\": \"flag\"\n },\n \"commercial\": {\n \"status\": \"flag\"\n },\n \"adverseMedia\": {\n \"status\": \"flag\"\n },\n \"controversial\": {\n \"status\": \"flag\"\n },\n \"registration\": {\n \"active\": \"yes\"\n }\n }\n }\n },\n {\n \"check\": \"eligibility\",\n \"reason\": {\n \"status\": \"cannot_define_eligibility\",\n \"results\": {\n \"eligibilityStatus\": null,\n \"confirmedActivitySubTags\": null,\n \"rejectedActivitySubTags\": null\n }\n }\n },\n {\n \"check\": \"eligibility\",\n \"reason\": {\n \"status\": \"live\",\n \"results\": {\n \"eligibilityStatus\": \"fail\",\n \"confirmedActivitySubTags\": [{\n \"id\": \"tag1\",\n \"name\": \"Tag 1\",\n \"tag\": {\n \"id\": \"tag1\",\n \"name\": \"Tag 1\",\n \"description\": \"Tag description\"\n },\n \"description\": \"Sub tag description\"\n }],\n \"rejectedActivitySubTags\": [{\n \"id\": \"tag1\",\n \"name\": \"Tag 1\",\n \"tag\": {\n \"id\": \"tag1\",\n \"name\": \"Tag 1\",\n \"description\": \"Tag description\"\n },\n \"description\": \"Sub tag description\"\n }]\n }\n }\n }\n ]\n }\n }\n}\n```\n\n## Donation events\n\nPII fields (`firstName`, `lastName` & `email`) will be included or excluded depending on your partner settings.\n\n| Event | Description |\n| ------------- |-------------|\n| donation.hosted.payment_received | Payment has been received from the user for a hosted donation. |\n\n```json\n{\n \"object\": \"event\",\n \"data\": {\n \"id\": \"event_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"eventType\": \"donation.hosted.payment_received\",\n \"createdAt\": \"2021-08-07T11:00:30.000Z\",\n \"eventData\": {\n \"id\": \"donation_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"userId\": \"user_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"organisationId\": \"organisation_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"type\": \"hosted\",\n \"hosted\": {\n \"sessionId\": \"donationsession_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"\n },\n \"amount\": 10000,\n \"currencyCode\": \"AUD\",\n \"status\": \"RECEIVED_PAYMENT\",\n \"firstName\": \"Julia\",\n \"lastName\": \"Russell\",\n \"email\": \"example@example.com\",\n \"consentedToBeContactedByOrg\": \"yes\",\n \"anonymous\": \"no\",\n \"giftAidId\": null,\n \"cancelledAt\": null,\n \"createdAt\": \"2021-08-07T11:00:00.000Z\",\n \"metadata\": {\n \"username\": \"jr123\"\n },\n \"subscription\": {\n \"initial\": true\n }\n }\n }\n}\n```\n| Event | Description |\n| ----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| donation.created | A new donation record has been successfully created in the system. |\n| donation.payment_successful | The payment for the donation has been successfully completed and verified. |\n| donation.settled | The donated funds have been received and reconciled by the partner foundation. |\n| donation.disbursed | The donated funds have been transferred to the intended nonprofit. |\n| donation.cancelled | The donation process has been terminated, either by the donor or due to system issues. |\n| donation.reassigned | The donation has been reassigned to another organisation, either because it has failed compliance, we are unable to pay the organisation or the organisation has been merged with another id. |\n\n```json\n{\n \"object\": \"event\",\n \"data\": {\n \"id\": \"event_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"eventType\": \"donation.payment_successful\",\n \"createdAt\": \"2021-08-07T11:00:30.000Z\",\n \"eventData\": {\n \"id\": \"donation_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"userId\": \"user_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"organisationId\": \"organisation_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"type\": \"direct\",\n \"amount\": { \"amount\": 10, \"currency\": \"GBP\" },\n \"status\": \"ACTIVE\",\n \"firstName\": \"Julia\",\n \"lastName\": \"Russell\",\n \"email\": \"example@example.com\",\n \"consentedToBeContacted\": \"yes\",\n \"anonymous\": \"no\",\n \"giftAidId\": \"giftaid_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"createdAt\": \"2021-08-07T11:00:00.000Z\",\n \"cancelledAt\": null,\n \"donationRequestId\": \"donationrequest_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"donationRequestAmount\": { \"amount\": 10, \"currency\": \"GBP\" },\n \"accountId\": \"account_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n \"metadata\": {\"data\": \"hash-value\"},\n \"settledAmount\": { amount: 10, currency: \"GBP\" },\n \"settledAt\": \"2021-08-07T11:00:00.000Z\",\n \"disbursedAt\": \"2021-08-07T11:00:00.000Z\",\n \"reassignedAt\": \"2021-08-07T11:00:00.000Z\",\n \"reassignedFromOrganisationId\": \"organisation_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n }\n }\n}\n```\n" servers: - url: https://api.goodstack.io description: Production server - url: https://sandbox-api.goodstack.io description: Sandbox server tags: - name: Donations description: 'A Donation object tracks the lifecycle of a Donation from creation and payment to disbursement to the nonprofit. Donations can be created during a Donation Session by the Hosted Donation Gateway or created directly by calling the [Create A Donation API](create-a-donation). ' paths: /v1/donations: get: security: - SecretApiKey: [] summary: List Donations description: 'Retrieve a list of donations. PII fields (`firstName`, `lastName` & `email`) will be included or excluded depending on your partner settings. ' tags: - Donations parameters: - in: query name: userId schema: type: string example: user_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx required: false description: Filter results by userId. - in: query name: status schema: type: string enum: - ACTIVE - REQUESTED_PAYMENT - RECEIVED_PAYMENT - DISBURSED - CANCELLED required: false description: Filter results by status. - in: query name: startDate schema: type: string format: date-time description: Start date to retrieve users donations from. example: '2020-10-13T17:46:54.000Z' - in: query name: endDate schema: type: string format: date-time description: End date to retrieve users donations from. example: '2020-10-13T17:46:54.000Z' - in: query name: organisationId schema: type: string example: organisation_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx required: false description: Filter results by organisationId. - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/pageSize' responses: '200': description: Successfully listed Donations content: application/json: schema: type: object properties: data: type: array items: anyOf: - $ref: '#/components/schemas/DonationDirect' - $ref: '#/components/schemas/DonationHosted' object: type: string example: donation totalResults: type: integer example: 33 pageSize: type: integer example: 25 _links: $ref: '#/components/schemas/CursorLinks' '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: IncorrectParams: $ref: '#/components/examples/IncorrectParams' CursorError: $ref: '#/components/examples/Pagination.CursorError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ForbiddenScope' post: security: - SecretApiKey: [] summary: Create a donation description: 'Creates a new Donation of type `direct`. We will request payment from you for the Donations aggregated over a period. Goodstack and our associated foundations will then handle the ongoing safe and efficient disbursement of funds to the nonprofit. Please note that if you are creating with a `userId` and no `organisationId` the user must be already [supporting an organisation](#operation/SupportOrganisation). ' parameters: - in: header name: Idempotency-Key schema: type: string required: false description: Idempotency key. tags: - Donations requestBody: required: true content: application/json: schema: oneOf: - type: object title: DirectDonation with Organisation ID properties: amount: description: Amount to be donated. A positive integer representing how much to donate in the smallest currency unit, for example 100 pence to donate £1.00. type: integer example: 120 currencyCode: description: Three-letter ISO currency code. Only currency codes supported by our foundations will be accepted. type: string example: GBP organisationId: type: string firstName: type: string maxLength: 255 lastName: type: string maxLength: 255 email: type: string maxLength: 255 consentedToBeContactedByOrg: type: string enum: - 'yes' - 'no' anonymous: type: string enum: - 'yes' - 'no' metadata: type: object description: '[Key-value data](/#section/Formats/Metadata) that you can attach to a Donation. ' example: key1: value1 key2: value2 required: - amount - currencyCode - organisationId - type: object title: DirectDonation with User ID properties: amount: type: integer example: 120 currencyCode: description: Three-letter ISO currency code. type: string example: GBP userId: type: string example: user_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx organisationId: type: string firstName: type: string maxLength: 255 lastName: type: string maxLength: 255 email: type: string maxLength: 255 consentedToBeContactedByOrg: type: string enum: - 'yes' - 'no' anonymous: type: string enum: - 'yes' - 'no' metadata: type: object description: '[Key-value data](/#section/Formats/Metadata) that you can attach to a Donation. ' example: key1: value1 key2: value2 required: - amount - currencyCode - userId responses: '200': description: Successfully created a Donation content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/DonationDirect' object: type: string example: donation '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: IncorrectParams: $ref: '#/components/examples/IncorrectParams' UserNotFound: $ref: '#/components/examples/Donations.UserNotFound' MissingOrganisation: $ref: '#/components/examples/Donations.MissingOrganisation' WrongTargetCurrency: $ref: '#/components/examples/Donations.WrongTargetCurrency' WrongPartnerCurrency: $ref: '#/components/examples/Donations.WrongPartnerCurrency' CannotAcceptDonations: $ref: '#/components/examples/Donations.CannotAcceptDonations' GiftAidMissing: $ref: '#/components/examples/Donations.GiftAidMissing' OriginalCallInProgress: $ref: '#/components/examples/Idempotency.OriginalCallInProgress' SameKeyDifferentData: $ref: '#/components/examples/Idempotency.SameKeyDifferentData' KeyInUse: $ref: '#/components/examples/Idempotency.KeyInUse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ForbiddenScope' /v1/donations/{id}: parameters: - in: path name: id schema: type: integer required: true description: Id of the Donation. get: security: - SecretApiKey: [] summary: Retrieve a Donation description: 'Retrieve a donation by its ID. PII fields (`firstName`, `lastName` & `email`) will be included or excluded depending on your partner settings. ' tags: - Donations responses: '200': description: Successfully retrieves a Donation content: application/json: schema: type: object properties: data: oneOf: - $ref: '#/components/schemas/DonationDirect' - $ref: '#/components/schemas/DonationHosted' object: type: string example: donation '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ForbiddenScope' '404': $ref: '#/components/responses/NotFound' patch: security: - SecretApiKey: [] summary: Edit a Donation description: 'Update the recipient organisation, metadata of a Donation. The recipient organisation can only be changed for `direct` type Donations created directly through the [Create A Donation API](./create-a-donation) that are in an `ACTIVE` status. ' tags: - Donations requestBody: required: true content: application/json: schema: type: object properties: organisationId: type: string metadata: type: object description: '[Key-value data](/#section/Formats/Metadata) that you can attach to a Donation. ' example: key1: value1 key2: value2 responses: '200': description: Successfully edited a particular donation content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/DonationDirect' object: type: string example: donation '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: IncorrectParams: $ref: '#/components/examples/IncorrectParams' InvalidState: $ref: '#/components/examples/Donations.InvalidState' InvalidMetadata: $ref: '#/components/examples/Donations.InvalidMetadata' InvalidTypeForEditOrganisation: $ref: '#/components/examples/Donations.InvalidTypeForEditOrganisation' MissingOrganisation: $ref: '#/components/examples/Donations.MissingOrganisation' WrongTargetCurrency: $ref: '#/components/examples/Donations.WrongTargetCurrency' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ForbiddenScope' /v1/donations/{id}/cancel: parameters: - in: path name: id schema: type: integer required: true description: Id of the Donation to cancel. post: security: - SecretApiKey: [] summary: Cancel a Donation description: 'Applicable only to `direct` type Donations created directly through the [Create A Donation API](./create-a-donation). ' tags: - Donations responses: '200': description: Successfully cancelled a Donation content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/DonationDirect' object: type: string example: donation '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: InvalidState: $ref: '#/components/examples/Donations.InvalidState' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ForbiddenScope' components: examples: Donations.GiftAidMissing: summary: Donation - GiftAid missing description: Can not find required gift aid for this donation value: error: code: donation/gift_aid_missing title: Bad request message: Can not find required gift aid for this donation Donations.InvalidTypeForEditOrganisation: summary: Donation - Organisation cannot be updated for this type of donation description: Organisation cannot be updated for this type of donation value: error: code: donation/cannot_edit_organisation_invalid_donation_type title: Bad request message: Organisation cannot be updated for this type of donation IncorrectParams: summary: 400 Incorrect Parameters description: Bad Request - Incorrect parameters value: error: code: bad_request title: Bad request message: One or more of the inputs were invalid reasons: - pageSize must be greater than or equal to 0 Donations.WrongPartnerCurrency: summary: Donation - Wrong partner currency description: You can not accept donations in this currency value: error: code: donation/wrong_partner_currency title: Bad request message: You can only donate in GBP Donations.UserNotFound: summary: Donation - User not found description: User not found value: error: code: donation/user_not_found title: Bad request message: User not found Idempotency.SameKeyDifferentData: summary: Idempotency - Data has changed from previous request description: Data has changed from previous request with this key value: error: code: idempotency/same_key_different_data title: Bad request message: Data has changed from previous request Idempotency.OriginalCallInProgress: summary: Idempotency - Original call in progress description: Original call with this idempotency key is still in progress, please wait and try again value: error: code: idempotency/original_call_in_progress title: Bad request message: Original call with this idempotency key is still in progress Donations.CannotAcceptDonations: summary: Donation - Organisation can not accept donations description: This Organisation can not accept donations at this time value: error: code: donation/cannot_accept_donations title: Bad request message: This organisation is currently unable to accept donations Donations.InvalidMetadata: summary: 400 Bad request description: Metadata provided not correct format value: error: title: Bad request message: Metadata can only contain from 1 up to 20 keys, with key names up to 50 characters long and values up to 500 characters long code: donation/invalid_metadata Donations.WrongTargetCurrency: summary: Donation - Wrong target currency description: The organisation can not accept donations in this currency value: error: code: donation/wrong_target_currency title: Bad request message: This organisation can not accept donations in GBP Idempotency.KeyInUse: summary: Idempotency - Key in use description: Idempotency Key is already in use value: error: code: idempotency/key_already_in_use title: Bad request message: Idempotency Key is already in use Pagination.CursorError: summary: Error in cursor parameter description: We were unable to decode the cursor value: error: code: pagination/cursor_error title: Bad request message: Unable to find the next page Donations.InvalidState: summary: Donation - Invalid state description: Donation is not in a valid state to update value: error: code: donation/invalid_state title: Bad request message: Donation is not in a valid state to update Donations.MissingOrganisation: summary: Donation - Organisation missing description: User must be supporting a cause, or organisationId must be provided value: error: code: donation/missing_organisation title: Bad request message: User must be supporting a cause, or organisationId must be provided schemas: DonationDirect: title: direct donation type: object allOf: - $ref: '#/components/schemas/DonationBase' - type: object properties: type: type: string enum: - direct DonationBase: type: object properties: id: type: string example: donation_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx userId: type: string nullable: true organisationId: type: string nullable: true amount: description: Donation amount. A positive integer representing donation amount in the smallest currency unit, for example 100 pence for a donation of £1.00. type: integer example: 123 currencyCode: description: Three-letter ISO currency code type: string example: AUD createdAt: type: string format: date-time example: '2020-10-13T17:46:54.000Z' status: type: string enum: - ACTIVE - REQUESTED_PAYMENT - RECEIVED_PAYMENT - DISBURSED - CANCELLED firstName: type: string nullable: true description: Users first name. lastName: type: string nullable: true description: Users last name. email: type: string nullable: true description: Users email. consentedToBeContacted: type: string enum: - 'yes' - 'no' nullable: true description: Whether the user consented to be contacted by the benefitting organisation. anonymous: type: string enum: - 'yes' - 'no' nullable: true description: Whether the user wants to share their donation publicly or not. metadata: type: object additionalProperties: type: string nullable: true description: Key-value data that you can attach to an object. giftAidId: type: string nullable: true cancelledAt: type: string format: date-time example: '2020-10-13T17:46:54.000Z' nullable: true donationRequestId: type: string example: donationrequest_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx nullable: true accountId: type: string example: account_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx nullable: true DonationHosted: type: object title: hosted donation allOf: - $ref: '#/components/schemas/DonationBase' - type: object properties: type: type: string enum: - hosted hosted: type: object description: Contains additional fields available for hosted Donations. properties: sessionId: type: string example: donationsession_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx description: Donation Session Id CursorLinks: type: object properties: current: type: string example: https://.../v1/...?cursor=eyJ2Ijox...N3AifQ%3D%3D next: type: string example: https://.../v1/...?cursor=eyJ2Ijox...N3AifQ%3D%3D prev: type: string example: https://.../v1/...?cursor=eyJ2Ijox...N3AifQ%3D%3D Error: type: object properties: error: type: object properties: code: type: string title: type: string message: type: string reasons: nullable: true type: array items: type: string responses: Unauthorized: description: Unauthorized NotFound: description: The specified resource was not found content: application/json: schema: type: object properties: error: type: object properties: code: type: string example: not_found title: type: string example: Resource not found message: type: string example: This endpoint is unavailable or can not be found ForbiddenScope: description: Forbidden (scope) content: application/json: schema: type: object properties: error: type: object properties: code: type: string example: forbidden title: type: string example: Forbidden message: type: string example: Access is denied due to missing scope permissions parameters: pageSize: in: query name: pageSize required: false schema: type: integer minimum: 0 default: 25 description: How many items per page, for pagination. cursor: in: query name: cursor required: false schema: type: string example: eyJ2IjoxLCJkIjoibmV4dCIsImlkIjoiZG9uYXRpb25fMDAwMDAwQnc3U1BhMHBxOHBRMFFsckVaWGFaN3AifQ%3D%3D description: A cursor that points to where to start the page securitySchemes: PublishableApiKey: type: apiKey in: header name: Authorization description: API key starting with 'pk_' that can be made public SecretApiKey: type: apiKey in: header description: API key starting with 'sk_' that must be kept secure name: Authorization DonationSessionToken: type: apiKey in: header name: donation-session-token description: Donation session token x-tagGroups: - name: NONPROFIT DATA tags: - Organisations - Countries - Registries - Categories - name: NONPROFIT VALIDATIONS tags: - Validation Requests - Validation Request Documents - Validation Invites - Validation Submissions - Validation Submission Documents - Validation Submission Configuration - Monitoring Subscriptions - Eligibility Subscriptions - Activities - Agent Verifications - name: MONETARY DONATIONS tags: - Donations - Donation Sessions - Users - Gift Aid - name: WEBHOOK SUBSCRIPTIONS tags: - Webhook Subscriptions